lcy
3 天以前 2dd1841d03a730d3d369092c2a3ad656cee4bf64
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
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]);
    }
}