| | |
| | | |
| | | public class ViewNPCManager : GameSystemManager<ViewNPCManager> |
| | | { |
| | | // 缓存字典结构: MapID -> FuncLineID -> NPCID -> Attr |
| | | public Dictionary<uint, Dictionary<uint, Dictionary<uint, ViewNPCAttr>>> dict = new Dictionary<uint, Dictionary<uint, Dictionary<uint, ViewNPCAttr>>>(); |
| | | private BattleClickHeroData pendingData; // 用于记录当前正在请求查看的 NPC 信息,以便回包时自动打开界面 --- |
| | | private bool isPendingOpen = false; // 是否是点击触发的请求(需要自动打开界面) |
| | | OtherPlayerDetailManager otherPlayerManager { get { return OtherPlayerDetailManager.Instance; } } |
| | | public override void Init() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin += OnBeforePlayerDataInitializeEventOnRelogin; |
| | | EventBroadcast.Instance.AddListener<BattleClickHeroData>(EventName.BATTLE_CLICK_HERO, OnBattleClickHero); |
| | | OtherPlayerDetailManager.Instance.OnRevPackage += OnRevPackage; |
| | | } |
| | | |
| | | public override void Release() |
| | | { |
| | | DTC0102_tagCDBPlayer.beforePlayerDataInitializeEventOnRelogin -= OnBeforePlayerDataInitializeEventOnRelogin; |
| | | EventBroadcast.Instance.RemoveListener<BattleClickHeroData>(EventName.BATTLE_CLICK_HERO, OnBattleClickHero); |
| | | OtherPlayerDetailManager.Instance.OnRevPackage -= OnRevPackage; |
| | | } |
| | | |
| | | |
| | | private void OnBeforePlayerDataInitializeEventOnRelogin() |
| | | { |
| | | dict.Clear(); |
| | | ResetPendingState(); |
| | | } |
| | | |
| | | private void ResetPendingState() |
| | | { |
| | | isPendingOpen = false; |
| | | pendingData.isMySide = false; |
| | | pendingData.funcLineID = 0; |
| | | pendingData.mapID = 0; |
| | | pendingData.npcID = 0; |
| | | pendingData.teams = null; |
| | | } |
| | | |
| | | private void OnBattleClickHero(BattleClickHeroData data) |
| | | { |
| | | pendingData = data; |
| | | // 主线不显示NPC信息 |
| | | if (data.mapID == 1) |
| | | return; |
| | | |
| | | // 自己的数据直接读背包 |
| | | if (data.isMySide) |
| | | { |
| | | OpenNPCDetailWin(pendingData, null); |
| | | return; |
| | | } |
| | | |
| | | // pvp的走查看玩家的 |
| | | if (BattleManager.Instance.IsPvpBattle(data.battleName)) |
| | | { |
| | | switch (data.battleName) |
| | | { |
| | | case BattleConst.ArenaBattleField: |
| | | int playerId = (int)ArenaManager.Instance.atkPlayerId; |
| | | OtherPlayerDetailManager.Instance.ViewPlayerDetail(playerId, (int)ViewPlayerType.viewArenaBattleEnemyHero, (int)BattlePreSetType.Arena); |
| | | break; |
| | | } |
| | | return; |
| | | } |
| | | // 非pvp的走查看npc的 |
| | | // 尝试直接从缓存获取数据 |
| | | if (TryGetNPCAttr((uint)data.mapID, (uint)data.funcLineID, (uint)data.npcID, out ViewNPCAttr attr)) |
| | | { |
| | | OpenNPCDetailWin(pendingData, attr); |
| | | } |
| | | else |
| | | { |
| | | isPendingOpen = true; |
| | | SendViewNPCAttr(data); |
| | | } |
| | | } |
| | | |
| | | private void OnRevPackage(int viewPlayerType, int playerID) |
| | | { |
| | | switch (viewPlayerType) |
| | | { |
| | | case (int)ViewPlayerType.viewArenaBattleEnemyHero: |
| | | ViewArenaBattleEnemyHero(playerID); |
| | | break; |
| | | } |
| | | } |
| | | |
| | | private void ViewArenaBattleEnemyHero(int playerID) |
| | | { |
| | | int presetID = otherPlayerManager.GetFuncPresetID(playerID, OtherPlayerDetailManager.Instance.viewPreSetType, (int)FuncPresetType.Global); |
| | | var heroList = otherPlayerManager.GetHeroDataSortList(playerID, presetID); |
| | | if (heroList.IsNullOrEmpty()) |
| | | { |
| | | heroList = otherPlayerManager.GetHeroDataSortList(playerID, FuncPresetManager.FuncDefaultPresetID); |
| | | } |
| | | var heroData = otherPlayerManager.GetHeroDataDict(playerID, presetID); |
| | | if (heroList.IsNullOrEmpty()) |
| | | { |
| | | heroList = otherPlayerManager.GetHeroDataSortList(playerID, FuncPresetManager.FuncDefaultPresetID); |
| | | } |
| | | if (heroList == null || heroData == null) |
| | | return; |
| | | int posNum = pendingData.posNum + 1; |
| | | if (!heroData.ContainsKey(posNum)) |
| | | return; |
| | | OtherPlayerDetailManager.Instance.viewHeroType = 0; |
| | | OtherPlayerDetailManager.Instance.clickHeroData = pendingData; |
| | | OtherPlayerDetailManager.Instance.heroData = heroData[posNum]; |
| | | OtherPlayerDetailManager.Instance.heroDatas = heroList; |
| | | |
| | | if (!UIManager.Instance.IsOpened<OtherHeroDetailWin>()) |
| | | { |
| | | UIManager.Instance.OpenWindow<OtherHeroDetailWin>(); |
| | | } |
| | | } |
| | | |
| | | |
| | | private void OpenNPCDetailWin(BattleClickHeroData data, ViewNPCAttr npcAttr) |
| | | { |
| | | OtherPlayerDetailManager.Instance.viewHeroType = 0; |
| | | OtherPlayerDetailManager.Instance.clickHeroData = data; |
| | | OtherPlayerDetailManager.Instance.viewNPCAttr = npcAttr; |
| | | |
| | | if (data.isMySide) |
| | | { |
| | | if (!UIManager.Instance.IsOpened<OtherHeroDetailWin>()) |
| | | { |
| | | UIManager.Instance.OpenWindow<OtherHeroDetailWin>(); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (!UIManager.Instance.IsOpened<OtherNPCDetailWin>()) |
| | | { |
| | | UIManager.Instance.OpenWindow<OtherNPCDetailWin>(); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | // --- 解析属性字典 --- |
| | | private Dictionary<int, long> ParseAttrDict(string jsonStr) |
| | | { |
| | |
| | | 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); |
| | | |
| | | long.TryParse(v.ToString(), out long val); |
| | | result[attrId] = val; |
| | | } |
| | | } |
| | | } |
| | | catch (System.Exception e) |
| | | catch (Exception e) |
| | | { |
| | | Debug.LogWarning($"解析NPC属性JSON失败: {e.Message}"); |
| | | } |
| | |
| | | } |
| | | |
| | | public event Action<uint, uint> OnUpdateViewNPCAttrRet; |
| | | |
| | | public void UpdateViewNPCAttrRet(HB432_tagSCViewNPCAttrRet vNetData) |
| | | { |
| | | // 1. 更新字典数据 |
| | | if (!dict.ContainsKey(vNetData.MapID)) |
| | | { |
| | | dict[vNetData.MapID] = new Dictionary<uint, Dictionary<uint, ViewNPCAttr>>(); |
| | |
| | | }; |
| | | } |
| | | } |
| | | |
| | | // 检查是否需要自动打开界面 (Pending 逻辑) |
| | | if (isPendingOpen) |
| | | { |
| | | // 检查回包是否对应当前的请求 (MapID 和 FuncLineID 匹配) |
| | | if (vNetData.MapID == pendingData.mapID && vNetData.FuncLineID == pendingData.funcLineID) |
| | | { |
| | | if (TryGetNPCAttr((uint)pendingData.mapID, (uint)pendingData.funcLineID, (uint)pendingData.npcID, out ViewNPCAttr targetAttr)) |
| | | { |
| | | OpenNPCDetailWin(pendingData, targetAttr); |
| | | } |
| | | // 处理完毕,重置状态 |
| | | ResetPendingState(); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | OnUpdateViewNPCAttrRet?.Invoke(vNetData.MapID, vNetData.FuncLineID); |
| | | |
| | | } |
| | | |
| | | |
| | | |
| | | public bool TryGetNPCAttr(uint mapID, uint funcLineID, uint npcID, out ViewNPCAttr npcAttr) |
| | |
| | | } |
| | | |
| | | return funcLineDict.TryGetValue(npcID, out npcAttr); |
| | | } |
| | | |
| | | public void SendViewNPCAttr(BattleClickHeroData data) |
| | | { |
| | | SendViewNPCAttr((uint)data.mapID, (uint)data.funcLineID, (uint)data.npcID); |
| | | } |
| | | |
| | | public void SendViewNPCAttr(uint mapID, uint funcLineID, uint viewNPCID) |
| | |
| | | public byte BreakLV; // 突破 |
| | | public byte AwakeLV; // 觉醒 |
| | | public Dictionary<int, long> AttrDict = new Dictionary<int, long>(); // 属性; |
| | | } |
| | | |
| | | public struct BattleClickHeroData |
| | | { |
| | | public string battleName; |
| | | public bool isMySide; |
| | | public int heroID; |
| | | public int funcLineID; |
| | | public int mapID; |
| | | public int npcID; |
| | | public int posNum; |
| | | public List<BattleObject> teams; |
| | | } |