using UnityEngine;
|
using System.Collections.Generic;
|
using Cysharp.Threading.Tasks;
|
using System;
|
|
|
// 如果这个Action卡住了 大概率是因为 动作被其他动作中断了 导致没有回调
|
public class DeathRecordAction : RecordAction
|
{
|
protected List<BattleDeadPack> deadPackList = new List<BattleDeadPack>();
|
|
protected Dictionary<BattleDeadPack, SkillRecordAction> deathActionDict = new Dictionary<BattleDeadPack, SkillRecordAction>();
|
|
protected Dictionary<BattleDeadPack, Func<bool>> deadActionStatesDict = new Dictionary<BattleDeadPack, Func<bool>>();
|
|
protected Dictionary<int, bool> dropStateDict = new Dictionary<int, bool>();
|
|
protected bool hasDeathTriggerSkill = false;
|
|
// 标记是否已经分发了死亡后的包
|
protected bool hasDistributedPacksAfterDeath = false;
|
|
private SkillRecordAction parentSkillAction = null;
|
|
private SkillRecordAction playSkillRecordAction = null;
|
|
public DeathRecordAction(BattleField _battleField, List<BattleDeadPack> _deadPackList, SkillRecordAction _parentSkillAction = null, SkillRecordAction _playSkillRecordAction = null)
|
: base(RecordActionType.Death, _battleField, null)
|
{
|
deadPackList = _deadPackList;
|
CheckHasDeathTriggerSkill();
|
|
// for (int i = 0; i < deadPackList.Count; i++)
|
// {
|
// BattleObject battleObject = battleField.battleObjMgr.GetBattleObject((int)deadPackList[i].deadPack.ObjID);
|
// Debug.LogError($"DeathRecordAction: 初始化死亡动作,死亡对象名字={battleObject?.GetName()}, hasDeathTriggerSkill={deadPackList[i].deadTriggerSkill != null}");
|
// }
|
|
parentSkillAction = _parentSkillAction;
|
playSkillRecordAction = _playSkillRecordAction;
|
|
}
|
|
protected void CheckHasDeathTriggerSkill()
|
{
|
foreach (var battleDeadPack in deadPackList)
|
{
|
if (battleDeadPack.deadTriggerSkill != null)
|
{
|
hasDeathTriggerSkill = true;
|
break;
|
}
|
}
|
}
|
|
|
public override void Run()
|
{
|
base.Run();
|
|
// 该死的正常死
|
// 有技能的则按照顺序播放死亡技能 后再正常死
|
if (isFinish)
|
return;
|
|
|
if (!isRunOnce)
|
{
|
isRunOnce = true;
|
|
SkillRecordAction waitingAnimeAction = playSkillRecordAction;
|
|
foreach (var battleDeadPack in deadPackList)
|
{
|
if (battleDeadPack.deadTriggerSkill != null)
|
{
|
SkillRecordAction skillAction = battleDeadPack.deadTriggerSkill.CreateSkillAction();
|
if (null != skillAction)
|
{
|
deathActionDict.Add(battleDeadPack, skillAction);
|
|
// 【使用 BattleField.recordPlayer】
|
// 原因:死亡触发技能是顶层的RecordAction,不是在某个RecordAction内部产生的
|
// 虽然可能是因为技能导致的死亡,但死亡触发的技能本身应该是独立的
|
// 使用ImmediatelyPlay并设置WaitingPlay=true,可以让死亡技能等待导致死亡的技能完成
|
// 如果DeathRecordAction有父节点(导致死亡的技能),则等待那个父节点
|
// 否则等待DeathRecordAction本身
|
if (waitingAnimeAction == null)
|
{
|
battleField.recordPlayer.ImmediatelyPlay(skillAction, this, true);
|
}
|
else
|
{
|
waitingAnimeAction.GetInnerRecordPlayer().ImmediatelyPlay(skillAction, waitingAnimeAction);
|
}
|
|
if (battleDeadPack.deadTriggerSkill.NeedWaiting() || waitingAnimeAction != null)
|
{
|
waitingAnimeAction = skillAction;
|
}
|
}
|
}
|
else
|
{
|
deadActionStatesDict.Add(battleDeadPack, CreateDeadActionState(battleDeadPack));
|
}
|
}
|
}
|
else
|
{
|
List<BattleDeadPack> finishedKeys = new List<BattleDeadPack>();
|
foreach (var kv in deathActionDict)
|
{
|
if (!kv.Key.isPlaySkill)
|
{
|
// battleField.recordPlayer.ImmediatelyPlay(kv.Value);
|
kv.Key.isPlaySkill = true;
|
}
|
|
if (!kv.Value.IsFinished())
|
{
|
kv.Value.Run();
|
}
|
else
|
{
|
deadActionStatesDict.Add(kv.Key, CreateDeadActionState(kv.Key, true));
|
finishedKeys.Add(kv.Key);
|
}
|
break;
|
}
|
|
foreach (var key in finishedKeys)
|
{
|
deathActionDict.Remove(key);
|
}
|
|
if (0 == deathActionDict.Count)
|
{
|
hasDeathTriggerSkill = false;
|
}
|
|
int completeNum = 0;
|
|
foreach (var kv in deadActionStatesDict)
|
{
|
if (kv.Value())
|
{
|
completeNum++;
|
}
|
}
|
|
if (completeNum == deadPackList.Count)
|
{
|
// 死亡处理完成后,分发死亡后的包
|
if (!hasDistributedPacksAfterDeath)
|
{
|
hasDistributedPacksAfterDeath = true;
|
DistributePacksAfterDeath();
|
}
|
|
isActionCompleted = true;
|
isFinish = true;
|
}
|
}
|
}
|
|
|
|
// 重写IsActionCompleted,死亡动作是否完成
|
public override bool IsActionCompleted()
|
{
|
return isActionCompleted || isFinish;
|
}
|
|
private Func<bool> CreateDeadActionState(BattleDeadPack deadPack, bool withoutAnime = false)
|
{
|
BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.deadPack.ObjID);
|
if (null == deadObj)
|
{
|
return () => true;
|
}
|
|
bool playDeath = false;
|
|
bool isComplete = false;
|
|
// 如果没有释放技能 则直接死亡
|
if (deadObj.CanStartDeath())
|
{
|
PerformDrop(deadObj);
|
|
deadObj.OnDeath(() => {
|
isComplete = true;
|
}, withoutAnime);
|
|
playDeath = true;
|
}
|
|
|
|
return () =>
|
{
|
// 还没播放死亡 并且没释放其他技能
|
if (!playDeath && deadObj.CanStartDeath())
|
{
|
PerformDrop(deadObj);
|
|
deadObj.OnDeath(() => {
|
isComplete = true;
|
}, withoutAnime);
|
|
playDeath = true;
|
}
|
|
if (deadObj.IsReborning())
|
{
|
isComplete = true;
|
}
|
|
return isComplete;
|
};
|
}
|
|
public override void ForceFinish()
|
{
|
if (isFinish)
|
return;
|
|
isFinish = true;
|
|
// 强制结束所有死亡触发技能
|
foreach (var kv in deathActionDict)
|
{
|
kv.Value.ForceFinish();
|
}
|
deathActionDict.Clear();
|
|
// 清理状态字典,防止回调继续等待
|
deadActionStatesDict.Clear();
|
|
// 直接结束所有死亡对象
|
foreach (var deadPack in deadPackList)
|
{
|
BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.deadPack.ObjID);
|
if (null != deadObj)
|
{
|
PerformDrop(deadObj);
|
deadObj.SetDeath();
|
}
|
}
|
|
// 强制分发死亡后的包
|
if (!hasDistributedPacksAfterDeath)
|
{
|
hasDistributedPacksAfterDeath = true;
|
DistributePacksAfterDeath();
|
}
|
|
base.ForceFinish();
|
}
|
|
private void PerformDrop(BattleObject deadObj)
|
{
|
// 只有主线掉落物品
|
if (battleField.MapID == 1 || battleField.MapID == 2)
|
{
|
if (dropStateDict.ContainsKey(deadObj.ObjID))
|
{
|
return;
|
}
|
dropStateDict.Add(deadObj.ObjID, true);
|
deadObj.PerformDrop();
|
}
|
}
|
|
protected bool HasDeathTriggerSkill()
|
{
|
return hasDeathTriggerSkill;
|
}
|
|
// 分发死亡后的包
|
protected void DistributePacksAfterDeath()
|
{
|
// 遍历所有死亡包,分发它们的 packListAfterDeath
|
foreach (var deadPack in deadPackList)
|
{
|
if (deadPack.packListAfterDeath != null && deadPack.packListAfterDeath.Count > 0)
|
{
|
foreach (var pack in deadPack.packListAfterDeath)
|
{
|
// 获取包的类型和UID用于调试
|
string packType = pack.GetType().Name;
|
ulong packUID = 0;
|
var packUIDField = pack.GetType().GetField("packUID");
|
if (packUIDField != null)
|
{
|
packUID = (ulong)packUIDField.GetValue(pack);
|
}
|
|
|
// 特殊处理 CustomHB426CombinePack:使用其自己的 Distribute 方法
|
if (pack is CustomHB426CombinePack combinePack)
|
{
|
combinePack.Distribute(playSkillRecordAction);
|
}
|
// 特殊处理 HB427_tagSCUseSkill:创建技能包并分发
|
else if (pack is HB427_tagSCUseSkill skillPack)
|
{
|
var skillAction = CustomHB426CombinePack.CreateSkillAction(battleField.guid, new List<GameNetPackBasic>() { skillPack });
|
if (skillAction != null)
|
{
|
if (playSkillRecordAction != null)
|
{
|
playSkillRecordAction.GetInnerRecordPlayer().PlayRecord(skillAction);
|
}
|
else
|
{
|
battleField.PlayRecord(skillAction);
|
}
|
}
|
}
|
else
|
{
|
// 【使用 causingRecordAction 或 battleField.recordPlayer】
|
// 原因:死亡后的包应该回到导致死亡的技能所在的上下文
|
// 如果有 parentSkillAction(导致死亡的技能),则分发到它的 innerRecordPlayer
|
// 否则分发到 battleField.recordPlayer(顶层)
|
if (playSkillRecordAction != null)
|
{
|
PackageRegeditEx.DistributeToRecordAction(pack, playSkillRecordAction);
|
}
|
else
|
{
|
// 如果没有 causingRecordAction,直接分发(使用原始的 PackageRegedit)
|
PackageRegedit.Distribute(pack);
|
}
|
}
|
}
|
|
// 分发完成后清理列表,防止重复分发和内存泄漏
|
deadPack.packListAfterDeath.Clear();
|
}
|
}
|
}
|
|
public override bool CanStartExecution()
|
{
|
// 如果不是WaitingPlay模式,直接可以执行
|
if (!isWaitingPlay)
|
{
|
return true;
|
}
|
|
// 如果没有父节点,也可以执行
|
if (parentSkillAction == null)
|
{
|
return true;
|
}
|
|
// 可以先执行没有死亡触发技能的死亡动作
|
if (!HasDeathTriggerSkill())
|
{
|
return true;
|
}
|
|
// WaitingPlay模式下,需要等待直接父节点的动作完成(不管父节点是否WaitingPlay)
|
if (!parentSkillAction.IsActionCompleted())
|
{
|
BattleDebug.LogError($"RecordAction.CanStartExecution: {this.GetType().Name} 等待父节点 {parentSkillAction.GetType().Name} 动作完成");
|
return false;
|
}
|
|
return true;
|
}
|
|
public override bool NeedWaitSibling()
|
{
|
return HasDeathTriggerSkill();
|
}
|
|
#if UNITY_EDITOR
|
/// <summary>
|
/// 首次运行时打印日志(仅编辑器)
|
/// 打印死亡对象的名字
|
/// </summary>
|
protected override void PrintFirstRunLog()
|
{
|
if (deadPackList != null && deadPackList.Count > 0)
|
{
|
string deadNames = "";
|
foreach (var deadPack in deadPackList)
|
{
|
BattleObject deadObj = battleField.battleObjMgr.GetBattleObject((int)deadPack.deadPack.ObjID);
|
string name = deadObj?.GetName() ?? "Unknown";
|
deadNames += name + ",";
|
}
|
deadNames = deadNames.TrimEnd(',');
|
Debug.LogError($"[DeathRecordAction首次Run] 死亡对象:{deadNames} 数量:{deadPackList.Count}");
|
}
|
else
|
{
|
base.PrintFirstRunLog();
|
}
|
}
|
#endif
|
}
|