feat(map): 引入任务阶段状态机重构战斗流程
- 新增 MissionPhase 枚举定义任务生命周期各阶段 - 实现 changePhase 方法统一管理阶段切换逻辑与事件触发 - 重构 to_fight、enterPreparePhase 等方法使用状态机驱动 - 调整战斗开始/结束逻辑以适配新的阶段状态 - 启用调试模式便于开发阶段问题排查
This commit is contained in:
@@ -46,6 +46,17 @@ import { Tooltip } from "../skill/Tooltip";
|
||||
import { CardInitCoins } from "../common/config/CardSet";
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/** 任务(关卡)生命周期阶段 */
|
||||
export enum MissionPhase {
|
||||
None = 0, // 未初始化
|
||||
PrepareStart = 1, // 准备开始阶段 (2s)
|
||||
Prepare = 2, // 准备阶段 (等待玩家点击开始)
|
||||
PrepareEnd = 3, // 准备结束阶段 (2s)
|
||||
BattleStart = 4, // 战斗开始阶段 (2s)
|
||||
Battle = 5, // 战斗阶段 (刷怪、战斗中)
|
||||
BattleEnd = 6, // 战斗结束阶段 (2s)
|
||||
Settle = 7 // 结算阶段
|
||||
}
|
||||
|
||||
//@todo 需要关注 当boss死亡的时候的动画播放完成后,需要触发事件,通知 MissionComp 进行奖励处理
|
||||
|
||||
@@ -59,7 +70,7 @@ const { ccclass, property } = _decorator;
|
||||
@ecs.register('MissionComp', false)
|
||||
export class MissionComp extends CCComp {
|
||||
@property({ tooltip: "是否启用调试日志" })
|
||||
private debugMode: boolean = false;
|
||||
private debugMode: boolean = true;
|
||||
@property({ tooltip: "是否显示战斗内存观测面板" })
|
||||
private showMemoryPanel: boolean = false;
|
||||
|
||||
@@ -133,6 +144,8 @@ export class MissionComp extends CCComp {
|
||||
private currentWave: number = 0;
|
||||
/** 上一次发放金币奖励的波数(防止重复发放) */
|
||||
private lastPrepareCoinWave: number = 0;
|
||||
/** 当前任务阶段 */
|
||||
public currentPhase: MissionPhase = MissionPhase.None;
|
||||
|
||||
// ======================== ECS 查询匹配器(预缓存) ========================
|
||||
|
||||
@@ -168,7 +181,7 @@ export class MissionComp extends CCComp {
|
||||
protected update(dt: number): void {
|
||||
if(!smc.mission.play) return
|
||||
if(smc.mission.pause) return
|
||||
if(smc.mission.in_fight){
|
||||
if(this.currentPhase === MissionPhase.Battle){
|
||||
this.syncMonsterSpawnState(dt)
|
||||
if(smc.mission.stop_mon_action) return
|
||||
smc.vmdata.mission_data.fight_time+=dt
|
||||
@@ -235,7 +248,7 @@ export class MissionComp extends CCComp {
|
||||
this.node.active=true
|
||||
this.data_init()
|
||||
oops.message.dispatchEvent(GameEvent.FightReady)
|
||||
this.enterPreparePhase()
|
||||
this.changePhase(MissionPhase.Prepare)
|
||||
let loading=this.node.parent.getChildByName("loading")
|
||||
loading.active=true
|
||||
this.scheduleOnce(()=>{
|
||||
@@ -243,6 +256,89 @@ export class MissionComp extends CCComp {
|
||||
},0.5)
|
||||
}
|
||||
|
||||
/**
|
||||
* 阶段切换核心方法(状态机)
|
||||
* 处理状态流转时所需的事件触发和全局标志位修改。
|
||||
* @param targetPhase 目标阶段
|
||||
*/
|
||||
private changePhase(targetPhase: MissionPhase) {
|
||||
if (this.currentPhase === targetPhase) return;
|
||||
const oldPhase = this.currentPhase;
|
||||
this.currentPhase = targetPhase;
|
||||
|
||||
// 取消状态机内部产生的定时流转任务,防止状态错乱
|
||||
this.unschedule(this.autoNextPhase);
|
||||
|
||||
switch (targetPhase) {
|
||||
case MissionPhase.PrepareStart:
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false;
|
||||
smc.mission.stop_spawn_mon = true;
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||
this.scheduleOnce(this.autoNextPhase, 2);
|
||||
break;
|
||||
|
||||
case MissionPhase.Prepare:
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = true;
|
||||
break;
|
||||
|
||||
case MissionPhase.PrepareEnd:
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||
this.scheduleOnce(this.autoNextPhase, 2);
|
||||
break;
|
||||
|
||||
case MissionPhase.BattleStart:
|
||||
// 触发战斗开始技能(fstart)
|
||||
this.triggerHeroBattleSkills(true);
|
||||
this.scheduleOnce(this.autoNextPhase, 2);
|
||||
break;
|
||||
|
||||
case MissionPhase.Battle:
|
||||
smc.mission.stop_spawn_mon = false;
|
||||
smc.mission.in_fight = true;
|
||||
smc.vmdata.mission_data.in_fight = true;
|
||||
oops.message.dispatchEvent(GameEvent.FightStart);
|
||||
break;
|
||||
|
||||
case MissionPhase.BattleEnd:
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false;
|
||||
smc.mission.stop_spawn_mon = true;
|
||||
// 触发战斗结束技能(fend)
|
||||
this.triggerHeroBattleSkills(false);
|
||||
break;
|
||||
|
||||
case MissionPhase.Settle:
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false;
|
||||
smc.mission.stop_spawn_mon = true;
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||
break;
|
||||
|
||||
case MissionPhase.None:
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false;
|
||||
smc.mission.stop_spawn_mon = false;
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** 自动流转到下一阶段(过渡状态结束时调用) */
|
||||
private autoNextPhase() {
|
||||
switch (this.currentPhase) {
|
||||
case MissionPhase.PrepareStart:
|
||||
this.changePhase(MissionPhase.Prepare);
|
||||
break;
|
||||
case MissionPhase.PrepareEnd:
|
||||
this.changePhase(MissionPhase.BattleStart);
|
||||
break;
|
||||
case MissionPhase.BattleStart:
|
||||
this.changePhase(MissionPhase.Battle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 进入战斗:
|
||||
* - 恢复刷怪
|
||||
@@ -252,12 +348,7 @@ export class MissionComp extends CCComp {
|
||||
* - 触发英雄战斗开始技能
|
||||
*/
|
||||
to_fight(){
|
||||
smc.mission.stop_spawn_mon = false;
|
||||
smc.mission.in_fight=true
|
||||
smc.vmdata.mission_data.in_fight = true
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||
oops.message.dispatchEvent(GameEvent.FightStart)
|
||||
this.triggerHeroBattleSkills(true);
|
||||
this.changePhase(MissionPhase.PrepareEnd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,11 +359,7 @@ export class MissionComp extends CCComp {
|
||||
* - 触发英雄战斗结束技能
|
||||
*/
|
||||
private enterPreparePhase() {
|
||||
this.triggerHeroBattleSkills(false);
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false
|
||||
smc.mission.stop_spawn_mon = true;
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = true;
|
||||
this.changePhase(MissionPhase.PrepareStart);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,7 +389,7 @@ export class MissionComp extends CCComp {
|
||||
private onStartFightBtnClick() {
|
||||
if (!smc.mission.play) return;
|
||||
if (smc.mission.pause) return;
|
||||
if (smc.mission.in_fight) return;
|
||||
if (this.currentPhase !== MissionPhase.Prepare) return;
|
||||
this.to_fight();
|
||||
}
|
||||
|
||||
@@ -316,24 +403,33 @@ export class MissionComp extends CCComp {
|
||||
* @param is_hero_dead 是否因英雄全灭触发
|
||||
*/
|
||||
open_Victory(e:any,is_hero_dead: boolean = false){
|
||||
smc.mission.pause = true;
|
||||
mLogger.log(this.debugMode, 'MissionComp', " open_Victory",is_hero_dead,this.revive_times)
|
||||
oops.gui.open(UIID.Victory,{
|
||||
victory:false,
|
||||
rewards:this.rewards,
|
||||
game_data:this.game_data,
|
||||
can_revive: is_hero_dead && this.revive_times > 0
|
||||
})
|
||||
this.changePhase(MissionPhase.BattleEnd);
|
||||
|
||||
// 延迟 2s 后进入结算,让 BattleEnd 阶段的表现能够播完
|
||||
this.scheduleOnce(() => {
|
||||
this.changePhase(MissionPhase.Settle);
|
||||
smc.mission.pause = true;
|
||||
mLogger.log(this.debugMode, 'MissionComp', " open_Victory",is_hero_dead,this.revive_times)
|
||||
oops.gui.open(UIID.Victory,{
|
||||
victory:false,
|
||||
rewards:this.rewards,
|
||||
game_data:this.game_data,
|
||||
can_revive: is_hero_dead && this.revive_times > 0
|
||||
})
|
||||
}, 2);
|
||||
}
|
||||
|
||||
|
||||
/** 战斗结束:延迟清理组件和对象池 */
|
||||
fight_end(){
|
||||
this.changePhase(MissionPhase.BattleEnd);
|
||||
|
||||
this.scheduleOnce(() => {
|
||||
this.changePhase(MissionPhase.Settle);
|
||||
smc.mission.play=false
|
||||
this.cleanComponents()
|
||||
this.clearBattlePools()
|
||||
}, 0.5)
|
||||
}, 2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,9 +443,7 @@ export class MissionComp extends CCComp {
|
||||
this.unscheduleAllCallbacks();
|
||||
smc.mission.play=false
|
||||
smc.mission.pause = false;
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false
|
||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
||||
this.changePhase(MissionPhase.None);
|
||||
this.cleanComponents()
|
||||
this.clearBattlePools()
|
||||
this.node.active=false
|
||||
@@ -372,6 +466,7 @@ export class MissionComp extends CCComp {
|
||||
smc.vmdata.mission_data.mon_num=0
|
||||
smc.vmdata.mission_data.level = 1
|
||||
smc.vmdata.mission_data.mon_max = Math.max(1, Math.floor(this.maxMonsterCount))
|
||||
this.currentPhase = MissionPhase.None;
|
||||
this.currentWave = 1;
|
||||
this.FightTime=FightSet.FiIGHT_TIME
|
||||
this.rewards=[]
|
||||
@@ -513,9 +608,7 @@ export class MissionComp extends CCComp {
|
||||
private handleHeroWipe(heroCount: number) {
|
||||
if (heroCount > 0) return;
|
||||
if (!smc.mission.play || smc.mission.pause) return;
|
||||
if (!smc.mission.in_fight) return;
|
||||
smc.mission.in_fight = false;
|
||||
smc.vmdata.mission_data.in_fight = false;
|
||||
if (this.currentPhase !== MissionPhase.Battle) return;
|
||||
this.open_Victory(null, true);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user