using BrewMonster; using BrewMonster.Network; using BrewMonster.UI; using CSNetwork; using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.UIElements; public class CECUIManager : MonoSingleton { [SerializeField] private Transform uiRoot; // nơi chứa UI được spawn (Canvas hoặc Transform) [SerializeField] private List uiPrefabs; // drag các prefab UI vào đây private readonly Dictionary _spawnedUIs = new(); [SerializeField] private HUDNPC npsUI; [SerializeField] private int currentTargetNPCID; CECGameUIMan gameUI; AUIManager aUIManager; [SerializeField] private DialogScriptTableObject dialogResouce; [SerializeField] private Canvas canvasDlg; [SerializeField] private CDlgQuickBar cDlgQuickBar; [SerializeField] private UnityEngine.UI.Button btnSecondClick; [SerializeField] CDlgQuickBar m_pDlgQuickBar1; CDlgMessageBox m_pDlgMessageBox; protected override void Awake() { base.Awake(); EventBus.Subscribe(ShowUINPC); EventBus.Subscribe(TryHideUINPC); EventBus.Subscribe(OnMessageBox); gameUI = new CECGameUIMan(); gameUI.SetDependency(dialogResouce, canvasDlg); gameUI.Init(); // Wire up second-click button / 连接第二次点击按钮 if (btnSecondClick != null) { btnSecondClick.onClick.AddListener(OnSecondClickButtonClicked); } ShowUI("Win_Hpmpxp"); } private void Update() { if (m_pDlgQuickBar1 != null) { m_pDlgQuickBar1.UpdateShortcuts(); } } private void OnDestroy() { EventBus.Unsubscribe(ShowUINPC); EventBus.Unsubscribe(TryHideUINPC); EventBus.Subscribe(OnMessageBox); } private void ShowUINPC(CECHostPlayer.NPCINFO obj) { npsUI.gameObject.SetActive(true); npsUI.SetText($"{obj.CurrentHealth}/{obj.MaxHealth}", obj.Name, ""); npsUI.SetHealthImage((float)obj.CurrentHealth / (float)obj.MaxHealth); currentTargetNPCID = obj.IDNPC; } public CDlgQuickBar GetCDlgQuickBar() { return cDlgQuickBar; } private void TryHideUINPC(NPCDiedEvent obj) { if (obj.NPCID != currentTargetNPCID) return; npsUI.gameObject.SetActive(false); } /// /// Show UI by name of component ("DlgTask", "EC_InventoryUI") /// /// name of component ("DlgTask", "EC_InventoryUI") public void ShowUI(string componentName) { if (string.IsNullOrEmpty(componentName) || canvasDlg == null) { if (canvasDlg == null) Debug.LogError("canvasDlg chưa được gán"); return; } GetInGameUIMan().GetDialog(componentName).Show(true); return; var type = FindTypeByName(componentName); if (TryShowCachedUI(type)) return; if (FindUIByName(componentName, type)) return; if (FindUIByType(type)) return; Debug.LogWarning($"Không tìm thấy UI {componentName} đã spawn trong canvasDlg. Type found: {(type != null ? type.FullName : "null")}"); } public void ShowMessageBox(string title, string message) { var msgBox = GetInGameUIMan().GetDialog("DlgMessageBox") as CDlgMessageBox; if (msgBox != null) { msgBox.ShowMessageBox(title, message); } else { Debug.LogError("DlgMessageBox not found in InGameUIMan"); } } private void OnMessageBox(MessageBoxEvent messageBoxEvent) { int iRetVal = messageBoxEvent.iRetVal; AUIDialog pDlg = messageBoxEvent.pDlg; if (pDlg == m_pDlgMessageBox) { OnNewMessageBox(iRetVal); return; } UnityGameSession pSession = UnityGameSession.Instance; CECHostPlayer pHost = CECGameRun.Instance.GetHostPlayer(); if (string.Equals(pDlg.GetName(), "Game_Quit", StringComparison.OrdinalIgnoreCase)) { } else if ((string.Equals(pDlg.GetName(), "Game_TeachSkill", StringComparison.OrdinalIgnoreCase) && DialogBoxCommandIDs.IDOK == iRetVal) || (string.Equals(pDlg.GetName(), "Game_LearnSkill", StringComparison.OrdinalIgnoreCase) && DialogBoxCommandIDs.IDOK == iRetVal)) { if (string.Equals(pDlg.GetName(), "Game_TeachSkill", StringComparison.OrdinalIgnoreCase)) { } else if (string.Equals(pDlg.GetName(), "Game_LearnSkill", StringComparison.OrdinalIgnoreCase)) { int skillID = (int)pDlg.GetData(); int nCondition = pHost.CheckSkillLearnCondition(skillID, true); if (0 == nCondition) { UnityGameSession.c2s_SendCmdNPCSevLearnSkill(skillID); } /*else if (1 == nCondition) AddChatMessage(GetStringFromTable(270), GP_CHAT_MISC); else if (6 == nCondition) AddChatMessage(GetStringFromTable(527), GP_CHAT_MISC); else if (7 == nCondition) AddChatMessage(GetStringFromTable(541), GP_CHAT_MISC); else if (8 == nCondition) AddChatMessage(GetStringFromTable(271), GP_CHAT_MISC); else if (9 == nCondition) AddChatMessage(GetStringFromTable(556), GP_CHAT_MISC); else if (10 == nCondition) AddChatMessage(GetStringFromTable(557), GP_CHAT_MISC); else if (12 == nCondition) AddChatMessage(GetStringFromTable(11168), GP_CHAT_MISC);*/ } } } private bool OnNewMessageBox(int iRetVal) { return true; } private System.Type FindTypeByName(string componentName) { string[] namespacePrefixes = { "", // No namespace "BrewMonster.Scripts.Task.UI.", "BrewMonster.UI.", "BrewMonster.Scripts.UI.", "BrewMonster." }; // Try with common namespace prefixes foreach (var prefix in namespacePrefixes) { string fullTypeName = string.IsNullOrEmpty(prefix) ? componentName : prefix + componentName; var type = System.Type.GetType(fullTypeName); if (type != null) return type; } // Search in all assemblies foreach (var assembly in System.AppDomain.CurrentDomain.GetAssemblies()) { var type = assembly.GetType(componentName); if (type != null) return type; foreach (var prefix in namespacePrefixes) { if (string.IsNullOrEmpty(prefix)) continue; type = assembly.GetType(prefix + componentName); if (type != null) return type; } } return null; } private bool TryShowCachedUI(System.Type type) { if (type != null && _spawnedUIs.TryGetValue(type, out var uiGo)) { uiGo.SetActive(true); return true; } return false; } private bool FindUIByName(string componentName, System.Type type) { for (int i = 0; i < canvasDlg.transform.childCount; i++) { var child = canvasDlg.transform.GetChild(i); if (!child.name.Contains(componentName) && child.name != componentName) continue; if (type != null) { var foundComponent = child.GetComponentInChildren(type, true); if (foundComponent != null) { ActivateAndCacheUI(foundComponent.gameObject, type); return true; } } ActivateAndCacheUI(child.gameObject, type); return true; } return false; } private bool FindUIByType(System.Type type) { if (type == null) return false; var foundComponent = canvasDlg.GetComponentInChildren(type, true); if (foundComponent != null) { ActivateAndCacheUI(foundComponent.gameObject, type); return true; } return false; } private void ActivateAndCacheUI(GameObject uiGameObject, System.Type type) { uiGameObject.SetActive(true); if (type != null) _spawnedUIs[type] = uiGameObject; } /// /// Ẩn UI (disable thay vì destroy) /// public void HideUI() where T : Component { var type = typeof(T); if (_spawnedUIs.TryGetValue(type, out var uiGo)) { uiGo.SetActive(false); } } /// /// Kiểm tra UI có đang active không /// public bool IsUIActive() where T : Component { var type = typeof(T); return _spawnedUIs.TryGetValue(type, out var uiGo) && uiGo.activeSelf; } /// /// Ẩn tất cả UI hiện tại /// public void HideAll() { foreach (var kv in _spawnedUIs) { kv.Value.SetActive(false); } } public CECGameUIMan GetInGameUIMan() { if (gameUI == null) { gameUI = new CECGameUIMan(); gameUI.SetDependency(dialogResouce, canvasDlg); gameUI.Init(); } return gameUI; } /// /// Get the current target NPC ID (same as stored from NPCINFO event) /// public int GetCurrentTargetNPCID() { return currentTargetNPCID; } //todo: change this code to other place private int slot = 0; public void OnClickedWaveHand() { if (EC_Game.GetGameRun().GetPoseCmdShortcuts() == null) { EC_Game.GetGameRun().StartGame(0, Vector3.zero); } CECShortcut pSC = EC_Game.GetGameRun().GetPoseCmdShortcuts().GetShortcut(slot); if (pSC != null) // && pObjSrc->GetDataPtr("ptr_CECShortcut") == pSC { // a_LogOutput(1, "[Dat Emote] ptr_CECShortcut"); pSC.Execute(); } } /// /// Handle second-click button click - triggers attack or move to NPC / 处理第二次点击按钮 - 触发攻击或移动到NPC /// Uses OnMsgLBtnClick with selected target to reuse existing logic / 使用OnMsgLBtnClick和选中的目标来重用现有逻辑 /// private void OnSecondClickButtonClicked() { CECHostPlayer hostPlayer = EC_Game.GetGameRun()?.GetHostPlayer(); if (hostPlayer != null) { int selectedTarget = hostPlayer.GetSelectedTarget(); if (selectedTarget != 0) { // Call OnMsgLBtnClick with the selected target to simulate second click / 使用选中的目标调用OnMsgLBtnClick以模拟第二次点击 hostPlayer.OnMsgLBtnClick(selectedTarget); } } } public struct MessageBoxEvent { public int iRetVal; public AUIDialog pDlg; public MessageBoxEvent(int retVal, AUIDialog dlg) { iRetVal = retVal; pDlg = dlg; } } }