743 lines
24 KiB
C#
743 lines
24 KiB
C#
using BrewMonster;
|
||
using BrewMonster.Network;
|
||
using BrewMonster.UI;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using BrewMonster.Scripts.Managers;
|
||
using UnityEngine;
|
||
using TMPro;
|
||
|
||
public class CECUIManager : MonoSingleton<CECUIManager>
|
||
{
|
||
[SerializeField] private TMP_Text _fpsText;
|
||
[SerializeField] private List<GameObject> uiPrefabs; // drag các prefab UI vào đây
|
||
|
||
private readonly Dictionary<Type, GameObject> _spawnedUIs = new();
|
||
|
||
/// <summary>Stack of dialog names (front = index 0 = top / currently on top).</summary>
|
||
[SerializeField]private List<string> _uiStack = new();
|
||
|
||
/// <summary>Max number of dialogs in stack; when exceeded on Push, the top is popped once. 0 = unlimited.</summary>
|
||
[SerializeField] private int _maxStack = 1;
|
||
|
||
[SerializeField] private HUDNPC npsUI;
|
||
|
||
[SerializeField] private int currentTargetNPCID;
|
||
CECGameUIMan gameUI;
|
||
public CECGameUIMan GameUI => gameUI;
|
||
AUIManager aUIManager;
|
||
AUIDialog _dlgPlayerOptions;
|
||
[SerializeField] private DialogScriptTableObject dialogResouce;
|
||
[SerializeField] private Canvas canvasDlg;
|
||
|
||
[SerializeField] private UnityEngine.UI.Button btnSecondClick;
|
||
[SerializeField] CDlgQuickBar m_pDlgQuickBar1;
|
||
public CDlgSkillSubOther m_pDlgSkillSubOther;
|
||
CDlgMessageBox m_pDlgMessageBox;
|
||
public CDlgSkillAction m_pDlgSkillAction;
|
||
Sprite[] m_iconlistIvtr;
|
||
private CDlgInfoTooltip m_pDlgSkillTooltip;
|
||
|
||
// Task update timer / 任务更新计时器
|
||
private float _nextTaskUpdateTime = 0f;
|
||
private const float TASK_UPDATE_INTERVAL = .1f;
|
||
|
||
protected override void Awake()
|
||
{
|
||
base.Awake();
|
||
|
||
EventBus.Subscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
|
||
EventBus.Subscribe<CECHostPlayer.TargetHUDClearEvent>(OnTargetHUDClear);
|
||
EventBus.Subscribe<NPCDiedEvent>(TryHideUINPC);
|
||
EventBus.Subscribe<MessageBoxEvent>(OnMessageBox);
|
||
|
||
gameUI = new CECGameUIMan();
|
||
gameUI.SetDependency(dialogResouce, canvasDlg);
|
||
gameUI.Init();
|
||
m_pDlgSkillAction = GetComponent<CDlgSkillAction>();
|
||
// Wire up second-click button / 连接第二次点击按钮
|
||
if (btnSecondClick != null)
|
||
{
|
||
btnSecondClick.onClick.AddListener(OnSecondClickButtonClicked);
|
||
}
|
||
|
||
ShowUI("Win_Hpmpxp");
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
// _fpsText.text = $"{Mathf.RoundToInt(1f / Time.deltaTime)}";
|
||
if (m_pDlgQuickBar1 != null)
|
||
{
|
||
m_pDlgQuickBar1.UpdateShortcuts();
|
||
}
|
||
|
||
// Periodically update task UI (DlgTask and DlgTaskTrace) / 定期更新任务UI(DlgTask和DlgTaskTrace)
|
||
if (Time.unscaledTime >= _nextTaskUpdateTime)
|
||
{
|
||
_nextTaskUpdateTime = Time.unscaledTime + TASK_UPDATE_INTERVAL;
|
||
UpdateTaskUI();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Update task UI from DlgTask and DlgTaskTrace / 从DlgTask和DlgTaskTrace更新任务UI
|
||
/// </summary>
|
||
private void UpdateTaskUI()
|
||
{
|
||
try
|
||
{
|
||
var inGameUIMan = GetInGameUIMan();
|
||
if (inGameUIMan == null) return;
|
||
|
||
var dlgTaskDialog = inGameUIMan.GetDialog("Win_Quest");
|
||
var dlgTaskTraceDialog = inGameUIMan.GetDialog("Win_QuestMinion");
|
||
if (dlgTaskDialog != null && dlgTaskDialog is BrewMonster.Scripts.Task.UI.DlgTask dlgTaskForTrace)
|
||
{
|
||
if (dlgTaskTraceDialog != null && dlgTaskTraceDialog.IsShow())
|
||
{
|
||
dlgTaskForTrace.RefreshTaskTrace();
|
||
}
|
||
|
||
dlgTaskForTrace.Tick();
|
||
}
|
||
}
|
||
catch (System.Exception)
|
||
{
|
||
// Silently handle errors to avoid spamming logs / 静默处理错误以避免日志刷屏
|
||
// Task UI update errors are handled silently / 任务UI更新错误被静默处理
|
||
}
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
EventBus.Unsubscribe<CECHostPlayer.NPCINFO>(ShowUINPC);
|
||
EventBus.Unsubscribe<CECHostPlayer.TargetHUDClearEvent>(OnTargetHUDClear);
|
||
EventBus.Unsubscribe<NPCDiedEvent>(TryHideUINPC);
|
||
EventBus.Unsubscribe<MessageBoxEvent>(OnMessageBox);
|
||
}
|
||
|
||
private void ShowUINPC(CECHostPlayer.NPCINFO obj)
|
||
{
|
||
var host = EC_Game.GetGameRun()?.GetHostPlayer();
|
||
if (host != null && host.GetSelectedTarget() != obj.IDNPC)
|
||
return;
|
||
npsUI.gameObject.SetActive(true);
|
||
string hpText = obj.MaxHealth > 0 ? $"{obj.CurrentHealth}/{obj.MaxHealth}" : "-/-";
|
||
npsUI.SetText(hpText, obj.Name ?? "", "");
|
||
float fill = obj.MaxHealth > 0 ? (float)obj.CurrentHealth / (float)obj.MaxHealth : 1f;
|
||
npsUI.SetHealthImage(fill);
|
||
currentTargetNPCID = obj.IDNPC;
|
||
}
|
||
|
||
private void OnTargetHUDClear(CECHostPlayer.TargetHUDClearEvent _)
|
||
{
|
||
npsUI.gameObject.SetActive(false);
|
||
}
|
||
|
||
public CDlgQuickBar GetCDlgQuickBar()
|
||
{
|
||
return m_pDlgQuickBar1;
|
||
}
|
||
|
||
private void TryHideUINPC(NPCDiedEvent obj)
|
||
{
|
||
if (obj.NPCID != currentTargetNPCID) return;
|
||
npsUI.gameObject.SetActive(false);
|
||
}
|
||
|
||
/// <summary>
|
||
/// Show UI by name of component ("DlgTask", "EC_InventoryUI"). When isStack is true, pushes the dialog onto the UI stack (brings to front and tracks for Pop).
|
||
/// </summary>
|
||
/// <param name="componentName">Name of component ("DlgTask", "EC_InventoryUI")</param>
|
||
/// <param name="isStack">If true, push onto stack (show + SetAsLastSibling + track); if false, just show.</param>
|
||
/// <param name="hideCurrentUI">just hide current ui- not pop</param>
|
||
public AUIDialog ShowUI(string componentName)
|
||
{
|
||
if (string.IsNullOrEmpty(componentName) || canvasDlg == null)
|
||
{
|
||
if (canvasDlg == null) Debug.LogError("canvasDlg is null");
|
||
return null;
|
||
}
|
||
|
||
var currentDialogue = GetCurrentDialog();
|
||
if (currentDialogue != null)
|
||
{
|
||
if (_uiStack.Count > 0 && string.Compare(_uiStack[0], componentName, StringComparison.Ordinal) == 0)
|
||
{
|
||
return currentDialogue;
|
||
}
|
||
currentDialogue.Show(false);
|
||
}
|
||
|
||
return Push(componentName);
|
||
}
|
||
|
||
public void HideCurrentUIInStack()
|
||
{
|
||
Pop();
|
||
//show next one
|
||
var currentDialogue = GetCurrentDialog();
|
||
if (currentDialogue != null)
|
||
{
|
||
currentDialogue.Show(true);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Push a dialog onto the UI stack: show it, add to front of stack, and SetAsLastSibling so it draws on top. If already in stack, moves it to front.
|
||
/// </summary>
|
||
private AUIDialog Push(string componentName)
|
||
{
|
||
if (string.IsNullOrEmpty(componentName) || canvasDlg == null) return null;
|
||
|
||
_uiStack.Remove(componentName);
|
||
|
||
if (_maxStack > 0 && _uiStack.Count >= _maxStack)
|
||
Pop();
|
||
|
||
var dlg = GetInGameUIMan().GetDialog(componentName);
|
||
if (dlg == null) return null;
|
||
|
||
dlg.Show(true);
|
||
_uiStack.Insert(0, componentName);
|
||
dlg.transform.SetAsLastSibling();
|
||
return dlg;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Pop the top dialog off the stack: hide it and bring the new top (if any) to front. Returns true if something was popped.
|
||
/// </summary>
|
||
private bool Pop()
|
||
{
|
||
if (_uiStack.Count == 0) return false;
|
||
|
||
string top = _uiStack[0];
|
||
_uiStack.RemoveAt(0);
|
||
|
||
var dlg = GetInGameUIMan().GetDialog(top);
|
||
if (dlg != null)
|
||
dlg.Show(false);
|
||
|
||
if (_uiStack.Count > 0)
|
||
{
|
||
var newTop = GetInGameUIMan().GetDialog(_uiStack[0]);
|
||
if (newTop != null)
|
||
newTop.transform.SetAsLastSibling();
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/// <summary>Returns the name of the dialog currently on top of the stack, or null if stack is empty.</summary>
|
||
public string GetCurrentUI()
|
||
{
|
||
if (_uiStack.Count == 0) return null;
|
||
return _uiStack[0];
|
||
}
|
||
|
||
/// <summary>Returns the dialog instance currently on top of the stack, or null if stack is empty.</summary>
|
||
public AUIDialog GetCurrentDialog()
|
||
{
|
||
var currentUI = GetCurrentUI();
|
||
if (currentUI == null) return null;
|
||
return GetInGameUIMan().GetDialog(currentUI);
|
||
}
|
||
|
||
/// <summary>Returns the number of dialogs in the stack (0 when empty).</summary>
|
||
public int GetStackCount() => _uiStack.Count;
|
||
|
||
/// <summary>Returns true if the given dialog name is in the stack.</summary>
|
||
public bool IsInStack(string componentName)
|
||
{
|
||
return !string.IsNullOrEmpty(componentName) && _uiStack.Contains(componentName);
|
||
}
|
||
|
||
/// <summary>Returns the dialog name at the given index (0 = top) without removing. Returns null if index is out of range.</summary>
|
||
public string PeekStack(int index = 0)
|
||
{
|
||
if (index < 0 || index >= _uiStack.Count) return null;
|
||
return _uiStack[index];
|
||
}
|
||
|
||
/// <summary>Clears the entire stack. If hideAll is true, hides every dialog in the stack before clearing.</summary>
|
||
public void ClearStack(bool hideAll = true)
|
||
{
|
||
if (hideAll)
|
||
{
|
||
var gui = GetInGameUIMan();
|
||
foreach (string name in _uiStack)
|
||
{
|
||
var dlg = gui?.GetDialog(name);
|
||
if (dlg != null) dlg.Show(false);
|
||
}
|
||
}
|
||
|
||
_uiStack.Clear();
|
||
}
|
||
|
||
public CDlgMessageBox ShowMessageBox(MessageBoxData messageBoxData)
|
||
{
|
||
var msgBox = GetInGameUIMan().GetDialog("DlgMessageBox") as CDlgMessageBox;
|
||
if (msgBox != null)
|
||
{
|
||
msgBox.ShowMessageBox(messageBoxData);
|
||
return msgBox;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("DlgMessageBox not found in InGameUIMan");
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
public CDlgMessageBox ShowMessageBox(string title, string message, MessageBoxType messageBoxType,
|
||
Action onClickedYes = null, Action onClickedNo = null)
|
||
{
|
||
var msgBox = GetInGameUIMan().GetDialog("DlgMessageBox") as CDlgMessageBox;
|
||
if (msgBox != null)
|
||
{
|
||
msgBox.ShowMessageBox(new MessageBoxData()
|
||
{
|
||
Title = title,
|
||
Message = message,
|
||
MessageBoxType = messageBoxType,
|
||
OnClickedYes = onClickedYes,
|
||
OnClickedNo = onClickedNo
|
||
});
|
||
return msgBox;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("DlgMessageBox not found in InGameUIMan");
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
public void UpdateSkillRelatedUI()
|
||
{
|
||
// ¸üм¼ÄÜÏà¹ØµÄ½çÃæÏÔʾ
|
||
|
||
if (m_pDlgQuickBar1)
|
||
m_pDlgQuickBar1.UpdateShortcuts();
|
||
|
||
/* if (m_pDlgSkillEdit != null && m_pDlgSkillEdit->IsShow())
|
||
{
|
||
// ¼¼Äܱ༽çÃæÖ»ÔÚ Show(true) µÄʱºò²ÅÄܸüÐÂ
|
||
m_pDlgSkillEdit->Show(false);
|
||
}*/
|
||
}
|
||
|
||
/// <summary>
|
||
/// Show skill tooltip with description near the clicked skill button.
|
||
/// </summary>
|
||
/// <param name="hintText">The skill description and requirements</param>
|
||
/// <param name="sourceButton">The button RectTransform to position near</param>
|
||
public void ShowSkillTooltip(string hintText, RectTransform sourceButton)
|
||
{
|
||
if (string.IsNullOrEmpty(hintText))
|
||
{
|
||
Debug.LogWarning("[CECUIManager] ShowSkillTooltip called with empty hint text");
|
||
return;
|
||
}
|
||
|
||
// Lazy-load the tooltip dialog
|
||
if (m_pDlgSkillTooltip == null)
|
||
{
|
||
var tooltip = GetInGameUIMan().GetDialog("CDlgInfoTooltip") as CDlgInfoTooltip;
|
||
if (tooltip != null)
|
||
{
|
||
m_pDlgSkillTooltip = tooltip;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning(
|
||
"[CECUIManager] CDlgSkillTooltip not found in dialog resource. Tooltip will not be displayed.");
|
||
return;
|
||
}
|
||
}
|
||
|
||
if (m_pDlgSkillTooltip != null)
|
||
{
|
||
m_pDlgSkillTooltip.ShowTooltip(hintText, sourceButton);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Hide the skill tooltip if it's currently visible.
|
||
/// </summary>
|
||
public void HideSkillTooltip()
|
||
{
|
||
if (m_pDlgSkillTooltip != null)
|
||
{
|
||
m_pDlgSkillTooltip.HideTooltip();
|
||
}
|
||
}
|
||
|
||
private void OnMessageBox(MessageBoxEvent messageBoxEvent)
|
||
{
|
||
BMLogger.LogError("CECUIManager OnMessageBox called");
|
||
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))
|
||
{
|
||
// TODO
|
||
// Cancel hotkey customize because hot key state is determinted by CECHostInputFilter
|
||
// which is shared between repick role
|
||
//
|
||
// if (m_pDlgSettingQuickKey->IsShow())
|
||
// m_pDlgSettingQuickKey->Show(false);
|
||
|
||
if( pSession.GameSession.IsConnected )
|
||
{
|
||
// TODO
|
||
// if (CECCrossServer::Instance().IsOnSpecialServer())
|
||
// g_pGame->GetGameRun()->GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutCrossServer());
|
||
// else
|
||
// g_pGame->GetGameRun()->GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutHalf());
|
||
|
||
EC_Game.GetGameRun().GetPendingLogOut().AppendForSaveConfig(new CECPendingLogoutHalf());
|
||
}
|
||
else
|
||
EC_Game.GetGameRun().SetLogoutFlag(2);
|
||
}
|
||
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);*/
|
||
}
|
||
}
|
||
else if (pDlg is DlgInstall dlgInstall && dlgInstall.GetInstallMode == DlgInstall.InstallMode.Disenchase &&
|
||
DialogBoxCommandIDs.IDOK == iRetVal)
|
||
{
|
||
UnityGameSession.c2s_CmdNPCSevClearEmbeddedChip(dlgInstall.FirstSlotIndex,
|
||
dlgInstall.SelectedEquip.GetTemplateID());
|
||
|
||
dlgInstall.Show(false);
|
||
pHost.EndNPCService();
|
||
// m_pCurNPCEssence = NULL;
|
||
// m_pDlgInventory->Show(false);
|
||
pHost.GetPack((int)InventoryType.IVTRTYPE_PACK).UnfreezeAllItems();
|
||
ShowMessageBox(new MessageBoxData()
|
||
{
|
||
Message = pDlg.GetStringFromTable(228)
|
||
});
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// Ẩn UI (disable thay vì destroy)
|
||
/// </summary>
|
||
// public void HideUI<T>() where T : Component
|
||
// {
|
||
// var type = typeof(T);
|
||
// if (_spawnedUIs.TryGetValue(type, out var uiGo))
|
||
// {
|
||
// uiGo.SetActive(false);
|
||
// }
|
||
// }
|
||
|
||
/// <summary>
|
||
/// Kiểm tra UI có đang active không
|
||
/// </summary>
|
||
public bool IsUIActive<T>() where T : Component
|
||
{
|
||
var type = typeof(T);
|
||
return _spawnedUIs.TryGetValue(type, out var uiGo) && uiGo.activeSelf;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Ẩn tất cả UI hiện tại
|
||
/// </summary>
|
||
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;
|
||
}
|
||
|
||
/// <summary>Shows the player options menu for the given character. Requires a prefab with id "DlgPlayerOptions" in DialogScriptTableObject.</summary>
|
||
public void ShowPlayerOptionsDialog(int characterId, Vector2 position)
|
||
{
|
||
if (characterId == 0 || canvasDlg == null) return;
|
||
var gui = GetInGameUIMan();
|
||
if (_dlgPlayerOptions == null)
|
||
_dlgPlayerOptions = gui.GetDialog("DlgPlayerOptions");
|
||
_dlgPlayerOptions?.ShowForPlayer(characterId);
|
||
_dlgPlayerOptions.transform.position = position;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Get the current target NPC ID (same as stored from NPCINFO event)
|
||
/// </summary>
|
||
public int GetCurrentTargetNPCID()
|
||
{
|
||
return currentTargetNPCID;
|
||
}
|
||
|
||
//todo: change this code to other place
|
||
private int slot = 0;
|
||
|
||
public Sprite[] IconlistIvtr
|
||
{
|
||
get
|
||
{
|
||
if (m_iconlistIvtr == null || m_iconlistIvtr.Length == 0)
|
||
{
|
||
m_iconlistIvtr = Resources.LoadAll<Sprite>("UI/IconSprites/iconlist_ivtrm_multisprite");
|
||
}
|
||
|
||
return m_iconlistIvtr;
|
||
}
|
||
}
|
||
|
||
public Sprite GetSpriteInListIvtr(string name)
|
||
{
|
||
foreach (var item in IconlistIvtr)
|
||
{
|
||
if (item.name.Equals(name))
|
||
{
|
||
return item;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
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();
|
||
}
|
||
}
|
||
|
||
public void OnClickFly()
|
||
{
|
||
CECHostPlayer hostPlayer = EC_Game.GetGameRun()?.GetHostPlayer();
|
||
if (hostPlayer != null)
|
||
{
|
||
hostPlayer.CmdFly(true);
|
||
}
|
||
}
|
||
|
||
public void OnChangeSkillShortcut()
|
||
{
|
||
CECHostPlayer hostPlayer = EC_Game.GetGameRun()?.GetHostPlayer();
|
||
if (hostPlayer != null)
|
||
{
|
||
hostPlayer.CycleSkillShortcuts();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Handle second-click button click - triggers attack or move to NPC / 处理第二次点击按钮 - 触发攻击或移动到NPC
|
||
/// Uses OnMsgLBtnClick with selected target to reuse existing logic / 使用OnMsgLBtnClick和选中的目标来重用现有逻辑
|
||
/// </summary>
|
||
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;
|
||
}
|
||
}
|
||
|
||
public void FilterBadWords(ref string str)
|
||
{
|
||
if (string.IsNullOrEmpty(str))
|
||
return;
|
||
|
||
string strLwr = str.ToLower();
|
||
|
||
char[] chars = str.ToCharArray();
|
||
|
||
foreach (string bad in gameUI.m_vecBadWords)
|
||
{
|
||
int pos = 0;
|
||
string badLwr = bad.ToLower();
|
||
|
||
while ((pos = strLwr.IndexOf(badLwr, pos, StringComparison.Ordinal)) >= 0)
|
||
{
|
||
for (int j = 0; j < badLwr.Length; j++)
|
||
{
|
||
chars[pos + j] = '*';
|
||
}
|
||
|
||
pos += badLwr.Length;
|
||
}
|
||
}
|
||
|
||
str = new string(chars);
|
||
}
|
||
} |