using System.Collections.Generic; using BrewMonster.Network; using CSNetwork.Common; using CSNetwork.GPDataType; using ModelRenderer.Scripts.Common; using UnityEngine; using UnityEngine.UI; namespace BrewMonster.UI { public class DlgWorldMap : AUIDialog { [SerializeField] private Image mapImage; [SerializeField] private Image _hostPlayerPositionImage; [Space(10)] [SerializeField] private float _positionFactor = 2f; [SerializeField] private Button _closeButton; [Space(10)] [Header("Transmit Points")] [SerializeField] private RectTransform _transPointButtonParent; // this is the prefab for the trans point button [SerializeField] private WorldMapTransPoint _transPointButtonPrefab; private Dictionary _transPoints = new(); // 世界 / World const int MAJOR_MAP = 1; // 仙魔 / Good Evil // Tiên Ma static bool GOOD_EVIL_MAP(int id) { return id == 121 || id == 122; } // 城战 / Guild War // Thành Chiến static bool GUILD_WAR_MAP(int id) { return id >= 230 && id <= 235; } // 蓬莱 / Penglai // Bồng Lai static bool PENGLAI_MAP(int id) { return id == 137; } static bool IS_MAP_MARKABLE(int mapID) { return MAJOR_MAP == mapID || GOOD_EVIL_MAP(mapID) || GUILD_WAR_MAP(mapID) || PENGLAI_MAP(mapID); } public override void Awake() { base.Awake(); _closeButton.onClick.AddListener(OnCloseButtonClicked); } public override void Show(bool value) { base.Show(value); if (value) { UpdateHostPlayerPositionImage(); } } public override void CloseDialogue() { base.CloseDialogue(); // hide all the trans points foreach(var transPoint in _transPoints) { transPoint.Value.gameObject.SetActive(false); } } public override bool Render() { UpdateHostPlayerPositionImage(); return base.Render(); } Vector3 _hostPlayerPosition; Quaternion _hostPlayerRotation; private void UpdateHostPlayerPositionImage() { if (_hostPlayerPositionImage == null) { return; } if (!TryGetHostPlayerPosition(out _hostPlayerPosition, out _hostPlayerRotation)) { _hostPlayerPositionImage.enabled = false; return; } if (Mathf.Approximately(_positionFactor, 0f)) { BMLogger.LogError("DlgWorldMap _positionFactor cannot be zero."); _hostPlayerPositionImage.enabled = false; return; } _hostPlayerPositionImage.enabled = true; RectTransform hostPlayerRectTransform = _hostPlayerPositionImage.rectTransform; hostPlayerRectTransform.anchoredPosition = new Vector2( _hostPlayerPosition.x / _positionFactor, _hostPlayerPosition.z / _positionFactor); hostPlayerRectTransform.localRotation = Quaternion.Euler(0, 0, -_hostPlayerRotation.eulerAngles.y); } /// /// If use use Transmit Scroll or Transmit Service, we have to show the transmit points on the map. /// private void ShowTranPoints() { CECGameUIMan pGameUI = CECUIManager.Instance.GetInGameUIMan(); var transPoints = pGameUI.GetMapDlgsMgr().m_transPoints; WorldMapTransPoint transPointObject = null; int currentMapId = (int)GetDataPtr("WorldID"); foreach(var transPointPair in transPoints) { // check if the trans point is already created. If not, create it. if(_transPoints.TryGetValue(transPointPair.Key, out transPointObject)) { // now enable the trans point object transPointObject.gameObject.SetActive(true); } else { // create the trans point object transPointObject = Instantiate(_transPointButtonPrefab, _transPointButtonParent); transPointObject.Init(this, transPointPair.Key); transPointObject.GetComponent().anchoredPosition = new Vector2(transPointPair.Value.vecPos.x / _positionFactor, transPointPair.Value.vecPos.z / _positionFactor); _transPoints[transPointPair.Key] = transPointObject; transPointObject.gameObject.SetActive(true); } } } private bool TryGetHostPlayerPosition(out Vector3 hostPlayerPosition, out Quaternion hostPlayerRotation) { hostPlayerPosition = Vector3.zero; hostPlayerRotation = Quaternion.identity; CECHostPlayer hostPlayer = GetHostPlayer(); if (hostPlayer == null || hostPlayer.transform == null) { return false; } hostPlayerPosition = hostPlayer.transform.position; hostPlayerRotation = hostPlayer.transform.rotation; return true; } public void BuildTravelMap(uint dwType, object pData) { // default world id int worldid = MAJOR_MAP; // select the correct map background // PAUIIMAGEPICTURE pImage = (PAUIIMAGEPICTURE)GetDlgItem("WorldMapTravel"); // prepare the necessary information SetData(dwType); // CECMapDlgsMgr *pMgr = GetGameUIMan()->GetMapDlgsMgr(); // ÖØÐ¿ªÊ¼¼ÆËã´«ËÍÏß· // pMgr->ResetTransWay(); if(dwType == (uint)DATA_TYPE.DT_NPC_TRANSMIT_SERVICE) { var serviceData = (NPC_TRANSMIT_SERVICE)pData; var worldInstanceName = UnityGameSession.Instance.GetWorldInstanceName((int)serviceData.id); // save the worldid SetDataPtr(worldid, "WorldID"); // pMgr->LoadMapTexture(m_pA3DDevice, pImage, CECMapDlgsMgr::MAP_TYPE_TRANSMIT); ShowTranPoints(); } else if(dwType == (uint)DATA_TYPE.DT_TRANSMITSCROLL_ESSENCE) { // save the slot info // SetDataPtr(pData, "ItemSlot"); // pMgr->LoadMapTexture(m_pA3DDevice, pImage, CECMapDlgsMgr::MAP_TYPE_SCROLL); } else { // invalid transmit type BMLogger.LogError($"Invalid transmit type: {dwType}"); } } /// /// When user click on the map texture. /// We will calculate the world coordinates from the local cursor position. Then move the host player to the world coordinates. /// /// public void OnMapClicked(Vector2 localCursorPosition) { var worldCoordinates = localCursorPosition * _positionFactor; UnityGameSession.c2s_CmdGoto(worldCoordinates.x, 1.0f, worldCoordinates.y); // close the map OnCloseButtonClicked(); } public void OnTransPointClicked(int id) { var transPoints = CECUIManager.Instance.GetInGameUIMan().GetMapDlgsMgr().m_transPoints; if(transPoints.TryGetValue(id, out var transPoint)) { UnityGameSession.c2s_CmdGoto(transPoint.vecPos.x, transPoint.vecPos.y, transPoint.vecPos.z); // close the map OnCloseButtonClicked(); } } private void OnCloseButtonClicked() { CloseDialogue(); } } public struct TRANS_POINT { public int id; public int worldid; public string strName; public A3DVECTOR3 vecPos; }; public enum TransMode { TM_INVALID = 0, TM_TRANSMITSCROLL = 1, // 通过传送卷轴传送 / Transmit scroll TM_NPC_TRANSMIT_NORMAL = 2, // 通过 NPC 传送服务、向当前 NPC 连接点传送 / Transmit service to the current NPC connection point TM_NPC_TRANSMIT_DIRECT = 3, // 通过 NPC 传送服务、向当前 NPC 可达点直接传送 / Transmit service to the current NPC reachable point directly }; public class CECMapDlgsMgr { public int m_nCurFlagIndex; public bool m_bMarking; public bool m_bMapDragging; public List m_vecTeamMate = new(); public Dictionary m_transPoints = new(); // update player way-points public void UpdateWayPoints(ushort[] pData, uint iSize, bool bClear) { var vecTarget = GlobalTransmitData.globaldata_gettranstargets; if(bClear) { m_transPoints.Clear(); } // got valid points. for(int i = 0; i < iSize; i++ ) { int idThis = pData[i];//*(pData+i); for(int j = 0; j < vecTarget.Count; j++ ) { if( idThis != vecTarget[j].id ) continue; TRANS_POINT tp; tp.id = idThis; tp.strName = vecTarget[j].Name; tp.vecPos = vecTarget[j].vecPos; tp.worldid = vecTarget[j].world_id; m_transPoints[idThis] = tp; break; } } } } public class TransWay { public const int WAYPOINT_ME = 0; public const int WAYPOINT_TARGET = 1; public const int MINIMAP_UL = 0; public const int MINIMAP_UR = 1; public const int MINIMAP_LL = 2; public const int MINIMAP_LR = 3; public const int MINIMAP_MAX = 4; // The transmission mode to use when sending the transmission protocol (TM_NPC_TRANSMIT_NORMAL =2 and the number of wayPoints is greater than 1 may be true at the same time) public TransMode mode; // 发送传送协议时应使用的传送模式(TM_NPC_TRANSMIT_NORMAL =2 与 wayPoints 个数大于1可能同时成立) public int nCost; // 需要的完美币 / The required perfect coin public int nLevel; // 需求的等级 / The required level // The transmission route (excluding the start point and including the end point) (can be used for display in all modes, can only be used for protocol in TM_NPC_TRANSMIT_DIRECT mode) public List wayPoints = new(); // 传送路线(不含起点、包括终点)(各模式下均可用于显示,TM_NPC_TRANSMIT_DIRECT 模式下才可用于协议) } }