yyl
2026-01-15 bface07b5ea879e40f5be8d082bfa77fb873b0bd
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
using System;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
 
public class ViewNPCManager : GameSystemManager<ViewNPCManager>
{
    public Dictionary<uint, Dictionary<uint, Dictionary<uint, ViewNPCAttr>>> dict = new Dictionary<uint, Dictionary<uint, Dictionary<uint, ViewNPCAttr>>>();
    public override void Init()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin;
    }
 
    public override void Release()
    {
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin;
    }
 
    private void OnBeforePlayerDataInitializeEventOnRelogin()
    {
        dict.Clear();
    }
    // --- 解析属性字典 ---
    private Dictionary<int, long> ParseAttrDict(string jsonStr)
    {
        Dictionary<int, long> result = new Dictionary<int, long>();
        if (string.IsNullOrEmpty(jsonStr)) return result;
 
        try
        {
            JsonData jd = JsonMapper.ToObject(jsonStr);
            foreach (string attrKey in jd.Keys)
            {
                if (int.TryParse(attrKey, out int attrId))
                {
                    JsonData v = jd[attrKey];
                    long val = 0;
                    // 健壮性数值转换
                    if (v.IsLong) val = (long)v;
                    else if (v.IsInt) val = (long)(int)v;
                    else if (v.IsDouble) val = (long)(double)v;
                    else if (v.IsString) long.TryParse(v.ToString(), out val);
 
                    result[attrId] = val;
                }
            }
        }
        catch (System.Exception e)
        {
            Debug.LogWarning($"解析NPC属性JSON失败: {e.Message}");
        }
        return result;
    }
 
    public event Action<uint, uint> OnUpdateViewNPCAttrRet;
    public void UpdateViewNPCAttrRet(HB432_tagSCViewNPCAttrRet vNetData)
    {
        if (!dict.ContainsKey(vNetData.MapID))
        {
            dict[vNetData.MapID] = new Dictionary<uint, Dictionary<uint, ViewNPCAttr>>();
        }
 
        var mapDict = dict[vNetData.MapID];
 
        if (!mapDict.ContainsKey(vNetData.FuncLineID))
        {
            mapDict[vNetData.FuncLineID] = new Dictionary<uint, ViewNPCAttr>();
        }
 
        var funcLineDict = mapDict[vNetData.FuncLineID];
 
        if (vNetData.NPCAttrList != null)
        {
            // 使用临时字典按NPCID分组
            Dictionary<uint, List<HB432_tagSCViewNPCAttrRet.tagSCViewNPCAttr>> tempGroup =
                new Dictionary<uint, List<HB432_tagSCViewNPCAttrRet.tagSCViewNPCAttr>>();
 
            foreach (var npcAttr in vNetData.NPCAttrList)
            {
                uint npcID = npcAttr.NPCID;
                if (!tempGroup.ContainsKey(npcID))
                {
                    tempGroup[npcID] = new List<HB432_tagSCViewNPCAttrRet.tagSCViewNPCAttr>();
                }
                tempGroup[npcID].Add(npcAttr);
            }
 
            // 存入第3层字典
            foreach (var kvp in tempGroup)
            {
                var firstAttr = kvp.Value[0];
                funcLineDict[kvp.Key] = new ViewNPCAttr
                {
                    PosNum = firstAttr.PosNum,
                    NPCID = firstAttr.NPCID,
                    HeroID = firstAttr.HeroID,
                    LV = firstAttr.LV,
                    Star = firstAttr.Star,
                    BreakLV = firstAttr.BreakLV,
                    AwakeLV = firstAttr.AwakeLV,
                    AttrDict = ParseAttrDict(firstAttr.AttrMsg)
                };
            }
        }
        OnUpdateViewNPCAttrRet?.Invoke(vNetData.MapID, vNetData.FuncLineID);
    }
 
 
    public bool TryGetNPCAttr(uint mapID, uint funcLineID, uint npcID, out ViewNPCAttr npcAttr)
    {
        npcAttr = null;
 
        if (!dict.TryGetValue(mapID, out var mapDict))
        {
            return false;
        }
 
        if (!mapDict.TryGetValue(funcLineID, out var funcLineDict))
        {
            return false;
        }
 
        return funcLineDict.TryGetValue(npcID, out npcAttr);
    }
 
    public void SendViewNPCAttr(uint mapID, uint funcLineID, uint viewNPCID)
    {
        CB416_tagCSViewNPCAttr pack = new CB416_tagCSViewNPCAttr();
        pack.MapID = mapID;
        pack.FuncLineID = funcLineID;
        pack.ViewNPCID = viewNPCID;
        GameNetSystem.Instance.SendInfo(pack);
    }
}
 
public class ViewNPCAttr
{
    public byte PosNum;        // 在本阵容中的站位,从1开始
    public uint NPCID;        // 战斗NPCID,不同的实例ID对应的NPCID可能一样
    public uint HeroID;        // 武将ID,玩家或NPC均可能有,如果有值则外观相关以该武将为准,否则以NPCID为准
    public ushort LV;        // 等级,玩家的武将等级或NPC成长等级,等级显示以该值为准
    public byte Star;        // 星级
    public byte BreakLV;        // 突破
    public byte AwakeLV;        // 觉醒
    public Dictionary<int, long> AttrDict = new Dictionary<int, long>(); // 属性;
}