mirror of
https://github.com/Mr-X-GTA/YimMenu.git
synced 2024-12-22 12:07:46 +08:00
Refactor how blips work (#3473)
This commit is contained in:
parent
64700270bf
commit
710edb87a7
@ -1,14 +1,14 @@
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
gtav_classes
|
||||
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
|
||||
GIT_TAG 06c58d9c11a9a22336947fbe430d5f4951ff34d7
|
||||
GIT_PROGRESS TRUE
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
)
|
||||
message("GTAV-Classes")
|
||||
if(NOT gtav_classes_POPULATED)
|
||||
FetchContent_Populate(gtav_classes)
|
||||
endif()
|
||||
include(FetchContent)
|
||||
|
||||
FetchContent_Declare(
|
||||
gtav_classes
|
||||
GIT_REPOSITORY https://github.com/Yimura/GTAV-Classes.git
|
||||
GIT_TAG a91475c198c59eff04de26929e83d86521299dda
|
||||
GIT_PROGRESS TRUE
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
)
|
||||
message("GTAV-Classes")
|
||||
if(NOT gtav_classes_POPULATED)
|
||||
FetchContent_Populate(gtav_classes)
|
||||
endif()
|
||||
|
@ -909,7 +909,7 @@ namespace big
|
||||
float fov = 60.f;
|
||||
float distance = 200.f;
|
||||
int32_t selected_bone = (int32_t)ePedBoneType::HEAD;
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(aimbot, enable, only_on_ped_type, only_on_player, only_on_enemy, fov, distance, selected_bone)
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(aimbot, enable, only_on_ped_type, only_on_player, only_on_enemy, fov, distance, selected_bone, use_weapon_range)
|
||||
} aimbot{};
|
||||
|
||||
struct flying_axe
|
||||
|
@ -1,60 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "natives.hpp"
|
||||
|
||||
namespace rage
|
||||
{
|
||||
#pragma pack(push, 1)
|
||||
class Blip_t
|
||||
{
|
||||
public:
|
||||
int32_t m_id; //0x0000
|
||||
uint16_t m_blip_array_index;//0x0004
|
||||
char pad_0006[4]; //0x0006
|
||||
bool m_active; //0x000A
|
||||
uint8_t N00000197; //0x000B
|
||||
int32_t m_entity_id; //0x000C
|
||||
float m_x; //0x0010
|
||||
float m_y; //0x0014
|
||||
float m_z; //0x0018
|
||||
char pad_001C[4]; //0x001C
|
||||
uint32_t m_display_bits; //0x0020
|
||||
uint32_t m_render_bits; //0x0024
|
||||
char* m_message; //0x0028
|
||||
char pad_0030[8]; //0x0030
|
||||
Hash m_description; //0x0038
|
||||
char pad_003C[4]; //0x003C
|
||||
int32_t m_icon; //0x0040
|
||||
int16_t m_flash_interval; //0x0044
|
||||
int16_t m_flash_timer; //0x0046
|
||||
uint32_t m_color; //0x0048
|
||||
uint32_t m_secondary_color; //0x004C
|
||||
float m_scale_x; //0x0050
|
||||
float m_scale_y; //0x0054
|
||||
float m_rotation; //0x0058
|
||||
uint8_t m_mission_bits; //0x005C
|
||||
uint8_t m_priority; //0x005D
|
||||
uint8_t m_display_id; //0x005E
|
||||
uint8_t m_alpha; //0x005F
|
||||
int8_t m_category; //0x0060
|
||||
int8_t m_show_number; //0x0061
|
||||
char pad_0062[14]; //0x0062
|
||||
}; //Size: 0x0070
|
||||
static_assert(sizeof(Blip_t) == 0x70, "Blip_t is not sized properly.");
|
||||
#pragma pack(pop)
|
||||
|
||||
class BlipEntry
|
||||
{
|
||||
public:
|
||||
Blip_t* m_pBlip;//0x0000
|
||||
|
||||
};//Size=0x0008
|
||||
|
||||
class BlipList
|
||||
{
|
||||
public:
|
||||
BlipEntry m_Blips[1500];//0x0000
|
||||
char _0x2EE0[56];
|
||||
|
||||
};//Size=0x2F18
|
||||
}
|
@ -1044,8 +1044,12 @@ enum class BlipColors
|
||||
WaypointColor = 0x54
|
||||
};
|
||||
|
||||
enum BlipDisplayBits
|
||||
enum BlipDisplayBits : uint32_t
|
||||
{
|
||||
BlipIsFlashing = (1 << 2),
|
||||
BlipIsGPSRoute = (1 << 4),
|
||||
BlipShowHeightMarker = (1 << 5),
|
||||
BlipsIsDirectional = (1 << 11),
|
||||
BlipShowCheckmark = (1 << 16),
|
||||
BlipShowDollarSign = (1 << 17),
|
||||
BlipShowHeadingIndicator = (1 << 18),
|
||||
|
84
src/util/blip.cpp
Normal file
84
src/util/blip.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
#include "blip.hpp"
|
||||
|
||||
namespace big::blip
|
||||
{
|
||||
bool get_blip_location(Vector3& location, int sprite, int color)
|
||||
{
|
||||
Blip blip;
|
||||
for (blip = HUD::GET_CLOSEST_BLIP_INFO_ID(sprite); HUD::DOES_BLIP_EXIST(blip) && color != -1 && HUD::GET_BLIP_COLOUR(blip) != color; blip = HUD::GET_NEXT_BLIP_INFO_ID(sprite))
|
||||
;
|
||||
|
||||
if (!HUD::DOES_BLIP_EXIST(blip) || (color != -1 && HUD::GET_BLIP_COLOUR(blip) != color))
|
||||
return false;
|
||||
|
||||
location = HUD::GET_BLIP_COORDS(blip);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_objective_location_iteration(Vector3& location, const std::unordered_set<BlipIcons> sprites, const std::unordered_set<BlipColors> blip_colors = {})
|
||||
{
|
||||
for (int i = 0; i < 1500; i++)
|
||||
{
|
||||
auto blip = g_pointers->m_gta.m_blip_list->m_Blips[i].m_pBlip;
|
||||
if (blip != nullptr
|
||||
&& ((sprites.contains((BlipIcons)blip->m_icon)
|
||||
&& (blip_colors.empty() || blip_colors.contains((BlipColors)blip->m_color)))
|
||||
|| (blip->m_display_bits & BlipIsGPSRoute)))
|
||||
{
|
||||
location.x = blip->m_position.x;
|
||||
location.y = blip->m_position.y;
|
||||
location.z = blip->m_position.z;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
location = {};
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get_blip_location_from_offset(Vector3& location, int sprite)
|
||||
{
|
||||
Blip blip = HUD::GET_CLOSEST_BLIP_INFO_ID(sprite);
|
||||
if (HUD::DOES_BLIP_EXIST(blip))
|
||||
{
|
||||
location = HUD::GET_BLIP_COORDS(blip);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool get_objective_location(Vector3& location)
|
||||
{
|
||||
if (get_objective_location_iteration(location, {BlipIcons::Circle}, {BlipColors::YellowMission, BlipColors::YellowMission2, BlipColors::Mission}))
|
||||
return true;
|
||||
if (get_objective_location_iteration(location, {BlipIcons::RaceFinish}, {BlipColors::None}))
|
||||
return true;
|
||||
if (get_objective_location_iteration(location, {BlipIcons::Circle}, {BlipColors::Green, BlipColors::Blue}))
|
||||
return true;
|
||||
if (get_objective_location_iteration(location, {BlipIcons::CrateDrop}))
|
||||
return true;
|
||||
|
||||
auto blip_icons = {0, 1, 2, 143, 144, 145, 146, 280, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 535, 536, 537, 538, 539, 540, 541, 542};
|
||||
for (const auto& icon : blip_icons)
|
||||
{
|
||||
if (get_blip_location_from_offset(location, icon))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
rage::CBlip* get_selected_blip()
|
||||
{
|
||||
for (int i = 0; i < 1500; i++)
|
||||
{
|
||||
auto blip = g_pointers->m_gta.m_blip_list->m_Blips[i].m_pBlip;
|
||||
if (blip && (blip->m_display_bits & BlipIsSelected))
|
||||
{
|
||||
return blip;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
@ -1,65 +1,19 @@
|
||||
#pragma once
|
||||
#include "gta/enums.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "script.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "ui/blip_t.hpp"
|
||||
#include "ui/CBlipList.hpp"
|
||||
|
||||
namespace big::blip
|
||||
{
|
||||
inline bool get_blip_location(Vector3& location, int sprite, int color = -1)
|
||||
{
|
||||
Blip blip;
|
||||
for (blip = HUD::GET_FIRST_BLIP_INFO_ID(sprite); HUD::DOES_BLIP_EXIST(blip) && color != -1 && HUD::GET_BLIP_COLOUR(blip) != color; blip = HUD::GET_NEXT_BLIP_INFO_ID(sprite))
|
||||
;
|
||||
|
||||
if (!HUD::DOES_BLIP_EXIST(blip) || (color != -1 && HUD::GET_BLIP_COLOUR(blip) != color))
|
||||
return false;
|
||||
|
||||
location = HUD::GET_BLIP_COORDS(blip);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool get_objective_location(Vector3& location)
|
||||
{
|
||||
if (get_blip_location(location, (int)BlipIcons::Circle, (int)BlipColors::YellowMission))
|
||||
return true;
|
||||
if (get_blip_location(location, (int)BlipIcons::Circle, (int)BlipColors::YellowMission2))
|
||||
return true;
|
||||
if (get_blip_location(location, (int)BlipIcons::Circle, (int)BlipColors::Mission))
|
||||
return true;
|
||||
if (get_blip_location(location, (int)BlipIcons::RaceFinish, (int)BlipColors::None))
|
||||
return true;
|
||||
if (get_blip_location(location, (int)BlipIcons::Circle, (int)BlipColors::Green))
|
||||
return true;
|
||||
if (get_blip_location(location, (int)BlipIcons::Circle, (int)BlipColors::Blue))
|
||||
return true;
|
||||
if (get_blip_location(location, (int)BlipIcons::CrateDrop))
|
||||
return true;
|
||||
|
||||
static const int blips[] = {1, 57, 128, 129, 130, 143, 144, 145, 146, 271, 286, 287, 288};
|
||||
for (const auto& blip : blips)
|
||||
{
|
||||
if (get_blip_location(location, blip, 5))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline rage::Blip_t* get_selected_blip()
|
||||
{
|
||||
for (int i = 0; i < 1500; i++)
|
||||
{
|
||||
|
||||
auto blip = g_pointers->m_gta.m_blip_list->m_Blips[i].m_pBlip;
|
||||
if (blip && (blip->m_display_bits & BlipDisplayBits::BlipIsSelected))
|
||||
{
|
||||
return blip;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#pragma once
|
||||
#include "gta/enums.hpp"
|
||||
#include "natives.hpp"
|
||||
#include "pointers.hpp"
|
||||
#include "script.hpp"
|
||||
#include "ui/CBlipList.hpp"
|
||||
|
||||
namespace big::blip
|
||||
{
|
||||
bool get_blip_location(Vector3& location, int sprite, int color = -1);
|
||||
|
||||
bool get_objective_location_iteration(Vector3& location, const std::unordered_set<BlipIcons> sprites, const std::unordered_set<BlipColors> blip_colors);
|
||||
|
||||
bool get_blip_location_from_offset(Vector3& location, int sprite);
|
||||
|
||||
bool get_objective_location(Vector3& location);
|
||||
|
||||
rage::CBlip* get_selected_blip();
|
||||
}
|
@ -236,7 +236,7 @@ namespace big::teleport
|
||||
{
|
||||
entity = self::veh;
|
||||
}
|
||||
ENTITY::SET_ENTITY_COORDS_NO_OFFSET(entity, blip->m_x, blip->m_y, blip->m_z, FALSE, FALSE, TRUE);
|
||||
ENTITY::SET_ENTITY_COORDS_NO_OFFSET(entity, blip->m_position.x, blip->m_position.y, blip->m_position.z, FALSE, FALSE, TRUE);
|
||||
ENTITY::SET_ENTITY_HEADING(entity, blip->m_rotation);
|
||||
|
||||
return false;
|
||||
|
@ -1,211 +1,211 @@
|
||||
#include "services/custom_teleport/custom_teleport_service.hpp"
|
||||
#include "util/math.hpp"
|
||||
#include "util/teleport.hpp"
|
||||
#include "util/blip.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
telelocation get_location_player_is_closest_to()
|
||||
{
|
||||
if (!g_local_player || !g_local_player->m_navigation || g_custom_teleport_service.all_saved_locations.empty())
|
||||
return {};
|
||||
|
||||
Vector3 transformed_vector = Vector3(g_local_player->m_navigation->get_position()->x,
|
||||
g_local_player->m_navigation->get_position()->y,
|
||||
g_local_player->m_navigation->get_position()->z);
|
||||
|
||||
float distance = 500;
|
||||
telelocation closest_location{};
|
||||
//saved_locations_filtered_list can be used to get a joint list of all categories when the filter is empty.
|
||||
for (auto& loc : g_custom_teleport_service.saved_locations_filtered_list())
|
||||
{
|
||||
float new_distance = math::distance_between_vectors(transformed_vector, {loc.x, loc.y, loc.z});
|
||||
|
||||
if (new_distance < distance)
|
||||
closest_location = loc, distance = new_distance;
|
||||
}
|
||||
|
||||
return closest_location;
|
||||
}
|
||||
|
||||
float get_distance_to_telelocation(telelocation t)
|
||||
{
|
||||
return math::distance_between_vectors(Vector3(t.x,t.y,t.z), Vector3(g_local_player->m_navigation->get_position()->x,
|
||||
g_local_player->m_navigation->get_position()->y,
|
||||
g_local_player->m_navigation->get_position()->z));
|
||||
}
|
||||
|
||||
void view::custom_teleport()
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
static std::string new_location_name{};
|
||||
static std::string category = "Default";
|
||||
static telelocation deletion_telelocation;
|
||||
static std::string filter{};
|
||||
|
||||
if (!std::string(deletion_telelocation.name).empty())
|
||||
ImGui::OpenPopup("##deletelocation");
|
||||
|
||||
if (ImGui::BeginPopupModal("##deletelocation", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGui::Text("VIEW_SELF_ANIMATIONS_ARE_YOU_SURE_DELETE"_T.data(), deletion_telelocation.name);
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Button("YES"_T.data()))
|
||||
{
|
||||
g_custom_teleport_service.delete_saved_location(category, deletion_telelocation.name);
|
||||
deletion_telelocation.name = "";
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("NO"_T.data()))
|
||||
{
|
||||
deletion_telelocation.name = "";
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(300);
|
||||
components::input_text_with_hint("VIEW_SELF_ANIMATIONS_CATEGORY"_T, "VIEW_SELF_ANIMATIONS_CATEGORY_DESC"_T, category);
|
||||
components::input_text_with_hint("VIEW_SELF_CUSTOM_TELEPORT_LOCATION"_T, "VIEW_SELF_CUSTOM_TELEPORT_LOCATION_DESC"_T, new_location_name);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
components::button("VIEW_SELF_CUSTOM_TELEPORT_SAVE_CURRENT_LOCATION"_T, [] {
|
||||
if (new_location_name.empty())
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "VIEW_SELF_CUSTOM_TELEPORT_INVALID_NAME"_T.data());
|
||||
}
|
||||
else if (g_custom_teleport_service.get_saved_location_by_name(new_location_name))
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), std::vformat("VIEW_SELF_CUSTOM_TELEPORT_LOCATION_ALREADY_EXISTS"_T, std::make_format_args(new_location_name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
telelocation teleport_location;
|
||||
Entity teleport_entity = self::ped;
|
||||
if (self::veh != 0)
|
||||
teleport_entity = self::veh;
|
||||
auto coords = ENTITY::GET_ENTITY_COORDS(teleport_entity, TRUE);
|
||||
teleport_location.name = new_location_name;
|
||||
teleport_location.x = coords.x;
|
||||
teleport_location.y = coords.y;
|
||||
teleport_location.z = coords.z;
|
||||
teleport_location.yaw = ENTITY::GET_ENTITY_HEADING(teleport_entity);
|
||||
teleport_location.pitch = CAM::GET_GAMEPLAY_CAM_RELATIVE_PITCH();
|
||||
teleport_location.roll = CAM::GET_GAMEPLAY_CAM_RELATIVE_HEADING();
|
||||
g_custom_teleport_service.save_new_location(category, teleport_location);
|
||||
}
|
||||
});
|
||||
ImGui::SameLine();
|
||||
components::button("VIEW_SELF_CUSTOM_TELEPORT_SAVE_BLIP"_T, [] {
|
||||
if (new_location_name.empty())
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "VIEW_SELF_CUSTOM_TELEPORT_INVALID_NAME"_T.data());
|
||||
}
|
||||
else if (g_custom_teleport_service.get_saved_location_by_name(new_location_name))
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), std::vformat("VIEW_SELF_CUSTOM_TELEPORT_LOCATION_ALREADY_EXISTS"_T, std::make_format_args(new_location_name)));
|
||||
}
|
||||
else if (!*g_pointers->m_gta.m_is_session_started)
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "TELEPORT_NOT_ONLINE"_T.data());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
telelocation teleport_location;
|
||||
auto blip = blip::get_selected_blip();
|
||||
if (blip == nullptr)
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "VIEW_SELF_CUSTOM_TELEPORT_INVALID_BLIP"_T.data());
|
||||
return;
|
||||
}
|
||||
teleport_location.name = new_location_name;
|
||||
teleport_location.x = blip->m_x;
|
||||
teleport_location.y = blip->m_y;
|
||||
teleport_location.z = blip->m_z;
|
||||
teleport_location.yaw = blip->m_rotation;
|
||||
teleport_location.pitch = 0.0f;
|
||||
teleport_location.roll = 0.0f;
|
||||
g_custom_teleport_service.save_new_location(category, teleport_location);
|
||||
}
|
||||
});
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
components::small_text("VIEW_SELF_CUSTOM_TELEPORT_DOUBLE_CLICK_TO_TELEPORT"_T);
|
||||
components::small_text("VIEW_SELF_ANIMATIONS_DOUBLE_SHIFT_CLICK_TO_DELETE"_T);
|
||||
|
||||
ImGui::Spacing();
|
||||
components::input_text_with_hint("##filter", "SEARCH"_T, filter);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
components::small_text("VIEW_SELF_ANIMATIONS_CATEGORIES"_T);
|
||||
if (ImGui::BeginListBox("##categories", {250, static_cast<float>(*g_pointers->m_gta.m_resolution_y * 0.5)}))
|
||||
{
|
||||
for (auto& l : g_custom_teleport_service.all_saved_locations | std::ranges::views::keys)
|
||||
{
|
||||
if (ImGui::Selectable(l.data(), l == category))
|
||||
{
|
||||
category = l;
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
components::small_text("VIEW_SELF_CUSTOM_TELEPORT_LOCATIONS"_T);
|
||||
if (ImGui::BeginListBox("##telelocations", {250, static_cast<float>(*g_pointers->m_gta.m_resolution_y * 0.5)}))
|
||||
{
|
||||
if (g_custom_teleport_service.all_saved_locations.find(category)
|
||||
!= g_custom_teleport_service.all_saved_locations.end())
|
||||
{
|
||||
std::vector<telelocation> current_list{};
|
||||
|
||||
if (!filter.empty())
|
||||
current_list = g_custom_teleport_service.saved_locations_filtered_list(filter);
|
||||
else
|
||||
current_list = g_custom_teleport_service.all_saved_locations.at(category);
|
||||
|
||||
for (const auto& l : current_list)
|
||||
{
|
||||
if (ImGui::Selectable(l.name.data(), l.name == get_location_player_is_closest_to().name, ImGuiSelectableFlags_AllowDoubleClick))
|
||||
{
|
||||
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
|
||||
{
|
||||
deletion_telelocation = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
g_fiber_pool->queue_job([l] {
|
||||
teleport::teleport_player_to_coords(g_player_service->get_self(), {l.x, l.y, l.z}, {l.yaw, l.pitch, l.roll});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
if (l.name.length() > 27)
|
||||
ImGui::Text(l.name.data());
|
||||
ImGui::Text(std::format("{}: {}", "VIEW_SELF_CUSTOM_TELEPORT_DISTANCE"_T, get_distance_to_telelocation(l)).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
}
|
||||
#include "services/custom_teleport/custom_teleport_service.hpp"
|
||||
#include "util/math.hpp"
|
||||
#include "util/teleport.hpp"
|
||||
#include "util/blip.hpp"
|
||||
#include "views/view.hpp"
|
||||
|
||||
namespace big
|
||||
{
|
||||
telelocation get_location_player_is_closest_to()
|
||||
{
|
||||
if (!g_local_player || !g_local_player->m_navigation || g_custom_teleport_service.all_saved_locations.empty())
|
||||
return {};
|
||||
|
||||
Vector3 transformed_vector = Vector3(g_local_player->m_navigation->get_position()->x,
|
||||
g_local_player->m_navigation->get_position()->y,
|
||||
g_local_player->m_navigation->get_position()->z);
|
||||
|
||||
float distance = 500;
|
||||
telelocation closest_location{};
|
||||
//saved_locations_filtered_list can be used to get a joint list of all categories when the filter is empty.
|
||||
for (auto& loc : g_custom_teleport_service.saved_locations_filtered_list())
|
||||
{
|
||||
float new_distance = math::distance_between_vectors(transformed_vector, {loc.x, loc.y, loc.z});
|
||||
|
||||
if (new_distance < distance)
|
||||
closest_location = loc, distance = new_distance;
|
||||
}
|
||||
|
||||
return closest_location;
|
||||
}
|
||||
|
||||
float get_distance_to_telelocation(telelocation t)
|
||||
{
|
||||
return math::distance_between_vectors(Vector3(t.x,t.y,t.z), Vector3(g_local_player->m_navigation->get_position()->x,
|
||||
g_local_player->m_navigation->get_position()->y,
|
||||
g_local_player->m_navigation->get_position()->z));
|
||||
}
|
||||
|
||||
void view::custom_teleport()
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
static std::string new_location_name{};
|
||||
static std::string category = "Default";
|
||||
static telelocation deletion_telelocation;
|
||||
static std::string filter{};
|
||||
|
||||
if (!std::string(deletion_telelocation.name).empty())
|
||||
ImGui::OpenPopup("##deletelocation");
|
||||
|
||||
if (ImGui::BeginPopupModal("##deletelocation", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGui::Text("VIEW_SELF_ANIMATIONS_ARE_YOU_SURE_DELETE"_T.data(), deletion_telelocation.name);
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Button("YES"_T.data()))
|
||||
{
|
||||
g_custom_teleport_service.delete_saved_location(category, deletion_telelocation.name);
|
||||
deletion_telelocation.name = "";
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("NO"_T.data()))
|
||||
{
|
||||
deletion_telelocation.name = "";
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(300);
|
||||
components::input_text_with_hint("VIEW_SELF_ANIMATIONS_CATEGORY"_T, "VIEW_SELF_ANIMATIONS_CATEGORY_DESC"_T, category);
|
||||
components::input_text_with_hint("VIEW_SELF_CUSTOM_TELEPORT_LOCATION"_T, "VIEW_SELF_CUSTOM_TELEPORT_LOCATION_DESC"_T, new_location_name);
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
components::button("VIEW_SELF_CUSTOM_TELEPORT_SAVE_CURRENT_LOCATION"_T, [] {
|
||||
if (new_location_name.empty())
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "VIEW_SELF_CUSTOM_TELEPORT_INVALID_NAME"_T.data());
|
||||
}
|
||||
else if (g_custom_teleport_service.get_saved_location_by_name(new_location_name))
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), std::vformat("VIEW_SELF_CUSTOM_TELEPORT_LOCATION_ALREADY_EXISTS"_T, std::make_format_args(new_location_name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
telelocation teleport_location;
|
||||
Entity teleport_entity = self::ped;
|
||||
if (self::veh != 0)
|
||||
teleport_entity = self::veh;
|
||||
auto coords = ENTITY::GET_ENTITY_COORDS(teleport_entity, TRUE);
|
||||
teleport_location.name = new_location_name;
|
||||
teleport_location.x = coords.x;
|
||||
teleport_location.y = coords.y;
|
||||
teleport_location.z = coords.z;
|
||||
teleport_location.yaw = ENTITY::GET_ENTITY_HEADING(teleport_entity);
|
||||
teleport_location.pitch = CAM::GET_GAMEPLAY_CAM_RELATIVE_PITCH();
|
||||
teleport_location.roll = CAM::GET_GAMEPLAY_CAM_RELATIVE_HEADING();
|
||||
g_custom_teleport_service.save_new_location(category, teleport_location);
|
||||
}
|
||||
});
|
||||
ImGui::SameLine();
|
||||
components::button("VIEW_SELF_CUSTOM_TELEPORT_SAVE_BLIP"_T, [] {
|
||||
if (new_location_name.empty())
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "VIEW_SELF_CUSTOM_TELEPORT_INVALID_NAME"_T.data());
|
||||
}
|
||||
else if (g_custom_teleport_service.get_saved_location_by_name(new_location_name))
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), std::vformat("VIEW_SELF_CUSTOM_TELEPORT_LOCATION_ALREADY_EXISTS"_T, std::make_format_args(new_location_name)));
|
||||
}
|
||||
else if (!*g_pointers->m_gta.m_is_session_started)
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "TELEPORT_NOT_ONLINE"_T.data());
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
telelocation teleport_location;
|
||||
auto blip = blip::get_selected_blip();
|
||||
if (blip == nullptr)
|
||||
{
|
||||
g_notification_service.push_warning("GUI_TAB_CUSTOM_TELEPORT"_T.data(), "VIEW_SELF_CUSTOM_TELEPORT_INVALID_BLIP"_T.data());
|
||||
return;
|
||||
}
|
||||
teleport_location.name = new_location_name;
|
||||
teleport_location.x = blip->m_position.x;
|
||||
teleport_location.y = blip->m_position.y;
|
||||
teleport_location.z = blip->m_position.z;
|
||||
teleport_location.yaw = blip->m_rotation;
|
||||
teleport_location.pitch = 0.0f;
|
||||
teleport_location.roll = 0.0f;
|
||||
g_custom_teleport_service.save_new_location(category, teleport_location);
|
||||
}
|
||||
});
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
components::small_text("VIEW_SELF_CUSTOM_TELEPORT_DOUBLE_CLICK_TO_TELEPORT"_T);
|
||||
components::small_text("VIEW_SELF_ANIMATIONS_DOUBLE_SHIFT_CLICK_TO_DELETE"_T);
|
||||
|
||||
ImGui::Spacing();
|
||||
components::input_text_with_hint("##filter", "SEARCH"_T, filter);
|
||||
|
||||
ImGui::BeginGroup();
|
||||
components::small_text("VIEW_SELF_ANIMATIONS_CATEGORIES"_T);
|
||||
if (ImGui::BeginListBox("##categories", {250, static_cast<float>(*g_pointers->m_gta.m_resolution_y * 0.5)}))
|
||||
{
|
||||
for (auto& l : g_custom_teleport_service.all_saved_locations | std::ranges::views::keys)
|
||||
{
|
||||
if (ImGui::Selectable(l.data(), l == category))
|
||||
{
|
||||
category = l;
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
components::small_text("VIEW_SELF_CUSTOM_TELEPORT_LOCATIONS"_T);
|
||||
if (ImGui::BeginListBox("##telelocations", {250, static_cast<float>(*g_pointers->m_gta.m_resolution_y * 0.5)}))
|
||||
{
|
||||
if (g_custom_teleport_service.all_saved_locations.find(category)
|
||||
!= g_custom_teleport_service.all_saved_locations.end())
|
||||
{
|
||||
std::vector<telelocation> current_list{};
|
||||
|
||||
if (!filter.empty())
|
||||
current_list = g_custom_teleport_service.saved_locations_filtered_list(filter);
|
||||
else
|
||||
current_list = g_custom_teleport_service.all_saved_locations.at(category);
|
||||
|
||||
for (const auto& l : current_list)
|
||||
{
|
||||
if (ImGui::Selectable(l.name.data(), l.name == get_location_player_is_closest_to().name, ImGuiSelectableFlags_AllowDoubleClick))
|
||||
{
|
||||
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
|
||||
{
|
||||
deletion_telelocation = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
g_fiber_pool->queue_job([l] {
|
||||
teleport::teleport_player_to_coords(g_player_service->get_self(), {l.x, l.y, l.z}, {l.yaw, l.pitch, l.roll});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
if (l.name.length() > 27)
|
||||
ImGui::Text(l.name.data());
|
||||
ImGui::Text(std::format("{}: {}", "VIEW_SELF_CUSTOM_TELEPORT_DISTANCE"_T, get_distance_to_telelocation(l)).c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user