using System.Collections.Generic;
|
using System;
|
using UnityEngine;
|
|
public class RecordPlayer
|
{
|
protected BattleField battleField;
|
|
private Queue<RecordAction> recordActionQueue = new Queue<RecordAction>();
|
protected RecordAction currentRecordAction;
|
|
protected List<RecordAction> immediatelyActionList = new List<RecordAction>();
|
|
private bool isWaitingNextAction = false;
|
private float waitTimer = 0f;
|
private const float waitInterval = 0.2f;
|
|
private float speedRatio = 1.5f;
|
|
private bool isForceFinish = false;
|
|
public bool IsForceFinish
|
{
|
get { return isForceFinish; }
|
}
|
|
private bool stepForcefinish = false;
|
|
public void Init(BattleField _battleField)
|
{
|
Reload(_battleField);
|
}
|
|
public void Reload(BattleField _battleField)
|
{
|
Release();
|
stepForcefinish = false;
|
battleField = _battleField;
|
}
|
|
public bool IsPlaying()
|
{
|
bool isPlaying = currentRecordAction != null || recordActionQueue.Count > 0 || immediatelyActionList.Count > 0;
|
//BattleDebug.LogError("IsPlaying " + isPlaying + " currentRecordAction " + (currentRecordAction != null) + " recordActionQueue.Count " + recordActionQueue.Count + " immediatelyActionList.Count " + immediatelyActionList.Count);
|
return isPlaying;
|
}
|
|
public void PlayRecord(RecordAction recordAction)
|
{
|
if (recordAction == null) return;
|
recordAction.actionOwner = this;
|
// Debug.LogError("Enqueue record action " + recordAction.GetType() + " to queue");
|
if (isForceFinish || stepForcefinish)
|
{
|
recordAction.ForceFinish();
|
return;
|
}
|
recordActionQueue.Enqueue(recordAction);
|
recordAction.AfterAddToQueue();
|
}
|
|
public void PlayRecord(RecordAction recordAction, RecordAction waitingAnimeAction)
|
{
|
if (recordAction == null) return;
|
recordAction.actionOwner = this;
|
// Debug.LogError("Enqueue record action " + recordAction.GetType() + " to queue");
|
if (isForceFinish || stepForcefinish)
|
{
|
recordAction.ForceFinish();
|
return;
|
}
|
recordAction.waitingAnimeAction = waitingAnimeAction;
|
recordActionQueue.Enqueue(recordAction);
|
recordAction.AfterAddToQueue();
|
}
|
|
public void PlayRecord(List<RecordAction> recordActions)
|
{
|
for (int i = 0; i < recordActions.Count; i++)
|
{
|
PlayRecord(recordActions[i]);
|
}
|
}
|
|
public void InsertRecord(RecordAction recordAction, int position = 0)
|
{
|
if (recordAction == null) return;
|
recordAction.actionOwner = this;
|
if (isForceFinish || stepForcefinish)
|
{
|
recordAction.ForceFinish();
|
return;
|
}
|
|
// Debug.LogError("Insert record action " + recordAction.GetType() + " at front of queue");
|
if (currentRecordAction != null)
|
{
|
Queue<RecordAction> tempQueue = new Queue<RecordAction>();
|
|
for (int i = 0; i < position && recordActionQueue.Count > 0; i++)
|
{
|
tempQueue.Enqueue(recordActionQueue.Dequeue());
|
}
|
|
tempQueue.Enqueue(recordAction);
|
|
while (recordActionQueue.Count > 0)
|
{
|
tempQueue.Enqueue(recordActionQueue.Dequeue());
|
}
|
|
recordActionQueue = tempQueue;
|
}
|
else
|
{
|
recordActionQueue.Enqueue(recordAction);
|
}
|
|
recordAction.AfterAddToQueue();
|
}
|
|
public void ImmediatelyPlay(RecordAction recordAction)
|
{
|
if (recordAction == null) return;
|
recordAction.actionOwner = this;
|
if (isForceFinish || stepForcefinish)
|
{
|
recordAction.ForceFinish();
|
return;
|
}
|
immediatelyActionList.Add(recordAction);
|
}
|
|
public void ImmediatelyPlay(RecordAction recordAction, RecordAction waitingAnimeAction)
|
{
|
if (recordAction == null) return;
|
recordAction.actionOwner = this;
|
if (isForceFinish || stepForcefinish)
|
{
|
recordAction.ForceFinish();
|
return;
|
}
|
recordAction.waitingAnimeAction = waitingAnimeAction;
|
immediatelyActionList.Add(recordAction);
|
}
|
|
// 增强版本:支持父子关系和WaitingPlay标记
|
public void ImmediatelyPlay(RecordAction recordAction, RecordAction parentAction, bool isWaitingPlay)
|
{
|
if (recordAction == null) return;
|
recordAction.actionOwner = this;
|
if (isForceFinish || stepForcefinish)
|
{
|
recordAction.ForceFinish();
|
return;
|
}
|
|
// Debug.LogError("insert recordAction ImmediatelyPlay: " + recordAction.GetType().Name + " parentAction: " + (parentAction != null ? parentAction.GetType().Name : "null") + " isWaitingPlay: " + isWaitingPlay);
|
|
// 设置父子关系
|
if (parentAction != null)
|
{
|
recordAction.SetParentAction(parentAction);
|
parentAction.AddChildAction(recordAction);
|
}
|
|
// 设置WaitingPlay标记
|
recordAction.SetWaitingPlay(isWaitingPlay);
|
|
immediatelyActionList.Add(recordAction);
|
}
|
|
public bool IsActionCompleted()
|
{
|
bool ret = true;
|
|
foreach (var imac in immediatelyActionList)
|
{
|
if (!imac.IsActionCompleted())
|
{
|
ret = false;
|
break;
|
}
|
}
|
|
if (ret == false)
|
{
|
return false;
|
}
|
|
if (currentRecordAction != null && !currentRecordAction.IsActionCompleted())
|
{
|
return false;
|
}
|
|
return ret;
|
}
|
|
protected void ImmediatelyPlayRun()
|
{
|
if (immediatelyActionList.Count > 0)
|
{
|
List<int> removeIndexList = new List<int>();
|
|
// 关键修复:从前往后遍历,确保按加入顺序执行
|
for (int i = 0; i < immediatelyActionList.Count; i++)
|
{
|
var action = immediatelyActionList[i];
|
if (action == null)
|
{
|
removeIndexList.Add(i);
|
continue;
|
}
|
|
// 检查是否可以开始执行(WaitingPlay条件检查)
|
if (!action.CanStartExecution())
|
{
|
continue;
|
}
|
|
// 检查同级的前置兄弟节点:如果有相同父节点且索引更小的节点还在执行,则等待
|
bool shouldWaitForSibling = false;
|
if (action.isWaitingPlay && action.parentAction != null)
|
{
|
for (int j = 0; j < i; j++)
|
{
|
var prevAction = immediatelyActionList[j];
|
if (prevAction != null && prevAction.parentAction == action.parentAction)
|
{
|
// 找到同级前置节点,如果它还在执行中,则当前节点需要等待
|
if (!prevAction.IsFinished() && action.NeedWaitSibling())
|
{
|
shouldWaitForSibling = true;
|
// BattleDebug.LogError($"RecordPlayer: {action.GetType().Name} 等待同级前置节点 {prevAction.GetType().Name} 完成");
|
break;
|
}
|
}
|
}
|
}
|
|
if (shouldWaitForSibling)
|
{
|
continue;
|
}
|
|
if (!action.IsFinished())
|
{
|
if (action.waitingAnimeAction != null)
|
{
|
if (!action.waitingAnimeAction.IsActionCompleted())
|
{
|
continue;
|
}
|
}
|
action.Run();
|
continue;
|
}
|
|
removeIndexList.Add(i);
|
}
|
|
// 从后往前删除,确保索引不会因为删除而错位
|
for (int i = removeIndexList.Count - 1; i >= 0; i--)
|
{
|
int index = removeIndexList[i];
|
if (index < 0 || index >= immediatelyActionList.Count)
|
continue;
|
immediatelyActionList.RemoveAt(index);
|
}
|
}
|
}
|
|
public virtual void Run()
|
{
|
ImmediatelyPlayRun();
|
|
// 等待下一个action
|
if (isWaitingNextAction)
|
{
|
waitTimer += Time.deltaTime * speedRatio;
|
if (waitTimer >= waitInterval)
|
{
|
isWaitingNextAction = false;
|
waitTimer = 0f;
|
}
|
else
|
{
|
return;
|
}
|
}
|
|
if (currentRecordAction == null)
|
{
|
if (recordActionQueue.Count <= 0)
|
{
|
return;
|
}
|
}
|
|
if (currentRecordAction != null && !currentRecordAction.IsFinished())
|
{
|
if (currentRecordAction.waitingAnimeAction != null)
|
{
|
if (!currentRecordAction.waitingAnimeAction.IsActionCompleted())
|
{
|
return;
|
}
|
}
|
currentRecordAction.Run();
|
return;
|
}
|
|
if (currentRecordAction != null && currentRecordAction.IsFinished())
|
{
|
var guid = currentRecordAction.GetBattleFieldGuid();
|
// BattleDebug.LogError("record action " + currentRecordAction.GetType() + " play finished");
|
currentRecordAction = null;
|
isWaitingNextAction = true;
|
waitTimer = 0f;
|
EventBroadcast.Instance.Broadcast<string>(EventName.RECORDPLAYER_END, guid);
|
return;
|
}
|
|
if (currentRecordAction == null)
|
{
|
if (recordActionQueue.Count > 0)
|
{
|
currentRecordAction = recordActionQueue.Dequeue();
|
#if UNITY_EDITOR
|
// if (currentRecordAction is SkillRecordAction skillRecordAction)
|
// {
|
// Debug.LogError("RecordPlayer Run Play SkillRecordAction skillname " + skillRecordAction.skillBase.skillConfig.SkillName + " caster " + skillRecordAction.skillBase.caster.teamHero.name);
|
// }
|
// else
|
#endif
|
{
|
BattleDebug.LogError("play record action " + currentRecordAction.GetType());
|
}
|
}
|
}
|
}
|
|
// 先预留 感觉用的上
|
public virtual void ResumeGame()
|
{
|
|
}
|
|
public virtual void PauseGame()
|
{
|
|
}
|
|
|
public void HaveRest()
|
{
|
ForceFinish();
|
}
|
|
public void ClearAllRecordAction()
|
{
|
currentRecordAction?.ForceFinish();
|
currentRecordAction = null;
|
recordActionQueue.Clear();
|
immediatelyActionList.Clear();
|
}
|
|
public void EnableForceFinish(bool enable)
|
{
|
stepForcefinish = enable;
|
}
|
|
public void ForceFinish()
|
{
|
isForceFinish = true;
|
for (int i = immediatelyActionList.Count - 1; i >= 0; i--)
|
{
|
var action = immediatelyActionList[i];
|
action.ForceFinish();
|
immediatelyActionList.Remove(action);
|
}
|
|
while (currentRecordAction != null)
|
{
|
var temp = currentRecordAction;
|
currentRecordAction = null;
|
temp.ForceFinish();
|
}
|
|
while (recordActionQueue.Count > 0)
|
{
|
recordActionQueue.Dequeue().ForceFinish();
|
}
|
}
|
|
public void Release()
|
{
|
if (null != currentRecordAction)
|
{
|
currentRecordAction.ForceFinish();
|
}
|
currentRecordAction = null;
|
recordActionQueue.Clear();
|
immediatelyActionList.Clear();
|
isForceFinish = false;
|
stepForcefinish = false;
|
}
|
|
public void SetSpeedRatio(float ratio)
|
{
|
speedRatio = ratio;
|
}
|
}
|