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";
|
import { CardInitCoins } from "../common/config/CardSet";
|
||||||
const { ccclass, property } = _decorator;
|
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 进行奖励处理
|
//@todo 需要关注 当boss死亡的时候的动画播放完成后,需要触发事件,通知 MissionComp 进行奖励处理
|
||||||
|
|
||||||
@@ -59,7 +70,7 @@ const { ccclass, property } = _decorator;
|
|||||||
@ecs.register('MissionComp', false)
|
@ecs.register('MissionComp', false)
|
||||||
export class MissionComp extends CCComp {
|
export class MissionComp extends CCComp {
|
||||||
@property({ tooltip: "是否启用调试日志" })
|
@property({ tooltip: "是否启用调试日志" })
|
||||||
private debugMode: boolean = false;
|
private debugMode: boolean = true;
|
||||||
@property({ tooltip: "是否显示战斗内存观测面板" })
|
@property({ tooltip: "是否显示战斗内存观测面板" })
|
||||||
private showMemoryPanel: boolean = false;
|
private showMemoryPanel: boolean = false;
|
||||||
|
|
||||||
@@ -133,6 +144,8 @@ export class MissionComp extends CCComp {
|
|||||||
private currentWave: number = 0;
|
private currentWave: number = 0;
|
||||||
/** 上一次发放金币奖励的波数(防止重复发放) */
|
/** 上一次发放金币奖励的波数(防止重复发放) */
|
||||||
private lastPrepareCoinWave: number = 0;
|
private lastPrepareCoinWave: number = 0;
|
||||||
|
/** 当前任务阶段 */
|
||||||
|
public currentPhase: MissionPhase = MissionPhase.None;
|
||||||
|
|
||||||
// ======================== ECS 查询匹配器(预缓存) ========================
|
// ======================== ECS 查询匹配器(预缓存) ========================
|
||||||
|
|
||||||
@@ -168,7 +181,7 @@ export class MissionComp extends CCComp {
|
|||||||
protected update(dt: number): void {
|
protected update(dt: number): void {
|
||||||
if(!smc.mission.play) return
|
if(!smc.mission.play) return
|
||||||
if(smc.mission.pause) return
|
if(smc.mission.pause) return
|
||||||
if(smc.mission.in_fight){
|
if(this.currentPhase === MissionPhase.Battle){
|
||||||
this.syncMonsterSpawnState(dt)
|
this.syncMonsterSpawnState(dt)
|
||||||
if(smc.mission.stop_mon_action) return
|
if(smc.mission.stop_mon_action) return
|
||||||
smc.vmdata.mission_data.fight_time+=dt
|
smc.vmdata.mission_data.fight_time+=dt
|
||||||
@@ -235,7 +248,7 @@ export class MissionComp extends CCComp {
|
|||||||
this.node.active=true
|
this.node.active=true
|
||||||
this.data_init()
|
this.data_init()
|
||||||
oops.message.dispatchEvent(GameEvent.FightReady)
|
oops.message.dispatchEvent(GameEvent.FightReady)
|
||||||
this.enterPreparePhase()
|
this.changePhase(MissionPhase.Prepare)
|
||||||
let loading=this.node.parent.getChildByName("loading")
|
let loading=this.node.parent.getChildByName("loading")
|
||||||
loading.active=true
|
loading.active=true
|
||||||
this.scheduleOnce(()=>{
|
this.scheduleOnce(()=>{
|
||||||
@@ -243,6 +256,89 @@ export class MissionComp extends CCComp {
|
|||||||
},0.5)
|
},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(){
|
to_fight(){
|
||||||
smc.mission.stop_spawn_mon = false;
|
this.changePhase(MissionPhase.PrepareEnd);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -268,11 +359,7 @@ export class MissionComp extends CCComp {
|
|||||||
* - 触发英雄战斗结束技能
|
* - 触发英雄战斗结束技能
|
||||||
*/
|
*/
|
||||||
private enterPreparePhase() {
|
private enterPreparePhase() {
|
||||||
this.triggerHeroBattleSkills(false);
|
this.changePhase(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 = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -302,7 +389,7 @@ export class MissionComp extends CCComp {
|
|||||||
private onStartFightBtnClick() {
|
private onStartFightBtnClick() {
|
||||||
if (!smc.mission.play) return;
|
if (!smc.mission.play) return;
|
||||||
if (smc.mission.pause) return;
|
if (smc.mission.pause) return;
|
||||||
if (smc.mission.in_fight) return;
|
if (this.currentPhase !== MissionPhase.Prepare) return;
|
||||||
this.to_fight();
|
this.to_fight();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,24 +403,33 @@ export class MissionComp extends CCComp {
|
|||||||
* @param is_hero_dead 是否因英雄全灭触发
|
* @param is_hero_dead 是否因英雄全灭触发
|
||||||
*/
|
*/
|
||||||
open_Victory(e:any,is_hero_dead: boolean = false){
|
open_Victory(e:any,is_hero_dead: boolean = false){
|
||||||
smc.mission.pause = true;
|
this.changePhase(MissionPhase.BattleEnd);
|
||||||
mLogger.log(this.debugMode, 'MissionComp', " open_Victory",is_hero_dead,this.revive_times)
|
|
||||||
oops.gui.open(UIID.Victory,{
|
// 延迟 2s 后进入结算,让 BattleEnd 阶段的表现能够播完
|
||||||
victory:false,
|
this.scheduleOnce(() => {
|
||||||
rewards:this.rewards,
|
this.changePhase(MissionPhase.Settle);
|
||||||
game_data:this.game_data,
|
smc.mission.pause = true;
|
||||||
can_revive: is_hero_dead && this.revive_times > 0
|
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(){
|
fight_end(){
|
||||||
|
this.changePhase(MissionPhase.BattleEnd);
|
||||||
|
|
||||||
this.scheduleOnce(() => {
|
this.scheduleOnce(() => {
|
||||||
|
this.changePhase(MissionPhase.Settle);
|
||||||
smc.mission.play=false
|
smc.mission.play=false
|
||||||
this.cleanComponents()
|
this.cleanComponents()
|
||||||
this.clearBattlePools()
|
this.clearBattlePools()
|
||||||
}, 0.5)
|
}, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -347,9 +443,7 @@ export class MissionComp extends CCComp {
|
|||||||
this.unscheduleAllCallbacks();
|
this.unscheduleAllCallbacks();
|
||||||
smc.mission.play=false
|
smc.mission.play=false
|
||||||
smc.mission.pause = false;
|
smc.mission.pause = false;
|
||||||
smc.mission.in_fight = false;
|
this.changePhase(MissionPhase.None);
|
||||||
smc.vmdata.mission_data.in_fight = false
|
|
||||||
if (this.start_btn && this.start_btn.isValid) this.start_btn.active = false;
|
|
||||||
this.cleanComponents()
|
this.cleanComponents()
|
||||||
this.clearBattlePools()
|
this.clearBattlePools()
|
||||||
this.node.active=false
|
this.node.active=false
|
||||||
@@ -372,6 +466,7 @@ export class MissionComp extends CCComp {
|
|||||||
smc.vmdata.mission_data.mon_num=0
|
smc.vmdata.mission_data.mon_num=0
|
||||||
smc.vmdata.mission_data.level = 1
|
smc.vmdata.mission_data.level = 1
|
||||||
smc.vmdata.mission_data.mon_max = Math.max(1, Math.floor(this.maxMonsterCount))
|
smc.vmdata.mission_data.mon_max = Math.max(1, Math.floor(this.maxMonsterCount))
|
||||||
|
this.currentPhase = MissionPhase.None;
|
||||||
this.currentWave = 1;
|
this.currentWave = 1;
|
||||||
this.FightTime=FightSet.FiIGHT_TIME
|
this.FightTime=FightSet.FiIGHT_TIME
|
||||||
this.rewards=[]
|
this.rewards=[]
|
||||||
@@ -513,9 +608,7 @@ export class MissionComp extends CCComp {
|
|||||||
private handleHeroWipe(heroCount: number) {
|
private handleHeroWipe(heroCount: number) {
|
||||||
if (heroCount > 0) return;
|
if (heroCount > 0) return;
|
||||||
if (!smc.mission.play || smc.mission.pause) return;
|
if (!smc.mission.play || smc.mission.pause) return;
|
||||||
if (!smc.mission.in_fight) return;
|
if (this.currentPhase !== MissionPhase.Battle) return;
|
||||||
smc.mission.in_fight = false;
|
|
||||||
smc.vmdata.mission_data.in_fight = false;
|
|
||||||
this.open_Victory(null, true);
|
this.open_Victory(null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user