From 05a66d5cb0a9d55e9da4d55e2ce684c0662a0358 Mon Sep 17 00:00:00 2001
From: Grinch_ <user.grinch@gmail.com>
Date: Thu, 15 Dec 2022 11:22:34 +0600
Subject: [PATCH] Fix spawning under water with quick teleport

---
 resource/common/locale/English.toml |  2 ++
 src/interface/ipage.h               | 24 ++++++++++++++++++------
 src/pages/player.h                  |  2 ++
 src/pages/teleport.cpp              | 20 +++++++++++++++++++-
 src/pages/teleport.h                |  1 +
 5 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/resource/common/locale/English.toml b/resource/common/locale/English.toml
index ec58c89..e705c51 100644
--- a/resource/common/locale/English.toml
+++ b/resource/common/locale/English.toml
@@ -424,6 +424,8 @@ LocationHint = "Groove Street"
 LocationRemoved = "Location removed"
 QuickTeleport = "Quick teleport"
 QuickTeleportHint = "Open quick teleport using "
+SpawnUnderwater = "Spawn underwater"
+SpawnUnderwaterHint = "Spawn under the surface with quick teleport"
 TeleportMarkerHint = """
 Teleport to the location of your radar
 target blip using """
diff --git a/src/interface/ipage.h b/src/interface/ipage.h
index 0f5ae8d..9741a7c 100644
--- a/src/interface/ipage.h
+++ b/src/interface/ipage.h
@@ -59,11 +59,24 @@ private:
     bool m_bHasHeader;      // Does the page has a header button
     std::string m_NameKey;  // A key to the page name string
 
+protected:
+    // Loads data from toml file
+    // virtual void ImportSaveData();
+
+    // // Saves data to toml file
+    // virtual void ExportSaveData();
+
 public:
     IPage(ePageID page, const std::string& key, bool header)
     : m_eID(page), m_NameKey(key), m_bHasHeader(header)
     {
         PageHandler::AddPage(reinterpret_cast<PagePtr>(this), static_cast<size_t>(m_eID));
+        // ImportSaveData();
+    }
+
+    ~IPage()
+    {
+        // ExportSaveData();
     }
 
     // Page drawing code goes here
@@ -75,16 +88,15 @@ public:
         return m_eID;
     }
 
-    // Returns true if the page has a visible header button
-    virtual bool HasHeaderButton() final
-    {
-        return m_bHasHeader;
-    }
-
     // Returns the page name key
     virtual std::string GetPageKey() final
     {
         return m_NameKey;
     }
 
+    // Returns true if the page has a visible header button
+    virtual bool HasHeaderButton() final
+    {
+        return m_bHasHeader;
+    }
 };
\ No newline at end of file
diff --git a/src/pages/player.h b/src/pages/player.h
index 3772316..a672f7a 100644
--- a/src/pages/player.h
+++ b/src/pages/player.h
@@ -40,6 +40,8 @@ private:
 public:
 
     void Draw();
+    void ImportSaveData();
+    void ExportSaveData();
 };
 
 extern PlayerPage &playerPage;
diff --git a/src/pages/teleport.cpp b/src/pages/teleport.cpp
index f7312aa..e5829d2 100644
--- a/src/pages/teleport.cpp
+++ b/src/pages/teleport.cpp
@@ -49,6 +49,7 @@ TeleportPage::TeleportPage()
     {
         m_bTeleportMarker = gConfig.Get("Features.TeleportMarker", false);
         m_bQuickTeleport = gConfig.Get("Features.QuickTeleport", false);
+        m_bSpawnUnderwater = gConfig.Get("Features.SpawnUnderwater", false);
         m_fMapSize.x = gConfig.Get("Game.MapSizeX", 6000.0f);
         m_fMapSize.y = gConfig.Get("Game.MapSizeY", 6000.0f);
     };
@@ -147,8 +148,20 @@ void TeleportPage::WarpPlayer(CVector pos, int interiorID)
 
     if (Type == eTeleportType::Marker || Type == eTeleportType::MapPosition)
     {   
+        float ground, water;
         CEntity* pPlayerEntity = FindPlayerEntity(-1);
-        pos.z = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, 1000, nullptr, &pPlayerEntity) + 1.0f;
+        ground = CWorld::FindGroundZFor3DCoord(pos.x, pos.y, 1000, nullptr, &pPlayerEntity) + 1.0f;
+
+        if (m_bSpawnUnderwater)
+        {
+            pos.z = ground;
+        }
+        else
+        {
+            Command<Commands::GET_WATER_HEIGHT_AT_COORDS>(pos.x, pos.y, true, &water);
+            pos.z = ground > water ? ground : water;
+        }
+        
     }
 
     if (pVeh && pPlayer->m_nPedFlags.bInVehicle)
@@ -282,6 +295,11 @@ void TeleportPage::Draw()
                     gConfig.Set("Features.QuickTeleport", m_bQuickTeleport);
                 }
                 ImGui::NextColumn();
+                if (Widget::Checkbox(TEXT("Teleport.SpawnUnderwater"), &m_bSpawnUnderwater,
+                                        TEXT("Teleport.SpawnUnderwaterHint")))
+                {
+                    gConfig.Set("Features.SpawnUnderwater", m_bSpawnUnderwater);
+                }
                 if (Widget::Checkbox(TEXT("Teleport.TeleportMarker"), &m_bTeleportMarker,
                                         std::string(TEXT_S("Teleport.TeleportMarkerHint") 
                                                     + teleportMarker.GetNameString()).c_str()))
diff --git a/src/pages/teleport.h b/src/pages/teleport.h
index 0881547..0026cdf 100644
--- a/src/pages/teleport.h
+++ b/src/pages/teleport.h
@@ -16,6 +16,7 @@ private:
     bool m_bInsertCoord;
     bool m_bTeleportMarker;
     bool m_bQuickTeleport;
+    bool m_bSpawnUnderwater;
     ImVec2 m_fMapSize;
 #ifdef GTASA