|
using System.Collections.Generic;
|
using System;
|
|
|
public class RecordAction
|
{
|
protected BattleField battleField;
|
|
// 本次Action的主角
|
protected BattleObject battleObject;
|
|
protected bool isFinish = false;
|
|
protected bool isRunOnce = false;
|
|
// ===== 父子关系和等待机制 =====
|
// 父RecordAction引用(如果是通过其他RecordAction内部触发的)
|
public RecordAction parentAction;
|
|
// 子RecordAction列表(此RecordAction内部触发的其他RecordAction)
|
protected List<RecordAction> childActionList = new List<RecordAction>();
|
|
// 是否是WaitingPlay模式(需要等待父节点动作完成)
|
public bool isWaitingPlay = false;
|
|
// 自身动作是否完成(不包括子节点的完成状态)
|
protected bool isActionCompleted = false;
|
|
// ===== 内部RecordPlayer机制 =====
|
// 内部RecordPlayer:用于播放由此RecordAction内部产生的RecordAction
|
// 当RecordAction内部产生新的RecordAction时(如PackageRegedit.Distribute触发的),
|
// 这些RecordAction应该由当前RecordAction的innerRecordPlayer管理,而不是BattleField的主RecordPlayer
|
// 这样可以保证:
|
// 1. 内部产生的RecordAction生命周期与父RecordAction绑定
|
// 2. ForceFinish时可以一并处理内部的RecordAction
|
// 3. 不会干扰BattleField主RecordPlayer的播放队列
|
protected RecordPlayer innerRecordPlayer;
|
|
public RecordAction(RecordActionType _actionType, BattleField _battleField, BattleObject _battleObj)
|
{
|
actionType = _actionType;
|
battleField = _battleField;
|
battleObject = _battleObj;
|
|
// 初始化内部RecordPlayer
|
// 每个RecordAction都有自己的RecordPlayer来管理内部产生的RecordAction
|
if (_battleField != null)
|
{
|
innerRecordPlayer = new RecordPlayer();
|
innerRecordPlayer.Init(_battleField);
|
}
|
}
|
|
public virtual void Played()
|
{
|
|
}
|
|
public RecordActionType actionType;
|
|
// 添加子RecordAction
|
public virtual void AddChildAction(RecordAction child)
|
{
|
if (child == null) return;
|
|
// 防止重复添加
|
if (childActionList.Contains(child)) return;
|
|
// 防止循环依赖
|
if (child == this)
|
{
|
BattleDebug.LogError("RecordAction.AddChildAction: 不能将自己添加为子节点");
|
return;
|
}
|
|
childActionList.Add(child);
|
BattleDebug.LogError($"RecordAction.AddChildAction: {this.GetType().Name} 添加子节点 {child.GetType().Name}");
|
}
|
|
// 设置父RecordAction
|
public virtual void SetParentAction(RecordAction parent)
|
{
|
parentAction = parent;
|
if (parent != null)
|
{
|
BattleDebug.LogError($"RecordAction.SetParentAction: {this.GetType().Name} 的父节点设置为 {parent.GetType().Name}");
|
}
|
}
|
|
// 设置WaitingPlay标记
|
public virtual void SetWaitingPlay(bool waiting)
|
{
|
isWaitingPlay = waiting;
|
BattleDebug.LogError($"RecordAction.SetWaitingPlay: {this.GetType().Name} WaitingPlay={waiting}");
|
}
|
|
// 检查自身动作是否完成(不包括子节点)
|
// 子类应该重写此方法来实现自己的动作完成判断
|
public virtual bool IsActionCompleted()
|
{
|
return isActionCompleted;
|
}
|
|
// 检查是否可以开始执行(WaitingPlay条件检查)
|
public virtual bool CanStartExecution()
|
{
|
// 如果不是WaitingPlay模式,直接可以执行
|
if (!isWaitingPlay)
|
{
|
return true;
|
}
|
|
// 如果没有父节点,也可以执行
|
if (parentAction == null)
|
{
|
return true;
|
}
|
|
// WaitingPlay模式下,需要等待直接父节点的动作完成(不管父节点是否WaitingPlay)
|
if (!parentAction.IsActionCompleted())
|
{
|
BattleDebug.LogError($"RecordAction.CanStartExecution: {this.GetType().Name} 等待父节点 {parentAction.GetType().Name} 动作完成");
|
return false;
|
}
|
|
return true;
|
}
|
|
public virtual bool IsNeedWaiting()
|
{
|
return false;
|
}
|
|
// 检查是否完全完成(包括所有子节点)
|
public virtual bool IsFinished()
|
{
|
// 首先自身动作必须完成
|
if (!isActionCompleted && !isFinish)
|
{
|
return false;
|
}
|
|
// 检查内部RecordPlayer是否还在播放
|
// 原因:内部产生的RecordAction必须全部播放完成后,当前RecordAction才算完成
|
if (innerRecordPlayer != null && innerRecordPlayer.IsPlaying())
|
{
|
return false;
|
}
|
|
// 检查所有子节点是否完成
|
foreach (var child in childActionList)
|
{
|
if (!child.IsFinished())
|
{
|
return false;
|
}
|
}
|
|
return true;
|
}
|
|
public virtual void Run()
|
{
|
// 先运行内部RecordPlayer
|
// 原因:内部产生的RecordAction需要先执行,确保内部逻辑按正确顺序播放
|
// 例如:技能内部产生的Buff添加、子技能等都由innerRecordPlayer管理
|
innerRecordPlayer?.Run();
|
}
|
|
public virtual void ForceFinish()
|
{
|
isFinish = true;
|
isActionCompleted = true;
|
|
// 强制结束内部RecordPlayer
|
// 原因:RecordAction被ForceFinish时,其内部产生的所有RecordAction也必须强制结束
|
// 这样才能保证整个RecordAction树的完整性和一致性
|
innerRecordPlayer?.ForceFinish();
|
|
// 强制结束所有子节点
|
for (int i = childActionList.Count - 1; i >= 0; i--)
|
{
|
var child = childActionList[i];
|
child?.ForceFinish();
|
}
|
|
// 清理父子引用,防止内存泄漏
|
childActionList.Clear();
|
parentAction = null;
|
}
|
|
public virtual string GetBattleFieldGuid()
|
{
|
if (battleField == null)
|
{
|
return string.Empty;
|
}
|
return battleField.guid;
|
}
|
|
// 获取内部RecordPlayer
|
// 用于外部代码需要将RecordAction添加到此RecordAction的内部播放器时使用
|
public virtual RecordPlayer GetInnerRecordPlayer()
|
{
|
return innerRecordPlayer;
|
}
|
|
public virtual bool NeedWaitSibling()
|
{
|
return true;
|
}
|
}
|