diff --git a/docs/lua-api.md b/docs/lua-api.md index bb4ee45..0a22e44 100644 --- a/docs/lua-api.md +++ b/docs/lua-api.md @@ -121,6 +121,8 @@ Build menu UI: submenus, categories, and groups. Most builders return a handle y | `menu.create_group(name, [per_row]) -> Group` | Creates a standalone group (drawn manually via `group:draw()`). `per_row` default 7. | | `menu.is_open() -> boolean` | Returns true if the menu is open. | | `menu.toggle()` | Toggles the menu open/closed. | +| `menu.add_imgui(fn)` | Registers a raw ImGui draw callback rendered every frame while the menu is open. | +| `menu.add_always_draw_imgui(fn)` | Registers a raw ImGui draw callback rendered every frame regardless of whether the menu is open. | #### Submenu | Method | Description | diff --git a/docs/yimmenu_v2.lua b/docs/yimmenu_v2.lua index 6a05849..38a1768 100644 --- a/docs/yimmenu_v2.lua +++ b/docs/yimmenu_v2.lua @@ -172,6 +172,12 @@ function menu.create_group(name, per_row) end ---@return boolean function menu.is_open() end function menu.toggle() end +---Register a raw ImGui draw callback rendered every frame while the menu is open. +---@param fn fun() +function menu.add_imgui(fn) end +---Register a raw ImGui draw callback rendered every frame regardless of whether the menu is open. +---@param fn fun() +function menu.add_always_draw_imgui(fn) end ---@param name string ---@return Category diff --git a/src/core/scripting/LuaUserInterface.cpp b/src/core/scripting/LuaUserInterface.cpp index b0b9913..78c77fe 100644 --- a/src/core/scripting/LuaUserInterface.cpp +++ b/src/core/scripting/LuaUserInterface.cpp @@ -60,6 +60,10 @@ namespace YimMenu luaL_unref(m_Script->GetState(), LUA_REGISTRYINDEX, ref); } m_RenderCallbacks.clear(); + m_ImGuiCallbacks.clear(); + m_AlwaysDrawImGuiCallbacks.clear(); + m_HasImGuiCallbacks = false; + m_HasAlwaysDrawImGuiCallbacks = false; for (auto* ptr : m_ScriptAllocations) std::free(ptr); @@ -97,6 +101,59 @@ namespace YimMenu m_RenderCallbacks.push_back(func_ref); } + void LuaUserInterface::AddImGuiCallback(int func_ref) + { + if (func_ref == LUA_NOREF || !m_Script) + return; + + std::lock_guard lock(m_Script->GetExecutionLock()); + m_ImGuiCallbacks.push_back(func_ref); + m_RenderCallbacks.push_back(func_ref); + m_HasImGuiCallbacks = true; + } + + void LuaUserInterface::AddAlwaysDrawImGuiCallback(int func_ref) + { + if (func_ref == LUA_NOREF || !m_Script) + return; + + std::lock_guard lock(m_Script->GetExecutionLock()); + m_AlwaysDrawImGuiCallbacks.push_back(func_ref); + m_RenderCallbacks.push_back(func_ref); + m_HasAlwaysDrawImGuiCallbacks = true; + } + + void LuaUserInterface::RunImGuiCallbacks(const std::vector& callbacks) + { + if (!m_Script) + return; + + std::vector refs; + { + std::lock_guard lock(m_Script->GetExecutionLock()); + if (callbacks.empty()) + return; + refs = callbacks; + } + + for (auto ref : refs) + m_Script->RunRenderCallback(ref); + } + + void LuaUserInterface::DrawImGuiCallbacks() + { + if (!m_HasImGuiCallbacks) + return; + RunImGuiCallbacks(m_ImGuiCallbacks); + } + + void LuaUserInterface::DrawAlwaysDrawImGuiCallbacks() + { + if (!m_HasAlwaysDrawImGuiCallbacks) + return; + RunImGuiCallbacks(m_AlwaysDrawImGuiCallbacks); + } + void LuaUserInterface::TrackScriptAllocation(void* ptr) { m_ScriptAllocations.insert(ptr); diff --git a/src/core/scripting/LuaUserInterface.hpp b/src/core/scripting/LuaUserInterface.hpp index 9e8298f..8029996 100644 --- a/src/core/scripting/LuaUserInterface.hpp +++ b/src/core/scripting/LuaUserInterface.hpp @@ -55,6 +55,11 @@ namespace YimMenu std::vector m_RenderCallbacks; + std::vector m_ImGuiCallbacks; + std::vector m_AlwaysDrawImGuiCallbacks; + std::atomic m_HasImGuiCallbacks{false}; + std::atomic m_HasAlwaysDrawImGuiCallbacks{false}; + std::unordered_set m_ScriptAllocations; std::mutex m_TickFunctionsLock; @@ -64,6 +69,8 @@ namespace YimMenu bool m_ShutdownCalled = false; + void RunImGuiCallbacks(const std::vector& callbacks); + public: LuaUserInterface(); ~LuaUserInterface(); @@ -97,6 +104,12 @@ namespace YimMenu void TrackOwnedGroup(std::shared_ptr group); void TrackRenderCallback(int func_ref); + void AddImGuiCallback(int func_ref); + void AddAlwaysDrawImGuiCallback(int func_ref); + + void DrawImGuiCallbacks(); + void DrawAlwaysDrawImGuiCallbacks(); + void TrackScriptAllocation(void* ptr); bool ReleaseScriptAllocation(void* ptr); diff --git a/src/core/scripting/libraries/Menu.cpp b/src/core/scripting/libraries/Menu.cpp index 8fcc52b..f23b4af 100644 --- a/src/core/scripting/libraries/Menu.cpp +++ b/src/core/scripting/libraries/Menu.cpp @@ -165,6 +165,22 @@ namespace YimMenu::Lua return 0; } + static int MenuAddImGui(lua_State* state) + { + auto& iface = LuaScript::GetScript(state).GetUserInterface(); + int fn = CaptureFunction(state, 1, true); + iface.AddImGuiCallback(fn); + return 0; + } + + static int MenuAddAlwaysDrawImGui(lua_State* state) + { + auto& iface = LuaScript::GetScript(state).GetUserInterface(); + int fn = CaptureFunction(state, 1, true); + iface.AddAlwaysDrawImGuiCallback(fn); + return 0; + } + static int MenuCreateGroup(lua_State* state) { auto& iface = LuaScript::GetScript(state).GetUserInterface(); @@ -408,6 +424,8 @@ namespace YimMenu::Lua SetFunction(state, MenuCreateGroup, "create_group"); SetFunction(state, IsOpen, "is_open"); SetFunction(state, Toggle, "toggle"); + SetFunction(state, MenuAddImGui, "add_imgui"); + SetFunction(state, MenuAddAlwaysDrawImGui, "add_always_draw_imgui"); lua_setglobal(state, "menu"); } }; diff --git a/src/game/features/teleport/DirectionalTp.cpp b/src/game/features/teleport/DirectionalTp.cpp new file mode 100644 index 0000000..bc77fa9 --- /dev/null +++ b/src/game/features/teleport/DirectionalTp.cpp @@ -0,0 +1,82 @@ +#include "core/commands/Command.hpp" +#include "core/commands/FloatCommand.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Natives.hpp" + +namespace YimMenu::Features +{ + static FloatCommand _DirectionalTpDistance{"directionaltpdistance", "Teleport Distance", "Teleportation distance of directional teleports"}; + + class TpForward : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto ped = Self::GetPed(); + ped.TeleportTo(ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped.GetHandle(), 0, _DirectionalTpDistance.GetState(), 0)); + } + }; + + class TpBackward : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto ped = Self::GetPed(); + ped.TeleportTo(ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped.GetHandle(), 0, -_DirectionalTpDistance.GetState(), 0)); + } + }; + + class TpRight : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto ped = Self::GetPed(); + ped.TeleportTo(ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped.GetHandle(), _DirectionalTpDistance.GetState(), 0, 0)); + } + }; + + class TpLeft : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto ped = Self::GetPed(); + ped.TeleportTo(ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped.GetHandle(), -_DirectionalTpDistance.GetState(), 0, 0)); + } + }; + + class TpUp : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto ped = Self::GetPed(); + ped.TeleportTo(ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped.GetHandle(), 0, 0, _DirectionalTpDistance.GetState())); + } + }; + + class TpDown : public Command + { + using Command::Command; + + virtual void OnCall() override + { + auto ped = Self::GetPed(); + ped.TeleportTo(ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ped.GetHandle(), 0, 0, -_DirectionalTpDistance.GetState())); + } + }; + + static TpForward _DirectionalTpForward {"directionaltpforward", "Teleport Forward", "Teleports you forward" }; + static TpBackward _DirectionalTpBackward{"directionaltpbackward", "Teleport Backward", "Teleports you backward" }; + static TpRight _DirectionalTpRight {"directionaltpright", "Teleport Right", "Teleports you to the right"}; + static TpLeft _DirectionalTpLeft {"directionaltpleft", "Teleport Left", "Teleports you to the left" }; + static TpUp _DirectionalTpUp {"directionaltpup", "Teleport Up", "Teleports you up" }; + static TpDown _DirectionalTpDown {"directionaltpdown", "Teleport Down", "Teleports you down" }; +} diff --git a/src/game/frontend/GUI.cpp b/src/game/frontend/GUI.cpp index c665bd9..fb8002a 100644 --- a/src/game/frontend/GUI.cpp +++ b/src/game/frontend/GUI.cpp @@ -5,6 +5,8 @@ #include "Overlay.hpp" #include "core/backend/ScriptMgr.hpp" #include "core/renderer/Renderer.hpp" +#include "core/scripting/LuaManager.hpp" +#include "core/scripting/LuaScript.hpp" #include "core/frontend/Notifications.hpp" #include "game/frontend/ChatDisplay.hpp" #include "game/gta/Natives.hpp" @@ -44,7 +46,23 @@ namespace YimMenu Overlay::Draw(); }, -6); - + Renderer::AddRendererCallBack( + [] { + LuaManager::ForAllLoadedScripts([](std::shared_ptr& script) { + script->GetUserInterface().DrawAlwaysDrawImGuiCallbacks(); + }); + }, + -7); + Renderer::AddRendererCallBack( + [] { + if (!GUI::IsOpen()) + return; + LuaManager::ForAllLoadedScripts([](std::shared_ptr& script) { + script->GetUserInterface().DrawImGuiCallbacks(); + }); + }, + -4); + Renderer::SetSafeToRender(); } diff --git a/src/game/frontend/submenus/Teleport.cpp b/src/game/frontend/submenus/Teleport.cpp index 4323f85..b694ace 100644 --- a/src/game/frontend/submenus/Teleport.cpp +++ b/src/game/frontend/submenus/Teleport.cpp @@ -165,6 +165,30 @@ namespace YimMenu::Submenus ImGui::EndGroup(); } + void RenderDirectionalTp() + { + FloatCommandItem("directionaltpdistance"_J).Draw(); + + ImGui::BeginGroup(); + CommandItem("directionaltpforward"_J).Draw(); + CommandItem("directionaltpbackward"_J).Draw(); + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + CommandItem("directionaltpright"_J).Draw(); + CommandItem("directionaltpleft"_J).Draw(); + ImGui::EndGroup(); + + ImGui::SameLine(); + + ImGui::BeginGroup(); + CommandItem("directionaltpup"_J).Draw(); + CommandItem("directionaltpdown"_J).Draw(); + ImGui::EndGroup(); + } + Teleport::Teleport() : #define ICON_FA_TELEPORT "\xef\x8f\x85" Submenu::Submenu("Teleport", ICON_FA_TELEPORT) @@ -175,6 +199,9 @@ namespace YimMenu::Submenus miscGroup->AddItem(std::make_shared("autotptowaypoint"_J, std::make_shared("tptowaypoint"_J), true)); miscGroup->AddItem(std::make_shared("autotptowaypoint"_J)); miscGroup->AddItem(std::make_shared("tptoobjective"_J)); + miscGroup->AddItem(std::make_shared([] { + RenderDirectionalTp(); + })); main->AddItem(miscGroup); diff --git a/src/game/scripting/libraries/ScriptGlobal.cpp b/src/game/scripting/libraries/ScriptGlobal.cpp index 1049932..2d33572 100644 --- a/src/game/scripting/libraries/ScriptGlobal.cpp +++ b/src/game/scripting/libraries/ScriptGlobal.cpp @@ -1,3 +1,4 @@ +#include "core/memory/PointerCalculator.hpp" #include "core/scripting/LuaLibrary.hpp" #include "core/scripting/LuaScript.hpp" #include "core/scripting/LuaUtils.hpp" @@ -77,6 +78,16 @@ namespace YimMenu::Lua return 1; } + static int GetPointer(lua_State* state) + { + auto& global = GetObject(state, 1); + void* value = nullptr; + if (global.CanAccess()) + value = global.As(); + PushObject(state, PointerCalculator(value)); + return 1; + } + static int SetInt(lua_State* state) { auto& global = GetObject(state, 1); @@ -134,6 +145,7 @@ namespace YimMenu::Lua SetFunction(state, GetFloat, "get_float"); SetFunction(state, GetString, "get_string"); SetFunction(state, GetVector3, "get_vector3"); + SetFunction(state, GetPointer, "get_pointer"); SetFunction(state, SetInt, "set_int"); SetFunction(state, SetFloat, "set_float"); SetFunction(state, SetString, "set_string"); diff --git a/src/game/scripting/libraries/ScriptLocal.cpp b/src/game/scripting/libraries/ScriptLocal.cpp index 9095788..cfb1432 100644 --- a/src/game/scripting/libraries/ScriptLocal.cpp +++ b/src/game/scripting/libraries/ScriptLocal.cpp @@ -1,3 +1,4 @@ +#include "core/memory/PointerCalculator.hpp" #include "core/scripting/LuaLibrary.hpp" #include "core/scripting/LuaScript.hpp" #include "core/scripting/LuaUtils.hpp" @@ -65,6 +66,14 @@ namespace YimMenu::Lua return 1; } + static int GetPointer(lua_State* state) + { + auto& local = GetObject(state, 1); + void* value = local.As(); + PushObject(state, PointerCalculator(value)); + return 1; + } + static int SetInt(lua_State* state) { auto& local = GetObject(state, 1); @@ -98,6 +107,7 @@ namespace YimMenu::Lua SetFunction(state, GetInt, "get_int"); SetFunction(state, GetFloat, "get_float"); SetFunction(state, GetVector3, "get_vector3"); + SetFunction(state, GetPointer, "get_pointer"); SetFunction(state, SetInt, "set_int"); SetFunction(state, SetFloat, "set_float"); SetFunction(state, SetVector3, "set_vector3");