using System.Collections.Generic;
|
using System.Linq;
|
using UnityEngine;
|
|
// SkillBase(Death 部分):死亡包、HP 刷新、掉落、经验的收集与分配。
|
public partial class SkillBase
|
{
|
// 处理HP刷新包(简化逻辑)
|
private void HandleRefreshHP()
|
{
|
// 查找HP刷新包
|
HB419_tagSCObjHPRefresh refreshPack = BattleUtility.FindObjHPRefreshPack(packList);
|
|
if (refreshPack != null)
|
{
|
// 分发HP刷新包
|
// 【使用 parentRecordAction.innerRecordPlayer】
|
// 原因:HP刷新包是技能内部产生的,应该由当前SkillRecordAction的innerRecordPlayer管理
|
// 这样可以确保HP刷新与技能的生命周期绑定,ForceFinish时一并处理
|
PackageRegeditEx.DistributeToRecordAction(refreshPack, ownRecordAction);
|
packList.Remove(refreshPack);
|
}
|
}
|
|
// 处理死亡相关逻辑:分配掉落和经验
|
protected void HandleDead()
|
{
|
List<BattleDeadPack> deadPackList = BattleUtility.FindDeadPack(packList);
|
if (deadPackList.Count <= 0) return;
|
|
foreach (var deadPack in deadPackList)
|
{
|
packList.Remove(deadPack.deadPack);
|
packList.Remove(deadPack.deadTriggerSkill);
|
}
|
|
// 找到最大的死亡包 packUID
|
BattleDeadPack lastBattleDeadPack = null;
|
ulong maxDeathPackUID = 0;
|
foreach (var deadPack in deadPackList)
|
{
|
if (deadPack.deadPack != null && deadPack.deadPack.packUID > maxDeathPackUID)
|
{
|
maxDeathPackUID = deadPack.deadPack.packUID;
|
lastBattleDeadPack = deadPack;
|
}
|
}
|
|
// 如果找到了死亡包,收集所有 packUID > maxDeathPackUID 的包
|
if (maxDeathPackUID > 0 && lastBattleDeadPack != null)
|
{
|
BattleDebug.LogError($"SkillBase.HandleDead: 找到死亡包,maxDeathPackUID = {maxDeathPackUID},开始收集死亡后的包");
|
|
// 1. 收集 packList 中 packUID 大于死亡包的包(排除经验包和掉落包,它们需要在当前技能中处理)
|
List<GameNetPackBasic> packsToRemove = new List<GameNetPackBasic>();
|
foreach (var pack in packList)
|
{
|
ulong packUID = GetPackUID(pack);
|
if (packUID > maxDeathPackUID)
|
{
|
// 排除经验包和掉落包,它们属于当前死亡事件的一部分,不是"死亡后"的包
|
if (pack is HB405_tagMCAddExp expPack && expPack.Source == 2 ||
|
(pack is H0704_tagRolePackRefresh h0704 && h0704.PackType == (byte)PackType.DropItem && h0704.IsBind == 1))
|
{
|
continue; // 跳过经验包和掉落包,让 CheckAfterDeadhPack() 处理它们
|
}
|
|
BattleDebug.LogError($"SkillBase.HandleDead: 从packList收集死亡后的包 - Type: {pack.GetType().Name}, UID: {packUID}");
|
lastBattleDeadPack.packListAfterDeath.Add(pack);
|
packsToRemove.Add(pack);
|
}
|
}
|
|
packList.RemoveAll(p => packsToRemove.Contains(p));
|
}
|
|
CheckAfterDeadhPack();
|
|
// 修复:先收集要删除的包,避免在foreach中修改集合
|
var dropPacksToRemove = new List<H0704_tagRolePackRefresh>(dropPackList);
|
foreach (var _dropPack in dropPacksToRemove)
|
{
|
// 【使用 parentRecordAction.innerRecordPlayer】
|
// 原因:掉落包是技能效果的一部分,应该由当前SkillRecordAction管理
|
// 掉落包的分发与技能完成绑定,确保在技能ForceFinish时正确处理
|
PackageRegeditEx.DistributeToRecordAction(_dropPack, ownRecordAction);
|
packList.Remove(_dropPack);
|
}
|
|
// 获取并分配掉落物品和经验
|
var dropPack = PackManager.Instance.GetSinglePack(PackType.DropItem);
|
var itemDict = dropPack.GetAllItems();
|
List<ItemModel> itemList = new List<ItemModel>(itemDict.Values.Where(item => item != null && item.isAuction));
|
|
var dropAssign = AssignDrops(itemList, deadPackList.Count);
|
var expAssign = AssignExp(expPackList, deadPackList.Count);
|
|
// 构造BattleDrops并缓存
|
for (int i = 0; i < deadPackList.Count; i++)
|
{
|
BattleDeadPack bdp = deadPackList[i];
|
int objID = (int)bdp.deadPack.ObjID;
|
BattleObject deadTarget = battleField.battleObjMgr.GetBattleObject(objID);
|
|
// 修复:添加空值检查
|
if (deadTarget == null)
|
{
|
Debug.LogError($"找不到死亡目标,ObjID: {objID}");
|
continue;
|
}
|
|
List<int> itemIndexList = dropAssign[i].Select(item => item.gridIndex).ToList();
|
|
BattleDrops battleDrops = new BattleDrops()
|
{
|
rectTransform = deadTarget.GetRectTransform(),
|
dropItemPackIndex = itemIndexList,
|
expDrops = expAssign[i]
|
};
|
|
// 修复:避免字典键冲突,使用安全的添加方式
|
if (!tempDropList.ContainsKey(objID))
|
{
|
tempDropList.Add(objID, battleDrops);
|
}
|
else
|
{
|
Debug.LogWarning($"tempDropList中已存在ObjID={objID}的记录,将覆盖原值");
|
tempDropList[objID] = battleDrops; // 覆盖现有值
|
}
|
|
if (!tempDeadPackList.ContainsKey(objID))
|
{
|
tempDeadPackList.Add(objID, deadPackList[i]);
|
}
|
else
|
{
|
Debug.LogWarning($"tempDeadPackList中已存在ObjID={objID}的记录,将覆盖原值");
|
tempDeadPackList[objID] = deadPackList[i]; // 覆盖现有值
|
}
|
}
|
|
// 修复:避免在遍历时修改集合,先收集后删除
|
var deadPacksToRemove = new List<GameNetPackBasic>(deadPackList.Select(d => d.deadPack));
|
deadPacksToRemove.AddRange(deadPackList.Where(d => d.deadTriggerSkill != null).Select(d => d.deadTriggerSkill));
|
foreach (var deadPack in deadPacksToRemove)
|
{
|
packList.Remove(deadPack);
|
}
|
}
|
|
// 分配掉落物品:将掉落物品平均分配给死亡对象
|
protected List<List<ItemModel>> AssignDrops(List<ItemModel> itemList, int deadCount)
|
{
|
var dropAssign = new List<List<ItemModel>>();
|
for (int i = 0; i < deadCount; i++)
|
dropAssign.Add(new List<ItemModel>());
|
for (int i = 0; i < itemList.Count; i++)
|
dropAssign[i % deadCount].Add(itemList[i]);
|
return dropAssign;
|
}
|
|
// 获取包的 packUID
|
protected ulong GetPackUID(GameNetPackBasic pack)
|
{
|
if (pack == null) return 0;
|
|
if (pack is HB422_tagMCTurnFightObjDead deadPack)
|
return deadPack.packUID;
|
|
if (pack is CustomHB426CombinePack combinePack)
|
{
|
var mainSkillPack = combinePack.GetMainHB427SkillPack();
|
return mainSkillPack?.packUID ?? 0;
|
}
|
|
if (pack is HB427_tagSCUseSkill skillPack)
|
return skillPack.packUID;
|
|
if (pack is HB428_tagSCBuffRefresh buffRefresh)
|
return buffRefresh.packUID;
|
|
if (pack is HB429_tagSCBuffDel buffDel)
|
return buffDel.packUID;
|
|
if (pack is HB419_tagSCObjHPRefresh hpRefresh)
|
return hpRefresh.packUID;
|
|
if (pack is HB405_tagMCAddExp expPack)
|
return expPack.packUID;
|
|
if (pack is H0704_tagRolePackRefresh dropPack)
|
return dropPack.packUID;
|
|
// 尝试通过反射获取 packUID
|
var packUIDField = pack.GetType().GetField("packUID");
|
if (packUIDField != null)
|
{
|
return (ulong)packUIDField.GetValue(pack);
|
}
|
|
return 0;
|
}
|
|
// 分配经验值:将经验包平均分配给每个死亡对象
|
protected List<List<HB405_tagMCAddExp>> AssignExp(List<HB405_tagMCAddExp> expList, int deadCount)
|
{
|
var expAssign = new List<List<HB405_tagMCAddExp>>();
|
for (int i = 0; i < deadCount; i++)
|
expAssign.Add(new List<HB405_tagMCAddExp>());
|
|
// 修复:检查除零风险
|
if (deadCount == 0)
|
{
|
Debug.LogWarning("AssignExp: deadCount为0,无法分配经验");
|
return expAssign;
|
}
|
|
// 修复:先收集要删除的包,避免在foreach中修改packList
|
var expPacksToRemove = new List<HB405_tagMCAddExp>();
|
|
foreach (var expPack in expList)
|
{
|
long totalExp = GeneralDefine.GetFactValue(expPack.Exp, expPack.ExpPoint);
|
long avgExp = totalExp / deadCount;
|
long remain = totalExp % deadCount;
|
|
for (int i = 0; i < deadCount; i++)
|
{
|
long assignExp = avgExp + (i < remain ? 1 : 0);
|
var newPack = new HB405_tagMCAddExp
|
{
|
Exp = (uint)(assignExp % Constants.ExpPointValue),
|
ExpPoint = (uint)(assignExp / Constants.ExpPointValue),
|
Source = expPack.Source
|
};
|
expAssign[i].Add(newPack);
|
}
|
expPacksToRemove.Add(expPack);
|
}
|
|
// 统一删除收集的包
|
foreach (var pack in expPacksToRemove)
|
{
|
packList.Remove(pack);
|
}
|
|
return expAssign;
|
}
|
|
/// <summary>
|
/// 将 tempDeadPackList 里 pending 的死亡包投递给 BattleField 生成 DeathRecordAction。
|
/// 合并 IsFinished(正常结束)与 ForceFinished(强制结束)两条路径的共同部分。
|
/// </summary>
|
/// <param name="useInnerPlayer">
|
/// true:把 DeathRecordAction 绑定到 ownRecordAction(正常结束,死亡动作会等待当前技能完成);
|
/// false:不绑定(强制结束,死亡动作立即在默认 RecordPlayer 里播放)。
|
/// </param>
|
/// <param name="clearEvenIfNotDispatched">
|
/// true:无论是否投递成功都清空 tempDeadPackList(ForceFinished 语义);
|
/// false:仅在成功投递 DeathRecordAction 时清空(IsFinished 语义)。
|
/// </param>
|
/// <returns>是否成功投递了 DeathRecordAction。</returns>
|
protected bool FlushPendingDeathActions(bool useInnerPlayer, bool clearEvenIfNotDispatched)
|
{
|
// 防御:battleField / caster 任一为 null 时直接返回,避免 NullReferenceException。
|
if (battleField == null || caster == null)
|
{
|
if (clearEvenIfNotDispatched) tempDeadPackList.Clear();
|
return false;
|
}
|
|
// 统一做的事:从战场 casting 注册里移除自身。
|
battleField.RemoveCastingSkill(caster.ObjID, this);
|
|
var deadPacks = new List<BattleDeadPack>(tempDeadPackList.Values);
|
// 两条路径的唯一差别:是否把 DeathRecordAction 绑定到 ownRecordAction(让死亡动作等技能完成)。
|
DeathRecordAction recordAction = useInnerPlayer
|
? battleField.OnObjsDead(deadPacks, null, ownRecordAction)
|
: battleField.OnObjsDead(deadPacks);
|
|
if (null != recordAction && ownRecordAction != null)
|
{
|
ownRecordAction.GetInnerRecordPlayer().ImmediatelyPlay(recordAction);
|
tempDeadPackList.Clear();
|
return true;
|
}
|
|
if (clearEvenIfNotDispatched)
|
{
|
tempDeadPackList.Clear();
|
}
|
return false;
|
}
|
|
// 检查死亡后的包处理:处理技能包、掉落包、经验包
|
protected void CheckAfterDeadhPack()
|
{
|
List<int> removeIndexList = new List<int>();
|
|
for (int i = 0; i < packList.Count; i++)
|
{
|
var pack = packList[i];
|
|
// 复活基本都靠技能包
|
if (pack is CustomHB426CombinePack combinePack && combinePack.startTag.Tag.StartsWith("Skill_"))
|
break;
|
|
if (pack is H0704_tagRolePackRefresh h0704Pack && h0704Pack.PackType == (byte)PackType.DropItem && h0704Pack.IsBind == 1)
|
{
|
dropPackList.Add(h0704Pack);
|
removeIndexList.Add(i);
|
}
|
|
if (pack is HB405_tagMCAddExp h405Pack && h405Pack.Source == 2)
|
{
|
expPackList.Add(h405Pack);
|
removeIndexList.Add(i);
|
}
|
}
|
|
for (int i = removeIndexList.Count - 1; i >= 0; i--)
|
packList.RemoveAt(removeIndexList[i]);
|
}
|
}
|