// ==================== CUSTOM FUNCTIONS ==================== //

        /*
         * AddWorldMarker
         * Adds a simple MapWorldMarker on a new gameobject as a child for the specified GameObject.
         * Returns the MapWorldMarker component.
         */
        public MapWorldMarker AddWorldMarker(GameObject go, string name)
        {
            var markerHolder = new GameObject("MarkerHolder");

            markerHolder.transform.parent   = go.transform;
            markerHolder.transform.position = go.transform.position;

            // setup the marker
            MapWorldMarker marker = markerHolder.AddComponent <MapWorldMarker>();

            marker.ShowCircle = true;
            marker.AlignLeft  = false;
            marker.Text       = name;

            // check if we need to add another text holder
            var markerTexts = At.GetValue(typeof(MapDisplay), MapDisplay.Instance, "m_markerTexts") as MapWorldMarkerDisplay[];
            var mapMarkers  = At.GetValue(typeof(MapDisplay), MapDisplay.Instance, "m_mapWorldMarkers") as List <MapWorldMarker>;

            if (markerTexts.Length < mapMarkers.Count)
            {
                AddTextHolder(markerTexts);
            }

            return(marker);
        }
            public static Exception Finalizer(MapDisplay __instance, Exception __exception)
            {
                var self = __instance;

                bool flag = !(self.CurrentMapScene.MarkerOffset == Vector2.zero) || !(self.CurrentMapScene.MarkerScale == Vector2.zero);

                if (flag)
                {
                    // update EnemyMarker positions
                    float zoomLevelSmooth = (float)At.GetValue(typeof(MapDisplay), MapDisplay.Instance, "m_zoomLevelSmooth");
                    for (int i = 0; i < Instance.EnemyMarkers.Count; i++)
                    {
                        Instance.EnemyMarkers[i].CalculateMapPosition(MapDisplay.Instance.CurrentMapScene, i, zoomLevelSmooth * 1.0351562f);
                        At.SetValue(Instance.EnemyMarkers[i].MapPosition, typeof(EnemyMarker), Instance.EnemyMarkers[i], "m_adjustedMapPosition");
                    }
                }

                // update enemy marker texts
                for (int i = 0; i < Instance.m_enemyTexts.Count; i++)
                {
                    if (i < Instance.EnemyMarkers.Count)
                    {
                        if (!Instance.m_enemyTexts[i].gameObject.activeSelf)
                        {
                            Instance.m_enemyTexts[i].SetActive(true);
                        }
                        Instance.m_enemyTexts[i].UpdateDisplay(Instance.EnemyMarkers[i]);
                    }
                    else
                    {
                        if (Instance.m_enemyTexts[i].gameObject.activeSelf)
                        {
                            Instance.m_enemyTexts[i].SetActive(false);
                        }
                    }
                }

                //if (__exception != null)
                //{
                //    Debug.Log("MapDisplay.UpdateWorldMarkers had an exception!");
                //    Debug.Log(__exception.ToString());
                //}

                return(null);
            }
            public static void Postfix(MapDisplay __instance)
            {
                var self = __instance;

                bool flag = !(self.CurrentMapScene.MarkerOffset == Vector2.zero) || !(self.CurrentMapScene.MarkerScale == Vector2.zero);

                if (flag)
                {
                    // update EnemyMarker positions
                    float zoomLevelSmooth = (float)At.GetValue(typeof(MapDisplay), MapDisplay.Instance, "m_zoomLevelSmooth");
                    for (int i = 0; i < Instance.EnemyMarkers.Count; i++)
                    {
                        Instance.EnemyMarkers[i].CalculateMapPosition(MapDisplay.Instance.CurrentMapScene, i, zoomLevelSmooth * 1.0351562f);
                        At.SetValue(Instance.EnemyMarkers[i].MapPosition, typeof(EnemyMarker), Instance.EnemyMarkers[i], "m_adjustedMapPosition");
                    }
                }

                // update enemy marker texts
                for (int i = 0; i < Instance.m_enemyTexts.Count; i++)
                {
                    if (i < Instance.EnemyMarkers.Count)
                    {
                        if (!Instance.m_enemyTexts[i].gameObject.activeSelf)
                        {
                            Instance.m_enemyTexts[i].SetActive(true);
                        }
                        Instance.m_enemyTexts[i].UpdateDisplay(Instance.EnemyMarkers[i]);
                    }
                    else
                    {
                        if (Instance.m_enemyTexts[i].gameObject.activeSelf)
                        {
                            Instance.m_enemyTexts[i].SetActive(false);
                        }
                    }
                }
            }
            public static void Postfix(MapDisplay __instance, CharacterUI _owner)
            {
                var self = __instance;

                Instance.m_mapID = (int)At.GetValue(typeof(MapDisplay), self, "m_currentMapSceneID");

                if (!(bool)At.GetValue(typeof(MapDisplay), self, "m_currentAreaHasMap"))
                {
                    return;
                }

                if (MapConfigs.ContainsKey(Instance.m_mapID))
                {
                    self.CurrentMapScene.MarkerOffset = MapConfigs[Instance.m_mapID].MarkerOffset;
                    self.CurrentMapScene.Rotation     = MapConfigs[Instance.m_mapID].Rotation;
                    self.CurrentMapScene.MarkerScale  = MapConfigs[Instance.m_mapID].MarkerScale;
                }

                var list = CharacterManager.Instance.Characters.Values
                           .Where(x =>
                                  !x.GetComponentInChildren <MapWorldMarker>() &&
                                  !x.IsDead &&
                                  x.gameObject.activeSelf);

                foreach (Character c in list)
                {
                    // player markers
                    if ((bool)config.GetValue("ShowPlayerMarkers") && !c.IsAI)
                    {
                        Instance.AddWorldMarker(c.gameObject, c.Name);
                    }
                    // enemy markers
                    if ((bool)config.GetValue("ShowEnemyMarkers") && c.IsAI)
                    {
                        Instance.AddEnemyWorldMarker(c.gameObject, c.Name);
                    }
                }
                // caravanner
                if ((bool)config.GetValue("ShowSoroboreanCaravanner"))
                {
                    var caravanner = GameObject.Find("HumanSNPC_CaravanTrader");

                    if (!caravanner)
                    {
                        caravanner = GameObject.Find("UNPC_CaravanTraderA");
                    }

                    if (caravanner && !caravanner.GetComponentInChildren <MapWorldMarker>())
                    {
                        Instance.AddWorldMarker(caravanner, "Soroborean Caravanner");
                    }
                }
                // player bags
                if ((bool)config.GetValue("ShowPlayerBagMarkers"))
                {
                    foreach (PlayerSystem ps in Global.Lobby.PlayersInLobby)
                    {
                        var c = ps.ControlledCharacter;
                        if (c.Inventory.Equipment.LastOwnedBag != null && c.Inventory.Equipment.LastOwnedBag.OwnerCharacter == null)
                        {
                            var tempObject = new GameObject("TempBagHolder");
                            tempObject.transform.position = c.Inventory.Equipment.LastOwnedBag.transform.position;
                            var marker = Instance.AddWorldMarker(tempObject, c.Name + "'s Bag");
                            Instance.m_bagMarkers.Add(marker);
                        }
                    }
                }

                ////unmarked dungeons
                //if (ModBase.settings.Show_Unmarked_Dungeons && MapConfigs.ContainsKey(m_mapID))
                //{
                //    var disabledObjects = FindDisabledGameObjectsByName(MapConfigs[m_mapID].UnmarkedDungeonObjects.Keys.ToList());

                //    for (int i = 0; i < MapConfigs[m_mapID].UnmarkedDungeonObjects.Count; i++)
                //    {
                //        var entry = MapConfigs[m_mapID].UnmarkedDungeonObjects.ElementAt(i);
                //        var go = disabledObjects[i];

                //        AddIconMarker(go, entry.Value);
                //    }
                //}

                return;
            }
            public static void Postfix(MapDisplay __instance, CharacterUI _owner)
            {
                var self = __instance;

                Instance.m_mapID = (int)At.GetValue(typeof(MapDisplay), self, "m_currentMapSceneID");

                if (!(bool)At.GetValue(typeof(MapDisplay), self, "m_currentAreaHasMap"))
                {
                    return;
                }

                //Debug.LogWarning("Current map ID: " + Instance.m_mapID);

                if (MapConfigs.ContainsKey(Instance.m_mapID))
                {
                    self.CurrentMapScene.MarkerOffset = MapConfigs[Instance.m_mapID].MarkerOffset;
                    self.CurrentMapScene.Rotation     = MapConfigs[Instance.m_mapID].Rotation;
                    self.CurrentMapScene.MarkerScale  = MapConfigs[Instance.m_mapID].MarkerScale;
                }

                // caldera node finder

                //var nodes = Resources.FindObjectsOfTypeAll<Gatherable>()
                //                     .Where(it => it.gameObject.scene.name == SceneManagerHelper.ActiveSceneName
                //                               && it.Name.Contains("Unidentified")
                //                               && !it.gameObject.GetComponent<MapWorldMarker>());

                //foreach (var node in nodes)
                //{
                //    var parent = node.transform.parent.parent;
                //    foreach (Transform child in parent)
                //    {
                //        if (child.name.Contains("Pos"))
                //        {
                //            string s;
                //            if (node.Name.Contains("Molepig"))
                //                s = "M";
                //            else if (node.Name.Contains("Ore"))
                //                s = "O";
                //            else
                //                s = "P";
                //            var id = parent.name.Substring(parent.name.Length - 1, 1);
                //            Instance.AddEnemyWorldMarker(child.gameObject, $"{s}{id}");
                //        }
                //    }
                //}

                var list = CharacterManager.Instance.Characters.Values
                           .Where(x =>
                                  !x.GetComponentInChildren <MapWorldMarker>() &&
                                  !x.IsDead &&
                                  x.gameObject.activeSelf);

                foreach (Character c in list)
                {
                    // player markers
                    if ((bool)config.GetValue("ShowPlayerMarkers") && !c.IsAI)
                    {
                        Instance.AddWorldMarker(c.gameObject, c.Name);
                    }
                    // enemy markers
                    if ((bool)config.GetValue("ShowEnemyMarkers") && c.IsAI)
                    {
                        Instance.AddEnemyWorldMarker(c.gameObject, c.Name);
                    }
                }
                // caravanner
                if ((bool)config.GetValue("ShowSoroboreanCaravanner"))
                {
                    var caravanner = GameObject.Find("HumanSNPC_CaravanTrader");

                    if (!caravanner)
                    {
                        caravanner = GameObject.Find("UNPC_CaravanTraderA");
                    }

                    if (caravanner && !caravanner.GetComponentInChildren <MapWorldMarker>())
                    {
                        Instance.AddWorldMarker(caravanner, "Soroborean Caravanner");
                    }
                }
                // player bags
                if ((bool)config.GetValue("ShowPlayerBagMarkers"))
                {
                    foreach (PlayerSystem ps in Global.Lobby.PlayersInLobby)
                    {
                        var c = ps.ControlledCharacter;
                        if (c.Inventory.Equipment.LastOwnedBag != null && c.Inventory.Equipment.LastOwnedBag.OwnerCharacter == null)
                        {
                            var tempObject = new GameObject("TempBagHolder");
                            tempObject.transform.position = c.Inventory.Equipment.LastOwnedBag.transform.position;
                            var marker = Instance.AddWorldMarker(tempObject, c.Name + "'s Bag");
                            Instance.m_bagMarkers.Add(marker);
                        }
                    }
                }

                ////unmarked dungeons
                //if (ModBase.settings.Show_Unmarked_Dungeons && MapConfigs.ContainsKey(m_mapID))
                //{
                //    var disabledObjects = FindDisabledGameObjectsByName(MapConfigs[m_mapID].UnmarkedDungeonObjects.Keys.ToList());

                //    for (int i = 0; i < MapConfigs[m_mapID].UnmarkedDungeonObjects.Count; i++)
                //    {
                //        var entry = MapConfigs[m_mapID].UnmarkedDungeonObjects.ElementAt(i);
                //        var go = disabledObjects[i];

                //        AddIconMarker(go, entry.Value);
                //    }
                //}

                return;
            }