mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-10 03:43:15 +08:00
feat(hotkeys): implement hotkeys and more
This commit is contained in:
@@ -88,43 +88,52 @@ namespace YimMenu
|
||||
MarkStateDirty();
|
||||
}
|
||||
|
||||
void HotkeySystem::Update()
|
||||
void HotkeySystem::RunScriptImpl()
|
||||
{
|
||||
for (auto& [hash, link] : m_CommandHotkeys)
|
||||
while (g_Running)
|
||||
{
|
||||
if (link.m_Chain.empty() || link.m_BeingModified)
|
||||
continue;
|
||||
|
||||
bool all_keys_pressed = true;
|
||||
|
||||
for (auto modifier : link.m_Chain)
|
||||
for (auto& [hash, link] : m_CommandHotkeys)
|
||||
{
|
||||
if (!(GetAsyncKeyState(modifier) & 0x8000))
|
||||
if (link.m_Chain.empty() || link.m_BeingModified)
|
||||
continue;
|
||||
|
||||
bool all_keys_pressed = true;
|
||||
|
||||
for (auto modifier : link.m_Chain)
|
||||
{
|
||||
all_keys_pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_keys_pressed && std::chrono::system_clock::now() - m_LastHotkeyTriggerTime > 100ms)
|
||||
{
|
||||
auto command = Commands::GetCommand(hash);
|
||||
if (command)
|
||||
{
|
||||
// TODO: this is the only way I can prevent chat from blocking the main loop while keeping everything else fast
|
||||
if (hash != "chathelper"_J)
|
||||
command->Call();
|
||||
else
|
||||
if (!(GetAsyncKeyState(modifier) & 0x8000))
|
||||
{
|
||||
FiberPool::Push([command] {
|
||||
command->Call();
|
||||
});
|
||||
all_keys_pressed = false;
|
||||
}
|
||||
}
|
||||
m_LastHotkeyTriggerTime = std::chrono::system_clock::now();
|
||||
|
||||
if (all_keys_pressed && std::chrono::system_clock::now() - m_LastHotkeyTriggerTime > 100ms)
|
||||
{
|
||||
auto command = Commands::GetCommand(hash);
|
||||
if (command)
|
||||
{
|
||||
// TODO: this is the only way I can prevent chat from blocking the main loop while keeping everything else fast
|
||||
if (hash != "chathelper"_J)
|
||||
command->Call();
|
||||
else
|
||||
{
|
||||
FiberPool::Push([command] {
|
||||
command->Call();
|
||||
});
|
||||
}
|
||||
}
|
||||
m_LastHotkeyTriggerTime = std::chrono::system_clock::now();
|
||||
}
|
||||
}
|
||||
ScriptMgr::Yield();
|
||||
}
|
||||
}
|
||||
|
||||
void HotkeySystem::RunScript()
|
||||
{
|
||||
g_HotkeySystem.RunScriptImpl();
|
||||
}
|
||||
|
||||
void HotkeySystem::SaveStateImpl(nlohmann::json& state)
|
||||
{
|
||||
for (auto& hotkey : m_CommandHotkeys)
|
||||
|
||||
@@ -26,7 +26,8 @@ namespace YimMenu
|
||||
std::string GetHotkeyLabel(int hotkey_modifiers);
|
||||
void CreateHotkey(std::vector<int>& Hotkey);
|
||||
|
||||
void Update();
|
||||
void RunScriptImpl();
|
||||
static void RunScript();
|
||||
|
||||
virtual void SaveStateImpl(nlohmann::json& state) override;
|
||||
virtual void LoadStateImpl(nlohmann::json& state) override;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace YimMenu
|
||||
|
||||
const char* LogSink::GetLevelStr(const eLogLevel level)
|
||||
{
|
||||
constexpr std::array<const char*, 4> levelStrings = {{{"DEBUG"}, {"INFO"}, {"WARN"}, {"ERROR"}}};
|
||||
constexpr std::array<const char*, 4> levelStrings = {"DEBUG", "INFO", "WARN", "ERROR"};
|
||||
|
||||
return levelStrings[level];
|
||||
}
|
||||
|
||||
@@ -31,10 +31,12 @@ namespace YimMenu
|
||||
|
||||
ImGui::DestroyContext();
|
||||
|
||||
#if 0
|
||||
// manually destroy the allocators we created for the rest of the frame contexts
|
||||
for (size_t i = 1; i < m_SwapChainDesc.BufferCount; ++i)
|
||||
if (m_FrameContext[i].CommandAllocator)
|
||||
m_FrameContext[i].CommandAllocator->Release();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Renderer::InitDX12()
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "SavedLocations.hpp"
|
||||
|
||||
#include "core/filemgr/FileMgr.hpp"
|
||||
#include "core/frontend/Notifications.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
std::filesystem::path SavedLocations::GetSavedLocationsFilePath()
|
||||
{
|
||||
return FileMgr::GetProjectFile("./saved_locations.json").Path();
|
||||
}
|
||||
|
||||
std::vector<SavedLocation> SavedLocations::SavedLocationsFilteredListImpl(std::string filter)
|
||||
{
|
||||
std::vector<SavedLocation> filterList{};
|
||||
|
||||
static auto toLower = [=](std::string text) -> std::string {
|
||||
std::transform(text.begin(), text.end(), text.begin(), ::tolower);
|
||||
return text;
|
||||
};
|
||||
|
||||
for (auto& location : m_AllSavedLocations | std::views::values | std::views::join)
|
||||
if (toLower(location.name).find(toLower(filter)) != std::string::npos)
|
||||
filterList.push_back(location);
|
||||
|
||||
return filterList;
|
||||
}
|
||||
|
||||
bool SavedLocations::FetchSavedLocationsImpl()
|
||||
{
|
||||
m_AllSavedLocations.clear();
|
||||
|
||||
auto path = GetSavedLocationsFilePath();
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
|
||||
try
|
||||
{
|
||||
if (!file.is_open())
|
||||
return false;
|
||||
|
||||
nlohmann::json j;
|
||||
file >> j;
|
||||
m_AllSavedLocations = j.get<std::map<std::string, std::vector<SavedLocation>>>();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG(WARNING) << "Failed fetching saved locations: " << e.what() << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SavedLocations::SaveNewLocationImpl(const std::string& category, SavedLocation t)
|
||||
{
|
||||
const auto& pair = m_AllSavedLocations.insert({category, {t}});
|
||||
if (!pair.second)
|
||||
{
|
||||
pair.first->second.push_back(t);
|
||||
}
|
||||
|
||||
auto path = GetSavedLocationsFilePath();
|
||||
|
||||
std::ofstream fileOut(path, std::ofstream::trunc | std::ofstream::binary);
|
||||
if (!fileOut.is_open())
|
||||
return false;
|
||||
|
||||
nlohmann::json j = m_AllSavedLocations;
|
||||
fileOut << j.dump(4);
|
||||
fileOut.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SavedLocations::DeleteSavedLocationImpl(const std::string& category, const std::string& locationName)
|
||||
{
|
||||
auto path = GetSavedLocationsFilePath();
|
||||
|
||||
const auto& it = m_AllSavedLocations.find(category);
|
||||
if (it == m_AllSavedLocations.end())
|
||||
return false;
|
||||
|
||||
std::erase_if(it->second, [locationName](SavedLocation t) {
|
||||
return t.name == locationName;
|
||||
});
|
||||
|
||||
if (!it->second.size())
|
||||
{
|
||||
m_AllSavedLocations.erase(category);
|
||||
}
|
||||
|
||||
std::ofstream fileOut(path, std::ofstream::trunc | std::ofstream::binary);
|
||||
if (!fileOut.is_open())
|
||||
return false;
|
||||
|
||||
nlohmann::json j = m_AllSavedLocations;
|
||||
fileOut << j.dump(4);
|
||||
fileOut.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SavedLocation* SavedLocations::GetSavedLocationByNameImpl(std::string name)
|
||||
{
|
||||
for (auto& loc : SavedLocationsFilteredList())
|
||||
if (loc.name == name)
|
||||
return &loc;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
struct SavedLocation
|
||||
{
|
||||
std::string name;
|
||||
float x, y, z;
|
||||
float yaw = 0.0f, pitch = 0.0f, roll = 0.0f;
|
||||
};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(SavedLocation, name, x, y, z, yaw, pitch, roll);
|
||||
|
||||
class SavedLocations
|
||||
{
|
||||
private:
|
||||
std::filesystem::path GetSavedLocationsFilePath();
|
||||
std::map<std::string, std::vector<SavedLocation>> m_AllSavedLocations;
|
||||
|
||||
private:
|
||||
bool FetchSavedLocationsImpl();
|
||||
bool SaveNewLocationImpl(const std::string& category, SavedLocation t);
|
||||
bool DeleteSavedLocationImpl(const std::string& category, const std::string& location_name);
|
||||
SavedLocation* GetSavedLocationByNameImpl(std::string);
|
||||
std::vector<SavedLocation> SavedLocationsFilteredListImpl(std::string filter = "");
|
||||
|
||||
static SavedLocations& GetInstance()
|
||||
{
|
||||
static SavedLocations instance{};
|
||||
return instance;
|
||||
}
|
||||
|
||||
public:
|
||||
static std::map<std::string, std::vector<SavedLocation>>& GetAllSavedLocations()
|
||||
{
|
||||
return GetInstance().m_AllSavedLocations;
|
||||
}
|
||||
|
||||
static bool FetchSavedLocations()
|
||||
{
|
||||
return GetInstance().FetchSavedLocationsImpl();
|
||||
};
|
||||
|
||||
static bool SaveNewLocation(const std::string& category, SavedLocation t)
|
||||
{
|
||||
return GetInstance().SaveNewLocationImpl(category, t);
|
||||
};
|
||||
|
||||
static bool DeleteSavedLocation(const std::string& category, const std::string& location_name)
|
||||
{
|
||||
return GetInstance().DeleteSavedLocationImpl(category, location_name);
|
||||
};
|
||||
|
||||
static SavedLocation* GetSavedLocationByName(std::string location_name)
|
||||
{
|
||||
return GetInstance().GetSavedLocationByNameImpl(location_name);
|
||||
};
|
||||
|
||||
static std::vector<SavedLocation> SavedLocationsFilteredList(std::string filter = "")
|
||||
{
|
||||
return GetInstance().SavedLocationsFilteredListImpl(filter);
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "core/commands/LoopedCommand.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/gta/Scripts.hpp"
|
||||
#include "types/script/globals/GlobalPlayerBD.hpp"
|
||||
|
||||
namespace YimMenu::Features
|
||||
{
|
||||
class OffTheRadar : public LoopedCommand
|
||||
{
|
||||
using LoopedCommand::LoopedCommand;
|
||||
|
||||
virtual void OnTick() override
|
||||
{
|
||||
if (auto gpbd = GlobalPlayerBD::Get(); gpbd && Scripts::SafeToModifyFreemodeBroadcastGlobals())
|
||||
gpbd->Entries[Self::GetPlayer().GetId()].OffRadarActive = true;
|
||||
}
|
||||
|
||||
virtual void OnDisable() override
|
||||
{
|
||||
if (auto gpbd = GlobalPlayerBD::Get(); gpbd && Scripts::SafeToModifyFreemodeBroadcastGlobals())
|
||||
gpbd->Entries[Self::GetPlayer().GetId()].OffRadarActive = false;
|
||||
}
|
||||
};
|
||||
|
||||
static OffTheRadar _OffTheRadar{"otr", "Off The Radar", "Hides you from other players on the radar"};
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
#include "core/commands/Command.hpp"
|
||||
#include "core/backend/ScriptMgr.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/gta/Natives.hpp"
|
||||
#include "core/frontend/Notifications.hpp"
|
||||
|
||||
namespace YimMenu::Features
|
||||
{
|
||||
void ResolveZCoordinate(Vector3& vec)
|
||||
{
|
||||
constexpr float max_ground_check = 1000.f;
|
||||
constexpr int max_attempts = 20;
|
||||
float ground_z = vec.z;
|
||||
int current_attempts = 0;
|
||||
|
||||
do
|
||||
{
|
||||
STREAMING::REQUEST_COLLISION_AT_COORD(vec.x, vec.y, vec.z);
|
||||
|
||||
float water_height;
|
||||
if (WATER::GET_WATER_HEIGHT(vec.x, vec.y, vec.z, &water_height))
|
||||
{
|
||||
vec.z = water_height;
|
||||
return;
|
||||
}
|
||||
|
||||
if (MISC::GET_GROUND_Z_FOR_3D_COORD(vec.x, vec.y, max_ground_check, &ground_z, false, false))
|
||||
{
|
||||
vec.z = ground_z + 1.0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_attempts % 3 == 0)
|
||||
{
|
||||
ground_z += 25.f;
|
||||
}
|
||||
|
||||
++current_attempts;
|
||||
ScriptMgr::Yield();
|
||||
} while (current_attempts < max_attempts);
|
||||
|
||||
vec.z = PATHFIND::GET_APPROX_HEIGHT_FOR_POINT(vec.x, vec.y); // fallback value
|
||||
}
|
||||
|
||||
class TpToWaypoint : public Command
|
||||
{
|
||||
using Command::Command;
|
||||
|
||||
virtual void OnCall() override
|
||||
{
|
||||
if (!HUD::IS_WAYPOINT_ACTIVE())
|
||||
Notifications::Show("Teleport", "No waypoint set", NotificationType::Warning);
|
||||
|
||||
auto coords = HUD::GET_BLIP_COORDS(HUD::GET_CLOSEST_BLIP_INFO_ID(HUD::GET_WAYPOINT_BLIP_ENUM_ID()));
|
||||
ResolveZCoordinate(coords);
|
||||
Self::GetPed().TeleportTo(coords);
|
||||
}
|
||||
};
|
||||
|
||||
static TpToWaypoint _TpToWaypoint{"tptowaypoint", "Teleport to Waypoint", "Teleports you to the waypoint"};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "core/commands/LoopedCommand.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
|
||||
namespace YimMenu::Features
|
||||
{
|
||||
class KeepFixed : public LoopedCommand
|
||||
{
|
||||
using LoopedCommand::LoopedCommand;
|
||||
|
||||
virtual void OnTick() override
|
||||
{
|
||||
auto veh = Self::GetVehicle();
|
||||
if (veh)
|
||||
veh.Fix();
|
||||
}
|
||||
};
|
||||
|
||||
static KeepFixed _KeepFixed{"keepfixed", "Keep Vehicle Fixed", "Keeps your vehicle clean and fixed"};
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "core/commands/LoopedCommand.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/gta/Natives.hpp"
|
||||
|
||||
namespace YimMenu::Features
|
||||
{
|
||||
class Speedometer : public LoopedCommand
|
||||
{
|
||||
using LoopedCommand::LoopedCommand;
|
||||
int m_ScaleformHandle{};
|
||||
|
||||
bool EnsureScaleformLoaded()
|
||||
{
|
||||
if (m_ScaleformHandle && GRAPHICS::HAS_SCALEFORM_MOVIE_LOADED(m_ScaleformHandle))
|
||||
return true;
|
||||
|
||||
if (!m_ScaleformHandle)
|
||||
m_ScaleformHandle = GRAPHICS::REQUEST_SCALEFORM_MOVIE("DRAG_RACE");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetVehicleSpeed(Vehicle veh)
|
||||
{
|
||||
auto speed = veh.GetSpeed();
|
||||
|
||||
if (MISC::SHOULD_USE_METRIC_MEASUREMENTS())
|
||||
return speed * 3.6f;
|
||||
else
|
||||
return speed * 2.23694f;
|
||||
}
|
||||
|
||||
virtual void OnTick() override
|
||||
{
|
||||
auto veh = Self::GetVehicle();
|
||||
|
||||
if (!veh || !EnsureScaleformLoaded() || STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS())
|
||||
return;
|
||||
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_GEAR");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(veh.GetGear());
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_SPEED");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_INT(GetVehicleSpeed(veh));
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_SPEED_UNITS");
|
||||
GRAPHICS::BEGIN_TEXT_COMMAND_SCALEFORM_STRING("STRING");
|
||||
HUD::ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME(MISC::SHOULD_USE_METRIC_MEASUREMENTS() ? "KPH" : "MPH");
|
||||
GRAPHICS::END_TEXT_COMMAND_SCALEFORM_STRING();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_METER_VALUE");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(veh.GetSpeed() * 2000);
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_OUTER_GOAL");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(-1.0f);
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(-1.0f);
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_INNER_GOAL");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(-1.0f);
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(-1.0f);
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_SCREEN_POSITION");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(1.0f);
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_FLOAT(0.85f);
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::BEGIN_SCALEFORM_MOVIE_METHOD(m_ScaleformHandle, "SET_IS_DRIFT_RACE");
|
||||
GRAPHICS::SCALEFORM_MOVIE_METHOD_ADD_PARAM_BOOL(false);
|
||||
GRAPHICS::END_SCALEFORM_MOVIE_METHOD();
|
||||
GRAPHICS::DRAW_SCALEFORM_MOVIE_FULLSCREEN(m_ScaleformHandle, 255, 255, 255, 255, 0);
|
||||
}
|
||||
|
||||
virtual void OnDisable() override
|
||||
{
|
||||
GRAPHICS::SET_SCALEFORM_MOVIE_AS_NO_LONGER_NEEDED(&m_ScaleformHandle);
|
||||
}
|
||||
};
|
||||
|
||||
static Speedometer _Speedometer{"speedometer", "Speedometer", "Shows a speedometer whenever you are in a vehicle"};
|
||||
}
|
||||
@@ -8,8 +8,10 @@
|
||||
#include "game/frontend/fonts/Fonts.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
#include "submenus/Self.hpp"
|
||||
#include "submenus/Teleport.hpp"
|
||||
#include "submenus/Network.hpp"
|
||||
#include "submenus/Players.hpp"
|
||||
#include "submenus/Settings.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
@@ -17,8 +19,10 @@ namespace YimMenu
|
||||
{
|
||||
// Arguably the only place this file should be edited at for more menus
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Self>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Teleport>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Network>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Players>());
|
||||
UIManager::AddSubmenu(std::make_shared<Submenus::Settings>());
|
||||
|
||||
Renderer::AddRendererCallBack(
|
||||
[&] {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "core/commands/BoolCommand.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
#include "game/gta/invoker/Invoker.hpp"
|
||||
#include "game/gta/Natives.hpp"
|
||||
|
||||
namespace YimMenu::Features
|
||||
{
|
||||
@@ -14,7 +15,6 @@ namespace YimMenu
|
||||
{
|
||||
void Overlay::Draw()
|
||||
{
|
||||
#if 0
|
||||
if (!Features::_OverlayEnabled.GetState() || !NativeInvoker::AreHandlersCached())
|
||||
return;
|
||||
|
||||
@@ -31,6 +31,5 @@ namespace YimMenu
|
||||
ImGui::PopFont();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::End();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@
|
||||
#include "core/commands/Command.hpp"
|
||||
#include "core/commands/Commands.hpp"
|
||||
#include "core/commands/Vector3Command.hpp"
|
||||
//#include "game/backend/SavedLocations.hpp"
|
||||
//#include "game/backend/Self.hpp"
|
||||
#include "game/backend/SavedLocations.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
@@ -26,7 +27,7 @@ namespace YimMenu
|
||||
ImGui::SetNextItemWidth(180);
|
||||
if (ImGui::InputFloat3("##coord_inp", &value.x, "%.1f"))
|
||||
m_Command->SetState(value);
|
||||
#if 0
|
||||
|
||||
if (Self::GetPed())
|
||||
{
|
||||
ImGui::SameLine();
|
||||
@@ -90,7 +91,7 @@ namespace YimMenu
|
||||
if (ImGui::IsItemHovered() && l.name.length() > 27)
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text(l.name.data());
|
||||
ImGui::Text("%s", l.name.data());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
@@ -108,7 +109,6 @@ namespace YimMenu
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
#endif
|
||||
|
||||
auto& label = m_LabelOverride.has_value() ? m_LabelOverride.value() : m_Command->GetLabel();
|
||||
if (!label.empty())
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace YimMenu::Submenus
|
||||
if (player.GetPed() && player.GetPed().IsInvincible())
|
||||
tags.push_back({"GOD", ImGui::Colors::Crimson});
|
||||
|
||||
if (player.GetPed() && !player.GetPed().IsVisible())
|
||||
if (player.GetPed() && !player.GetPed().IsVisible() && false) // doesn't really seem to work on GTA
|
||||
tags.push_back({"INVIS", ImGui::Colors::MediumPurple});
|
||||
|
||||
return tags;
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace YimMenu::Submenus
|
||||
|
||||
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("godmode"_J));
|
||||
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("invis"_J));
|
||||
globalsGroup->AddItem(std::make_shared<BoolCommandItem>("otr"_J));
|
||||
|
||||
toolsGroup->AddItem(std::make_shared<CommandItem>("suicide"_J));
|
||||
|
||||
@@ -50,12 +51,16 @@ namespace YimMenu::Submenus
|
||||
|
||||
auto vehicle = std::make_shared<Category>("Vehicle");
|
||||
auto vehicleGlobalsGroup = std::make_shared<Group>("Globals");
|
||||
auto vehicleMiscGroup = std::make_shared<Group>("Misc");
|
||||
|
||||
vehicleGlobalsGroup->AddItem(std::make_shared<BoolCommandItem>("vehiclegodmode"_J));
|
||||
vehicleGlobalsGroup->AddItem(std::make_shared<BoolCommandItem>("vehiclegodmode"_J, "Godmode"));
|
||||
vehicleGlobalsGroup->AddItem(std::make_shared<BoolCommandItem>("keepfixed"_J, "Keep Fixed"));
|
||||
vehicleGlobalsGroup->AddItem(std::make_shared<CommandItem>("repairvehicle"_J));
|
||||
|
||||
|
||||
vehicleMiscGroup->AddItem(std::make_shared<BoolCommandItem>("speedometer"_J));
|
||||
|
||||
vehicle->AddItem(vehicleGlobalsGroup);
|
||||
vehicle->AddItem(vehicleMiscGroup);
|
||||
AddCategory(std::move(vehicle));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include "Settings.hpp"
|
||||
|
||||
#include "core/commands/Commands.hpp"
|
||||
#include "core/commands/HotkeySystem.hpp"
|
||||
#include "core/commands/LoopedCommand.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/frontend/items/Items.hpp"
|
||||
|
||||
namespace YimMenu::Submenus
|
||||
{
|
||||
// TODO: refactor this
|
||||
static void Hotkeys()
|
||||
{
|
||||
ImGui::BulletText("Hold the command name clicked to change its hotkey");
|
||||
ImGui::BulletText("Press any registered key to remove");
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
|
||||
for (auto& [Hash, Command] : Commands::GetCommands())
|
||||
{
|
||||
ImGui::PushID(Hash);
|
||||
|
||||
if (g_HotkeySystem.m_CommandHotkeys.find(Hash) != g_HotkeySystem.m_CommandHotkeys.end())
|
||||
HotkeySetter(Hash).Draw();
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
ImGui::PopID();
|
||||
}
|
||||
};
|
||||
|
||||
Settings::Settings() :
|
||||
Submenu::Submenu("Settings")
|
||||
{
|
||||
auto hotkeys = std::make_shared<Category>("Hotkeys");
|
||||
auto gui = std::make_shared<Category>("GUI");
|
||||
auto overlay = std::make_shared<Group>("Overlay");
|
||||
|
||||
hotkeys->AddItem(std::make_shared<ImGuiItem>(Hotkeys));
|
||||
|
||||
overlay->AddItem(std::make_shared<BoolCommandItem>("overlay"_J));
|
||||
overlay->AddItem(std::make_shared<ConditionalItem>("overlay"_J, std::make_shared<BoolCommandItem>("overlayfps"_J)));
|
||||
|
||||
gui->AddItem(overlay);
|
||||
|
||||
AddCategory(std::move(hotkeys));
|
||||
AddCategory(std::move(gui));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "core/frontend/manager/UIManager.hpp"
|
||||
|
||||
namespace YimMenu::Submenus
|
||||
{
|
||||
class Settings : public Submenu
|
||||
{
|
||||
public:
|
||||
Settings();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
#include "Teleport.hpp"
|
||||
|
||||
#include "core/frontend/Notifications.hpp"
|
||||
#include "core/backend/FiberPool.hpp"
|
||||
#include "game/backend/SavedLocations.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/frontend/items/Items.hpp"
|
||||
|
||||
namespace YimMenu::Submenus
|
||||
{
|
||||
static float GetDistanceFromLocation(const SavedLocation& t)
|
||||
{
|
||||
return rage::fvector3(t.x, t.y, t.z).GetDistance(Self::GetPed().GetPosition());
|
||||
}
|
||||
|
||||
void RenderCustomTeleport()
|
||||
{
|
||||
ImGui::BeginGroup();
|
||||
static std::string newLocationName{};
|
||||
static std::string category = "Default";
|
||||
static SavedLocation locationToDelete;
|
||||
|
||||
if (!std::string(locationToDelete.name).empty())
|
||||
ImGui::OpenPopup("##deletelocation");
|
||||
|
||||
if (ImGui::BeginPopupModal("##deletelocation", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove))
|
||||
{
|
||||
ImGui::Text("Are you sure you want to delete %s?", locationToDelete.name.data());
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
if (ImGui::Button("Yes"))
|
||||
{
|
||||
SavedLocations::DeleteSavedLocation(category, locationToDelete.name);
|
||||
locationToDelete.name = "";
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("No"))
|
||||
{
|
||||
locationToDelete.name = "";
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::PushItemWidth(300);
|
||||
InputTextWithHint("Category", "Category", &category).Draw();
|
||||
|
||||
ImGui::PushItemWidth(200);
|
||||
InputTextWithHint("Location name", "New location", &newLocationName).Draw();
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if (ImGui::Button("Save current location")) // Button widget still crashes
|
||||
{
|
||||
FiberPool::Push([=] {
|
||||
if (newLocationName.empty())
|
||||
{
|
||||
Notifications::Show("Custom Teleport", "Please enter a valid name", NotificationType::Warning);
|
||||
}
|
||||
else if (SavedLocations::GetSavedLocationByName(newLocationName))
|
||||
{
|
||||
Notifications::Show("Custom Teleport", std::format("Location with name {} already exists", newLocationName));
|
||||
}
|
||||
else
|
||||
{
|
||||
SavedLocation teleportLocation;
|
||||
Entity teleportEntity = Self::GetPed();
|
||||
if (auto vehicle = Self::GetVehicle())
|
||||
teleportEntity = vehicle;
|
||||
|
||||
auto coords = teleportEntity.GetPosition();
|
||||
teleportLocation.name = newLocationName;
|
||||
teleportLocation.x = coords.x;
|
||||
teleportLocation.y = coords.y;
|
||||
teleportLocation.z = coords.z;
|
||||
teleportLocation.yaw = teleportEntity.GetHeading();
|
||||
teleportLocation.pitch = 0.0f; // why do we need pitch and roll anyway?
|
||||
teleportLocation.roll = 0.0f;
|
||||
SavedLocations::SaveNewLocation(category, teleportLocation);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Text("Double click to teleport\nShift click to delete");
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
static std::string filter{};
|
||||
InputTextWithHint("##filter", "Search", &filter).Draw();
|
||||
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("Categories");
|
||||
if (ImGui::BeginListBox("##categories", {200, -1}))
|
||||
{
|
||||
for (auto& l : SavedLocations::GetAllSavedLocations() | std::ranges::views::keys)
|
||||
{
|
||||
if (ImGui::Selectable(l.data(), l == category))
|
||||
{
|
||||
category = l;
|
||||
}
|
||||
|
||||
if (category.empty())
|
||||
{
|
||||
category = l;
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
ImGui::Text("Locations");
|
||||
if (ImGui::BeginListBox("##saved_locs", {200, -1})) // Need automatic dimensions instead of hard coded
|
||||
{
|
||||
if (SavedLocations::GetAllSavedLocations().find(category) != SavedLocations::GetAllSavedLocations().end())
|
||||
{
|
||||
std::vector<SavedLocation> current_list{};
|
||||
|
||||
if (!filter.empty())
|
||||
current_list = SavedLocations::SavedLocationsFilteredList(filter);
|
||||
else
|
||||
current_list = SavedLocations::GetAllSavedLocations().at(category);
|
||||
|
||||
for (const auto& l : current_list)
|
||||
{
|
||||
if (ImGui::Selectable(l.name.data(), false, ImGuiSelectableFlags_AllowDoubleClick))
|
||||
{
|
||||
if (GetAsyncKeyState(VK_SHIFT) & 0x8000)
|
||||
{
|
||||
locationToDelete = l;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ImGui::IsMouseDoubleClicked(0))
|
||||
{
|
||||
FiberPool::Push([l] {
|
||||
rage::fvector3 l_ = {l.x, l.y, l.z};
|
||||
Self::GetPed().TeleportTo(l_);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
if (l.name.length() > 27)
|
||||
ImGui::Text("%s", l.name.data());
|
||||
ImGui::Text("Distance: %f", GetDistanceFromLocation(l));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
|
||||
ImGui::EndGroup();
|
||||
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
|
||||
Teleport::Teleport() :
|
||||
Submenu::Submenu("Teleport")
|
||||
{
|
||||
auto main = std::make_shared<Category>("Main");
|
||||
auto miscGroup = std::make_shared<Group>("Misc");
|
||||
|
||||
// miscGroup->AddItem(std::make_shared<BoolCommandItem>("autotp"_J));
|
||||
miscGroup->AddItem(std::make_shared<CommandItem>("tptowaypoint"_J));
|
||||
// miscGroup->AddItem(std::make_shared<CommandItem>("tptomount"_J));
|
||||
// miscGroup->AddItem(std::make_shared<CommandItem>("tptotraintrack"_J));
|
||||
// miscGroup->AddItem(std::make_shared<CommandItem>("tptomoonshineshack"_J));
|
||||
// miscGroup->AddItem(std::make_shared<CommandItem>("tptonazar"_J));
|
||||
|
||||
main->AddItem(miscGroup);
|
||||
|
||||
auto customteleport = std::make_shared<Category>("Saved");
|
||||
customteleport->AddItem(std::make_shared<ImGuiItem>([] {
|
||||
RenderCustomTeleport();
|
||||
}));
|
||||
|
||||
|
||||
AddCategory(std::move(main));
|
||||
AddCategory(std::move(customteleport));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "core/frontend/manager/UIManager.hpp"
|
||||
|
||||
namespace YimMenu::Submenus
|
||||
{
|
||||
class Teleport : public Submenu
|
||||
{
|
||||
public:
|
||||
Teleport();
|
||||
};
|
||||
}
|
||||
@@ -155,6 +155,25 @@ namespace YimMenu
|
||||
ENTITY::SET_ENTITY_VELOCITY(GetHandle(), vel.x, vel.y, vel.z);
|
||||
}
|
||||
|
||||
float Entity::GetHeading()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
return ENTITY::GET_ENTITY_HEADING(GetHandle());
|
||||
}
|
||||
|
||||
void Entity::SetHeading(float heading)
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
ENTITY_ASSERT_CONTROL();
|
||||
ENTITY::SET_ENTITY_HEADING(GetHandle(), heading);
|
||||
}
|
||||
|
||||
float Entity::GetSpeed()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
return ENTITY::GET_ENTITY_SPEED(GetHandle());
|
||||
}
|
||||
|
||||
void Entity::SetCollision(bool enabled)
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
|
||||
@@ -101,6 +101,9 @@ namespace YimMenu
|
||||
void SetRotation(rage::fvector3 rotation, int order = 2);
|
||||
rage::fvector3 GetVelocity();
|
||||
void SetVelocity(rage::fvector3 velocity);
|
||||
float GetHeading();
|
||||
void SetHeading(float heading);
|
||||
float GetSpeed();
|
||||
|
||||
// physical
|
||||
void SetCollision(bool enabled);
|
||||
|
||||
+14
-1
@@ -51,7 +51,9 @@ namespace YimMenu
|
||||
Vehicle Ped::GetVehicle()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
return Vehicle(PED::GET_VEHICLE_PED_IS_IN(GetHandle(), true));
|
||||
if (!PED::IS_PED_IN_ANY_VEHICLE(GetHandle(), false))
|
||||
return nullptr;
|
||||
return Vehicle(PED::GET_VEHICLE_PED_IS_USING(GetHandle()));
|
||||
}
|
||||
|
||||
bool Ped::GetRagdoll()
|
||||
@@ -139,4 +141,15 @@ namespace YimMenu
|
||||
|
||||
WEAPON::SET_PED_INFINITE_AMMO_CLIP(GetHandle(), infinite); // is this networked?
|
||||
}
|
||||
|
||||
void Ped::TeleportTo(const rage::fvector3& pos)
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
ENTITY_ASSERT_CONTROL();
|
||||
|
||||
if (auto veh = GetVehicle())
|
||||
veh.SetPosition(pos);
|
||||
else
|
||||
SetPosition(pos);
|
||||
}
|
||||
}
|
||||
@@ -40,5 +40,8 @@ namespace YimMenu
|
||||
// weapons
|
||||
void SetInfiniteAmmo(bool infinite);
|
||||
void SetInfiniteClip(bool infinite);
|
||||
|
||||
// teleport
|
||||
void TeleportTo(const rage::fvector3& pos); // similar to SetPosition, but handles vehicles correctly
|
||||
};
|
||||
}
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "types/script/GtaThread.hpp"
|
||||
#include "types/script/CGameScriptHandler.hpp"
|
||||
#include "types/script/CGameScriptId.hpp"
|
||||
#include "types/script/globals/GlobalPlayerBD.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
|
||||
namespace YimMenu::Scripts
|
||||
{
|
||||
@@ -59,4 +61,20 @@ namespace YimMenu::Scripts
|
||||
thread->m_ScriptHandler->GetId()->m_Hash = *hash_4;
|
||||
}
|
||||
}
|
||||
|
||||
bool SafeToModifyFreemodeBroadcastGlobals()
|
||||
{
|
||||
if (!*Pointers.IsSessionStarted)
|
||||
return false;
|
||||
|
||||
if (!FindScriptThread("freemode"_J))
|
||||
return false;
|
||||
|
||||
if (auto gpbd = GlobalPlayerBD::Get())
|
||||
{
|
||||
return gpbd->Entries[Self::GetPlayer().GetId()].FreemodeState == eFreemodeState::RUNNING;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -12,4 +12,5 @@ namespace YimMenu::Scripts
|
||||
extern rage::scrThread* FindScriptThread(joaat_t hash);
|
||||
extern void RunAsScript(rage::scrThread* thread, std::function<void()> callback);
|
||||
extern void RunWithSpoofedThreadName(std::uint32_t name, std::function<void()> callback); // consider using RunAsScript if possible
|
||||
extern bool SafeToModifyFreemodeBroadcastGlobals(); // TODO: find a better method for this that works for all scripts
|
||||
}
|
||||
@@ -57,4 +57,25 @@ namespace YimMenu
|
||||
VEHICLE::SET_VEHICLE_DIRT_LEVEL(GetHandle(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
int Vehicle::GetGear()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
|
||||
return VEHICLE::_GET_VEHICLE_CURRENT_DRIVE_GEAR(GetHandle());
|
||||
}
|
||||
|
||||
float Vehicle::GetRevRatio()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
|
||||
return VEHICLE::_GET_VEHICLE_CURRENT_REV_RATIO(GetHandle());
|
||||
}
|
||||
|
||||
float Vehicle::GetMaxSpeed()
|
||||
{
|
||||
ENTITY_ASSERT_VALID();
|
||||
|
||||
return VEHICLE::GET_VEHICLE_ESTIMATED_MAX_SPEED(GetHandle());
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,12 @@ namespace YimMenu
|
||||
static Vehicle Create(std::uint32_t model, rage::fvector3 coords, float heading = 0.0f);
|
||||
|
||||
void Fix();
|
||||
|
||||
// gears
|
||||
int GetGear();
|
||||
float GetRevRatio(); // doesn't work
|
||||
|
||||
// speed
|
||||
float GetMaxSpeed();
|
||||
};
|
||||
}
|
||||
@@ -43,6 +43,7 @@ namespace YimMenu
|
||||
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&Self::RunScript));
|
||||
FiberPool::Init(5);
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&HotkeySystem::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&Commands::RunScript));
|
||||
|
||||
Notifications::Show("YimMenuV2", "Loaded succesfully", NotificationType::Success);
|
||||
|
||||
Reference in New Issue
Block a user