From b769d36a1c0460cda677a87a8dcd7eebb035e0ea Mon Sep 17 00:00:00 2001 From: maybegreat48 <96936658+maybegreat48@users.noreply.github.com> Date: Wed, 25 Jun 2025 17:01:10 -0400 Subject: [PATCH] feat(lua): initial lua scripting prototype --- CMakeLists.txt | 5 +- cmake/luajit.cmake | 23 ++ src/core/scripting/LuaLibrary.cpp | 10 + src/core/scripting/LuaLibrary.hpp | 13 + src/core/scripting/LuaManager.cpp | 75 +++++ src/core/scripting/LuaManager.hpp | 60 ++++ src/core/scripting/LuaScript.cpp | 99 +++++++ src/core/scripting/LuaScript.hpp | 49 ++++ src/core/scripting/libraries/Default.cpp | 49 ++++ src/core/scripting/libraries/Logging.cpp | 71 +++++ src/game/frontend/submenus/Debug/Scripts.cpp | 38 ++- src/game/gta/Scripts.cpp | 158 ++++++++++ src/game/gta/Scripts.hpp | 3 + src/game/gta/data/LauncherScripts.hpp | 274 ++++++++++++++++++ src/game/gta/data/ScriptNames.hpp | 234 ++++++++------- src/main.cpp | 2 + .../script/CGameScriptHandlerNetComponent.hpp | 5 + src/types/script/MPScriptData.hpp | 16 +- src/types/script/ScriptEvent.hpp | 28 +- src/types/script/globals/GPBD_FM_3.hpp | 2 +- src/types/script/globals/Globals.cpp | 4 +- .../script/globals/LauncherServerData.hpp | 60 ++++ .../script/locals/LauncherClientData.hpp | 19 ++ src/types/script/locals/Locals.cpp | 6 +- 24 files changed, 1179 insertions(+), 124 deletions(-) create mode 100644 cmake/luajit.cmake create mode 100644 src/core/scripting/LuaLibrary.cpp create mode 100644 src/core/scripting/LuaLibrary.hpp create mode 100644 src/core/scripting/LuaManager.cpp create mode 100644 src/core/scripting/LuaManager.hpp create mode 100644 src/core/scripting/LuaScript.cpp create mode 100644 src/core/scripting/LuaScript.hpp create mode 100644 src/core/scripting/libraries/Default.cpp create mode 100644 src/core/scripting/libraries/Logging.cpp create mode 100644 src/game/gta/data/LauncherScripts.hpp create mode 100644 src/types/script/globals/LauncherServerData.hpp create mode 100644 src/types/script/locals/LauncherClientData.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ebed46..abe1daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ include(cmake/async-logger.cmake) include(cmake/imgui.cmake) include(cmake/json.cmake) include(cmake/minhook.cmake) +include(cmake/luajit.cmake) # source set(SRC_DIR "${PROJECT_SOURCE_DIR}/src") @@ -35,7 +36,9 @@ target_include_directories(${PROJECT_NAME} PRIVATE "${imgui_SOURCE_DIR}" "${minhook_SOURCE_DIR}/include" "${minhook_SOURCE_DIR}/src/hde" + "${luajit_SOURCE_DIR}/src" + "${luajit_BINARY_DIR}/src" ) message(STATUS "Setting up linked libraries") -target_link_libraries(${PROJECT_NAME} PRIVATE AsyncLogger imgui minhook nlohmann_json::nlohmann_json dbghelp d3dcompiler dwmapi) \ No newline at end of file +target_link_libraries(${PROJECT_NAME} PRIVATE AsyncLogger imgui minhook nlohmann_json::nlohmann_json dbghelp d3dcompiler dwmapi libluajit) \ No newline at end of file diff --git a/cmake/luajit.cmake b/cmake/luajit.cmake new file mode 100644 index 0000000..ad9b229 --- /dev/null +++ b/cmake/luajit.cmake @@ -0,0 +1,23 @@ +include(FetchContent) + +message("LuaJIT") + +# For some reason putting this into crosscompile.cmake doesn't work. +if(CROSSCOMPILE) + set(CMAKE_SYSTEM_VERSION 10.0.26100) +endif() +set(LUAJIT_BUILD_TOOL OFF) +set(LUAJIT_FORCE_UTF8_FOPEN ON) + +FetchContent_Declare( + luajit + GIT_REPOSITORY https://github.com/WohlSoft/LuaJIT.git + GIT_TAG 27878965958986687f8caaf8a2b6b73bc5df85e0 + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(luajit) +target_compile_definitions(libluajit PRIVATE + "_CRT_SECURE_NO_WARNINGS" + "LUAJIT_ENABLE_LUA52COMPAT" +) \ No newline at end of file diff --git a/src/core/scripting/LuaLibrary.cpp b/src/core/scripting/LuaLibrary.cpp new file mode 100644 index 0000000..f36f55f --- /dev/null +++ b/src/core/scripting/LuaLibrary.cpp @@ -0,0 +1,10 @@ +#include "LuaLibrary.hpp" +#include "LuaManager.hpp" + +namespace YimMenu +{ + LuaLibrary::LuaLibrary() + { + LuaManager::RegisterLibrary(this); + } +} \ No newline at end of file diff --git a/src/core/scripting/LuaLibrary.hpp b/src/core/scripting/LuaLibrary.hpp new file mode 100644 index 0000000..c65020a --- /dev/null +++ b/src/core/scripting/LuaLibrary.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "lua.hpp" + +namespace YimMenu +{ + class LuaLibrary + { + public: + LuaLibrary(); + + virtual void Register(lua_State* state) = 0; + }; +} \ No newline at end of file diff --git a/src/core/scripting/LuaManager.cpp b/src/core/scripting/LuaManager.cpp new file mode 100644 index 0000000..0257eb5 --- /dev/null +++ b/src/core/scripting/LuaManager.cpp @@ -0,0 +1,75 @@ +#include "LuaManager.hpp" +#include "core/filemgr/FileMgr.hpp" +#include "core/backend/ScriptMgr.hpp" +#include "core/frontend/Notifications.hpp" + +namespace YimMenu +{ + void LuaManager::RegisterLibraryImpl(LuaLibrary* library) + { + m_Libraries.push_back(library); + } + + void LuaManager::LoadLibrariesImpl(lua_State* state) + { + for (auto library : m_Libraries) + library->Register(state); + } + + void LuaManager::LoadScriptImpl(std::string path) + { + std::lock_guard lock(m_LoadMutex); + m_ScriptsToLoad.push(path); + } + + void LuaManager::RunScriptImpl() + { + m_MainThreadId = GetCurrentThreadId(); + + auto scripts_dir = FileMgr::GetProjectFolder("./scripts"); + for (const auto& entry : std::filesystem::directory_iterator(scripts_dir.Path())) + { + if (entry.path().extension() != ".lua") + continue; + + m_ScriptsToLoad.push(entry.path().string()); + } + + while (g_Running) + { + { + // 1) process new load requests + std::lock_guard lock(m_LoadMutex); + while (!m_ScriptsToLoad.empty()) + { + m_LoadedScripts.push_back(std::make_shared(m_ScriptsToLoad.front())); + m_ScriptsToLoad.pop(); + } + + // 2) remove malfunctioning scripts + std::erase_if(m_LoadedScripts, [](auto& script) { + auto is_malfunctioning = script->IsMalfunctioning(); + if (is_malfunctioning) + { + script->Invalidate(); + Notifications::Show("Lua Scripting", std::format("Script {} has been unloaded due to a malfunction", script->GetName()), NotificationType::Warning); + return true; + } + + return false; + }); + } + + // 3) run tick coroutines + { + // TODO! + } + ScriptMgr::Yield(); + } + } + + bool LuaManager::IsRunningInMainThreadImpl() + { + return GetCurrentThreadId() == m_MainThreadId; + } +} \ No newline at end of file diff --git a/src/core/scripting/LuaManager.hpp b/src/core/scripting/LuaManager.hpp new file mode 100644 index 0000000..89bfb3d --- /dev/null +++ b/src/core/scripting/LuaManager.hpp @@ -0,0 +1,60 @@ +#pragma once +#include "LuaScript.hpp" +#include "LuaLibrary.hpp" + +namespace YimMenu +{ + // note to future self: Lua is a horrible language and should never be used + class LuaManager + { + public: + enum class ScriptPermission + { + }; + + private: + std::vector> m_LoadedScripts; + std::vector m_Libraries; + std::queue m_ScriptsToLoad; + std::mutex m_LoadMutex; + std::uint32_t m_MainThreadId; + + void RegisterLibraryImpl(LuaLibrary* library); + void LoadLibrariesImpl(lua_State* state); + void LoadScriptImpl(std::string path); + void RunScriptImpl(); + bool IsRunningInMainThreadImpl(); + + static LuaManager& GetInstance() + { + static LuaManager instance; + return instance; + } + + public: + static void RegisterLibrary(LuaLibrary* library) + { + GetInstance().RegisterLibraryImpl(library); + } + + static void LoadLibraries(lua_State* state) + { + GetInstance().LoadLibrariesImpl(state); + } + + static void LoadScript(std::string file_name) + { + GetInstance().LoadScriptImpl(file_name); + } + + static void RunScript() + { + GetInstance().RunScriptImpl(); + } + + static bool IsRunningInMainThread() + { + return GetInstance().IsRunningInMainThreadImpl(); + } + }; +} \ No newline at end of file diff --git a/src/core/scripting/LuaScript.cpp b/src/core/scripting/LuaScript.cpp new file mode 100644 index 0000000..5674ec4 --- /dev/null +++ b/src/core/scripting/LuaScript.cpp @@ -0,0 +1,99 @@ +#include "LuaScript.hpp" +#include "LuaManager.hpp" + +namespace YimMenu +{ + // https://github.com/brimworks/lua-ev/blob/2d11066b6f96a7501805e8c28d92f70dd2c0ab13/lua_ev.c#L144 + // TODO: may need to check if debug is a real table if ChatGPT is to be trusted + static int ErrorHandler(lua_State* state) + { + auto error_msg = lua_tostring(state, 1); + if (!error_msg) + return 1; // return error_msg + + // ok this is the fun part + // our stack right now: retaddr error_message < + lua_getglobal(state, "debug"); + lua_getfield(state, -1, "traceback"); + + lua_pushstring(state, error_msg); + lua_pushinteger(state, 2); + + lua_call(state, 2, 1); // now the top of stack should have the stacktrace + + return 1; + } + + bool LuaScript::CallFunction(int n_args, int n_results) + { + if (!LuaManager::IsRunningInMainThread()) + { + LOGF(FATAL, "LuaScript::CallFunction: {} attempted to call a Lua function outside the main thread. This is not allowed", m_ModuleName); + lua_pop(m_State, 1); // pop the function from the stack since we aren't going to call it + SetMalfunctioning(); + return false; + } + + lua_pushcfunction(m_State, &ErrorHandler); + int handler_index = lua_gettop(m_State) - n_args - 1; + lua_insert(m_State, handler_index); // move it before all the args + + auto result = lua_pcall(m_State, n_args, n_results, handler_index); + + if (result == LUA_OK) + { + // the lua runtime doesn't pop the handler if there's no error + lua_remove(m_State, handler_index); // TODO: does this actually work? What happens if your function returns stuff? + return true; + } + else + { + auto trace = lua_tostring(m_State, -1); + LOGF(FATAL, "{}: {}", m_ModuleName, trace); + lua_pop(m_State, 1); // pop the stack trace + SetMalfunctioning(); + return false; + } + } + + LuaScript::LuaScript(std::string_view file_name) : + m_FileName(file_name), + m_ModuleName(std::filesystem::path(file_name).filename().string()) + { + m_State = luaL_newstate(); + + lua_pushlightuserdata(m_State, (void*)this); + lua_setfield(m_State, LUA_REGISTRYINDEX, "context"); + + LuaManager::LoadLibraries(m_State); + + if (luaL_loadfilex(m_State, file_name.data(), "t") != LUA_OK) // don't load binary chunks + { + auto error = lua_tostring(m_State, -1); + LOGF(FATAL, "{}: {}", m_ModuleName, error); + SetMalfunctioning(); + return; + } + + // we should have a function in the top of stack + CallFunction(0, 0); + m_IsValid = true; + } + + LuaScript::~LuaScript() + { + if (m_State) + { + lua_close(m_State); + m_State = nullptr; + } + } + + LuaScript& LuaScript::GetScript(lua_State* state) + { + lua_getfield(state, LUA_REGISTRYINDEX, "context"); + auto script = static_cast(lua_touserdata(state, -1)); + lua_pop(state, 1); + return *script; + } +} \ No newline at end of file diff --git a/src/core/scripting/LuaScript.hpp b/src/core/scripting/LuaScript.hpp new file mode 100644 index 0000000..04e4e86 --- /dev/null +++ b/src/core/scripting/LuaScript.hpp @@ -0,0 +1,49 @@ +#pragma once +#include "lua.hpp" + +namespace YimMenu +{ + class LuaScript + { + lua_State* m_State; + std::string m_FileName; + std::string m_ModuleName; + bool m_IsMalfunctioning; // when this is set to true, the script will be unloaded next tick + bool m_IsValid; + + // Calls the function at the top of stack. If this returns false the stack would have nothing on it + bool CallFunction(int n_args, int n_results); + + public: + LuaScript(std::string_view file_name); + ~LuaScript(); + + bool IsMalfunctioning() const + { + return m_IsMalfunctioning; + } + + bool IsValid() const + { + return m_IsValid; + } + + void Invalidate() + { + m_IsValid = false; + } + + void SetMalfunctioning() + { + m_IsMalfunctioning = true; + } + + std::string_view GetName() + { + return m_ModuleName; + } + + // we're guaranteed to have a LuaScript for each lua_State, so we can return it as a reference + static LuaScript& GetScript(lua_State* state); + }; +} \ No newline at end of file diff --git a/src/core/scripting/libraries/Default.cpp b/src/core/scripting/libraries/Default.cpp new file mode 100644 index 0000000..d5828d0 --- /dev/null +++ b/src/core/scripting/libraries/Default.cpp @@ -0,0 +1,49 @@ +#include "core/scripting/LuaLibrary.hpp" +#include "core/scripting/LuaScript.hpp" + +namespace YimMenu::Lua +{ + class Default : LuaLibrary + { + using LuaLibrary::LuaLibrary; + + virtual void Register(lua_State* state) override + { + // ensure that only safe libraries are loaded + static const luaL_Reg lj_lib_load[] = { + {"", luaopen_base}, + // {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + // {LUA_IOLIBNAME, luaopen_io}, + // {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {LUA_BITLIBNAME, luaopen_bit}, + {LUA_JITLIBNAME, luaopen_jit}, + {NULL, NULL}}; + + static const luaL_Reg lj_lib_preload[] = { + // {LUA_FFILIBNAME, luaopen_ffi}, + {NULL, NULL}}; + + + const luaL_Reg* lib; + for (lib = lj_lib_load; lib->func; lib++) + { + lua_pushcfunction(state, lib->func); + lua_pushstring(state, lib->name); + lua_call(state, 1, 0); + } + luaL_findtable(state, LUA_REGISTRYINDEX, "_PRELOAD", sizeof(lj_lib_preload) / sizeof(lj_lib_preload[0]) - 1); + for (lib = lj_lib_preload; lib->func; lib++) + { + lua_pushcfunction(state, lib->func); + lua_setfield(state, -2, lib->name); + } + lua_pop(state, 1); + } + }; + + Default _Default; +} \ No newline at end of file diff --git a/src/core/scripting/libraries/Logging.cpp b/src/core/scripting/libraries/Logging.cpp new file mode 100644 index 0000000..0de3ccd --- /dev/null +++ b/src/core/scripting/libraries/Logging.cpp @@ -0,0 +1,71 @@ +#include "core/scripting/LuaLibrary.hpp" +#include "core/scripting/LuaScript.hpp" + +namespace YimMenu::Lua +{ + class Logging : LuaLibrary + { + using LuaLibrary::LuaLibrary; + + static int Verbose(lua_State* state) + { + const char* message = luaL_checkstring(state, 1); + LOGF(VERBOSE, "{}: {}", LuaScript::GetScript(state).GetName(), message); + return 0; + } + + static int Info(lua_State* state) + { + const char* message = luaL_checkstring(state, 1); + LOGF(INFO, "{}: {}", LuaScript::GetScript(state).GetName(), message); + return 0; + } + + static int Warn(lua_State* state) + { + const char* message = luaL_checkstring(state, 1); + LOGF(WARNING, "{}: {}", LuaScript::GetScript(state).GetName(), message); + return 0; + } + + static int Error(lua_State* state) + { + const char* message = luaL_checkstring(state, 1); + LOGF(FATAL, "{}: {}", LuaScript::GetScript(state).GetName(), message); + return 0; + } + + static int Trace(lua_State* state) + { + const char* message = luaL_checkstring(state, 1); + luaL_traceback(state, state, message, 1); + LOGF(VERBOSE, "{}: {}", LuaScript::GetScript(state).GetName(), lua_tostring(state, -1)); + lua_pop(state, 1); // pop the traceback + return 0; + } + + virtual void Register(lua_State* state) override + { + lua_newtable(state); + + lua_pushcfunction(state, Verbose); + lua_setfield(state, -2, "verbose"); + + lua_pushcfunction(state, Info); + lua_setfield(state, -2, "info"); + + lua_pushcfunction(state, Warn); + lua_setfield(state, -2, "warn"); + + lua_pushcfunction(state, Error); + lua_setfield(state, -2, "error"); + + lua_pushcfunction(state, Trace); + lua_setfield(state, -2, "trace"); + + lua_setglobal(state, "log"); + } + }; + + Logging _Logging; +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Debug/Scripts.cpp b/src/game/frontend/submenus/Debug/Scripts.cpp index 796ef0f..264570d 100644 --- a/src/game/frontend/submenus/Debug/Scripts.cpp +++ b/src/game/frontend/submenus/Debug/Scripts.cpp @@ -242,21 +242,24 @@ namespace YimMenu::Submenus ImGui::EndGroup(); ImGui::TreePop(); } - RenderBytecode(curProgram); + if (ImGui::TreeNode("Bytecode")) + { + RenderBytecode(curProgram); + } } })); script->AddItem(std::make_unique([] { static std::string scriptSearch = ""; - static std::string scriptName = ""; static std::string stackSizeName = stackSizes[0].first; + static std::optional launcherIndex = std::nullopt; static int stackSize = 0; static std::int64_t* args = nullptr; static int argCount = 0; static int previousArgCount = 0; static bool pauseAfterStarting = false; - ImGui::InputTextWithHint("Script Name", "Search", &scriptSearch); + bool modified = ImGui::InputTextWithHint("Script Name", "Search", &scriptSearch); if (ImGui::BeginCombo("Stack Size", stackSizeName.c_str())) { @@ -312,10 +315,10 @@ namespace YimMenu::Submenus std::transform(lowerScript.begin(), lowerScript.end(), lowerScript.begin(), ::tolower); if (lowerScript.find(lowerSearch) != std::string::npos) { - if (ImGui::Selectable(script, scriptName == script)) + if (ImGui::Selectable(script, scriptSearch == script)) { scriptSearch = script; - scriptName = script; + modified = true; } } } @@ -323,12 +326,17 @@ namespace YimMenu::Submenus ImGui::EndListBox(); } + if (modified) + { + launcherIndex = Scripts::GetLauncherIndexFromScript(Joaat(scriptSearch)); + } + ImGui::Checkbox("Pause After Starting", &pauseAfterStarting); if (ImGui::Button("Start Script")) { FiberPool::Push([] { - auto hash = Joaat(scriptName); + auto hash = Joaat(scriptSearch); if (!SCRIPT::DOES_SCRIPT_WITH_NAME_HASH_EXIST(hash)) { @@ -374,6 +382,24 @@ namespace YimMenu::Submenus Notifications::Show("Start Script", std::format("Started script with ID {}.", id), NotificationType::Success); }); } + + if (launcherIndex && *Pointers.IsSessionStarted) + { + ImGui::SameLine(); + if (ImGui::Button("Start Session Script")) + { + FiberPool::Push([] { + Scripts::StartLauncherScript(Joaat(scriptSearch)); + }); + } + ImGui::SameLine(); + if (ImGui::Button("Start Script With Event")) + { + FiberPool::Push([] { + Scripts::ForceScriptOnPlayer(Joaat(scriptSearch), -1); + }); + } + } })); menu->AddItem(std::make_shared([] { diff --git a/src/game/gta/Scripts.cpp b/src/game/gta/Scripts.cpp index 4e2fcb0..ac7b698 100644 --- a/src/game/gta/Scripts.cpp +++ b/src/game/gta/Scripts.cpp @@ -9,11 +9,17 @@ #include "types/script/CGameScriptHandlerNetComponent.hpp" #include "types/script/CGameScriptId.hpp" #include "types/script/globals/GlobalPlayerBD.hpp" +#include "types/script/globals/GPBD_FM_3.hpp" +#include "types/script/globals/LauncherServerData.hpp" +#include "types/script/locals/LauncherClientData.hpp" #include "game/gta/Natives.hpp" #include "game/gta/Packet.hpp" #include "game/backend/Players.hpp" #include "game/backend/Self.hpp" #include "core/memory/Pattern.hpp" +#include "game/gta/data/LauncherScripts.hpp" +#include "types/script/ScriptEvent.hpp" +#include "game/gta/ScriptGlobal.hpp" namespace YimMenu::Scripts { @@ -187,4 +193,156 @@ namespace YimMenu::Scripts pkt.Send(player.second.GetMessageId()); } } + + std::optional GetLauncherIndexFromScript(joaat_t hash) + { + for (int i = 0; i < g_LauncherScripts.size(); i++) + if (g_LauncherScripts[i] == hash) + return i; + + return std::nullopt; + } + + void StartLauncherScript(joaat_t hash) + { + auto index = GetLauncherIndexFromScript(hash); + + if (!index) + return; + + static auto atLeastOnePlayerInState = [](GtaThread* launcher, eLauncherState state) -> bool { + bool set = false; + + if (!launcher->m_NetComponent) + return false; + + for (auto& [_, plyr] : Players::GetPlayers()) + { + if (launcher->m_NetComponent->IsParticipant(plyr.GetId())) + { + if (LauncherClientData::Get(launcher)->Entries[plyr.GetId()].LauncherState == state) + { + set = true; + break; + } + } + } + + return set; + }; + + // 1) Get launcher + if (auto launcher = reinterpret_cast(FindScriptThread("am_launcher"_J)); launcher && launcher->m_NetComponent) + { + // 2) Force host of launcher + if (!launcher->m_NetComponent->IsLocalPlayerHost()) + { + ForceScriptHost(launcher); + ScriptMgr::Yield(400ms); + } + + launcher->m_Context.m_State = rage::scrThread::State::PAUSED; + + auto serverData = LauncherServerData::Get(); + + // 3) Remove players from that annoying waiting stage + if (atLeastOnePlayerInState(launcher, eLauncherState::WAIT_FOR_ACK)) + { + for (int i = 0; atLeastOnePlayerInState(launcher, eLauncherState::WAIT_FOR_ACK); i++) + { + if (i > 200) + break; // 3F) Timeout + + serverData->CurrentScript.LauncherIndex = 0; + serverData->LauncherState = eLauncherState::START_SCRIPT; + ScriptMgr::Yield(10ms); + } + } // State should now be 6 or 0 + + // 4) Check if a script is already being executed, and unstuck from that state if so + if (atLeastOnePlayerInState(launcher, eLauncherState::START_SCRIPT)) + { + for (int i = 0; atLeastOnePlayerInState(launcher, eLauncherState::START_SCRIPT); i++) + { + if (i > 200) + break; // 4F) Timeout + + serverData->CurrentScript.LauncherIndex = 0; + serverData->LauncherState = eLauncherState::WAIT_FOR_TERMINATION; + ScriptMgr::Yield(10ms); + } + } // State should now be 7 or 0 + + // 5) Get everyone out of state 7 + if (atLeastOnePlayerInState(launcher, eLauncherState::WAIT_FOR_TERMINATION)) + { + for (int i = 0; atLeastOnePlayerInState(launcher, eLauncherState::WAIT_FOR_TERMINATION); i++) + { + if (i > 200) + break; // 5F) Timeout + + serverData->LauncherState = eLauncherState::EMPTY; + ScriptMgr::Yield(10ms); + } + } // State should now be 0 + + // 6) Actually get the script to start + serverData->Flags.Set(eLauncherFlags::RUN_IMMEDIATELY); + serverData->CurrentScript.EventIndex = 0; + serverData->CurrentScript.LauncherIndex = *index; + serverData->CurrentScript.Terminated = false; + serverData->LauncherState = eLauncherState::START_SCRIPT; + LauncherClientData::Get(launcher)->Entries[Self::GetPlayer().GetId()].LauncherState = eLauncherState::START_SCRIPT; + + launcher->m_Context.m_State = rage::scrThread::State::RUNNING; + } + } + + void ForceScriptOnPlayer(joaat_t hash, int bits) + { + auto index = GetLauncherIndexFromScript(hash); + + if (!index) + return; + + int random_int = time(0) ^ -*index; + + MP_SCRIPT_DATA data{}; + data.MissionIndex = *index; + strcpy(data.CloudFileName.Data, "0"); + data.InstanceId = -1; + data.UniqueId = random_int; + data.GenericInt = 0; + + SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION event; + event.ScriptData = data; + event.Flags = 0; + event.ReplayProtectionValue = GPBD_FM_3::Get()->Entries[Self::GetPlayer().GetId()].ScriptEventReplayProtectionCounter; + event.PAD_0026 = random_int ^ 917391583 ^ rand(); + + // we need to REALLY make sure we're getting an unique random number since the script checks it against the last five events sent + auto& rand_int_2 = event.GetEventIndex(); + rand_int_2 ^= (random_int ^ -2024791401); // TODO: this is a pretty ghetto way to create random numbers + rand_int_2 ^= (random_int ^ 917391583); + + auto bypass_global = ScriptGlobal(1986361); // this global will bypass the new checks added this update + auto old_val = *bypass_global.As(); + *bypass_global.As() = rand_int_2 ^ rand() ^ time(0); + + event.SetPlayerBits(bits); + event.Send(); + + for (int i = 0; i < 2; i++) + { + SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION_SERVER_ACK ack; // not strictly necessary but still useful + ack.ScriptData = data; + ack.SetPlayerBits(bits); + ack.Send(); + + ScriptMgr::Yield(20ms); + } + + // restore global just in case + *bypass_global.As() = old_val; + } } \ No newline at end of file diff --git a/src/game/gta/Scripts.hpp b/src/game/gta/Scripts.hpp index 30c086e..c6b8f20 100644 --- a/src/game/gta/Scripts.hpp +++ b/src/game/gta/Scripts.hpp @@ -22,4 +22,7 @@ namespace YimMenu::Scripts extern bool SafeToModifyFreemodeBroadcastGlobals(); // TODO: find a better method for this that works for all scripts extern std::optional GetCodeLocationByPattern(rage::scrProgram* program, SimplePattern pattern); extern void ForceScriptHost(rage::scrThread* thread); // likely unstable, beware! + extern std::optional GetLauncherIndexFromScript(joaat_t hash); + extern void StartLauncherScript(joaat_t hash); + extern void ForceScriptOnPlayer(joaat_t hash, int bits); } \ No newline at end of file diff --git a/src/game/gta/data/LauncherScripts.hpp b/src/game/gta/data/LauncherScripts.hpp new file mode 100644 index 0000000..e3329ad --- /dev/null +++ b/src/game/gta/data/LauncherScripts.hpp @@ -0,0 +1,274 @@ +#pragma once +#include "core/util/Joaat.hpp" + +namespace YimMenu +{ + constexpr auto g_LauncherScripts = std::to_array({ + ""_J, + "AM_HOLD_UP"_J, + ""_J, + "AM_CR_SELL_DRUGS"_J, + "AM_STRIPPER"_J, + "stripclub_mp"_J, + "AM_ArmWrestling"_J, + "AM_ImportExport"_J, + "AM_Tennis"_J, + "AM_Darts"_J, + "AM_FistFight"_J, + "AM_DropOffHooker"_J, + "AM_Safehouse"_J, + "AM_Hitchhiker"_J, + ""_J, + "AM_DOORS"_J, + "MG_RACE_TO_POINT"_J, + "AM_PI_MENU"_J, + "AM_CRATE_DROP"_J, + "AM_IMP_EXP"_J, + "FM_INTRO"_J, + "AM_PROSTITUTE"_J, + "AM_TAXI"_J, + "AM_TAXI_LAUNCHER"_J, + "AM_GANG_CALL"_J, + "heli_gun"_J, + "AM_backup_heli"_J, + "AM_airstrike"_J, + "AM_AMMO_DROP"_J, + "AM_VEHICLE_DROP"_J, + "AM_BRU_BOX"_J, + "AM_GA_PICKUPS"_J, + "AM_JOYRIDER"_J, + "AM_PLANE_TAKEDOWN"_J, + "AM_DISTRACT_COPS"_J, + "AM_DESTROY_VEH"_J, + "AM_HOT_TARGET"_J, + "AM_KILL_LIST"_J, + "AM_TIME_TRIAL"_J, + "AM_CP_COLLECTION"_J, + "AM_CHALLENGES"_J, + "AM_PENNED_IN"_J, + "AM_PASS_THE_PARCEL"_J, + "AM_HOT_PROPERTY"_J, + "AM_DEAD_DROP"_J, + "AM_KING_OF_THE_CASTLE"_J, + "AM_CRIMINAL_DAMAGE"_J, + "AM_HUNT_THE_BEAST"_J, + "GB_LIMO_ATTACK"_J, + "GB_DEATHMATCH"_J, + "GB_STEAL_VEH"_J, + "GB_POINT_TO_POINT"_J, + "GB_TERMINATE"_J, + "GB_YACHT_ROB"_J, + "GB_BELLYBEAST"_J, + "GB_FIVESTAR"_J, + "GB_ROB_SHOP"_J, + "GB_COLLECT_MONEY"_J, + "GB_ASSAULT"_J, + "GB_VEH_SURV"_J, + "GB_SIGHTSEER"_J, + "GB_FLYING_IN_STYLE"_J, + "GB_FINDERSKEEPERS"_J, + "GB_HUNT_THE_BOSS"_J, + "GB_CARJACKING"_J, + "GB_HEADHUNTER"_J, + "GB_CONTRABAND_BUY"_J, + "GB_CONTRABAND_SELL"_J, + "GB_CONTRABAND_DEFEND"_J, + "GB_AIRFREIGHT"_J, + "GB_CASHING_OUT"_J, + "GB_SALVAGE"_J, + "GB_FRAGILE_GOODS"_J, + "GB_VEHICLE_EXPORT"_J, + "GB_VEHICLE_EXPORT"_J, + "GB_PLOUGHED"_J, + "GB_FULLY_LOADED"_J, + "GB_AMPHIBIOUS_ASSAULT"_J, + "GB_TRANSPORTER"_J, + "GB_FORTIFIED"_J, + "GB_VELOCITY"_J, + "GB_RAMPED_UP"_J, + "GB_STOCKPILING"_J, + "GB_BIKER_RACE_P2P"_J, + "GB_BIKER_JOUST"_J, + "GB_BIKER_UNLOAD_WEAPONS"_J, + ""_J, + "GB_BIKER_BAD_DEAL"_J, + "GB_BIKER_RESCUE_CONTACT"_J, + "GB_BIKER_LAST_RESPECTS"_J, + "GB_BIKER_CONTRACT_KILLING"_J, + "GB_BIKER_CONTRABAND_SELL"_J, + "GB_BIKER_CONTRABAND_DEFEND"_J, + "GB_ILLICIT_GOODS_RESUPPLY"_J, + "GB_BIKER_DRIVEBY_ASSASSIN"_J, + "GB_BIKER_RIPPIN_IT_UP"_J, + "GB_BIKER_FREE_PRISONER"_J, + "GB_BIKER_SAFECRACKER"_J, + "GB_BIKER_STEAL_BIKES"_J, + "GB_BIKER_SEARCH_AND_DESTROY"_J, + "AM_PENNED_IN"_J, + "GB_BIKER_STAND_YOUR_GROUND"_J, + "GB_BIKER_CRIMINAL_MISCHIEF"_J, + "GB_BIKER_DESTROY_VANS"_J, + "GB_BIKER_BURN_ASSETS"_J, + "GB_BIKER_SHUTTLE"_J, + "GB_BIKER_WHEELIE_RIDER"_J, + "GB_GUNRUNNING"_J, + "GB_GUNRUNNING"_J, + "GB_GUNRUNNING_DEFEND"_J, + "GB_SMUGGLER"_J, + "GB_SMUGGLER"_J, + "GB_SMUGGLER"_J, + "GB_GANGOPS"_J, + "BUSINESS_BATTLES"_J, + "BUSINESS_BATTLES_SELL"_J, + "BUSINESS_BATTLES_DEFEND"_J, + "GB_SECURITY_VAN"_J, + "GB_TARGET_PURSUIT"_J, + "GB_JEWEL_STORE_GRAB"_J, + "GB_BANK_JOB"_J, + "GB_DATA_HACK"_J, + "GB_INFILTRATION"_J, + "BUSINESS_BATTLES_DEFEND"_J, + "BUSINESS_BATTLES_SELL"_J, + "GB_CASINO"_J, + "GB_CASINO_HEIST"_J, + "fm_content_business_battles"_J, + "fm_content_drug_vehicle"_J, + "fm_content_movie_props"_J, + "fm_content_island_heist"_J, + "fm_content_island_dj"_J, + "AM_ISLAND_BACKUP_HELI"_J, + "fm_content_golden_gun"_J, + "fm_content_tuner_robbery"_J, + "fm_content_vehicle_list"_J, + "tuner_sandbox_activity"_J, + "fm_content_auto_shop_delivery"_J, + "fm_content_payphone_hit"_J, + "fm_content_security_contract"_J, + "fm_content_vip_contract_1"_J, + "fm_content_metal_detector"_J, + "am_agency_suv"_J, + "fm_content_phantom_car"_J, + "fm_content_slasher"_J, + "fm_content_sightseeing"_J, + "fm_content_hsw_time_trial"_J, + "fm_content_mp_intro"_J, + "fm_content_hsw_setup"_J, + "fm_content_smuggler_trail"_J, + "fm_content_smuggler_plane"_J, + "fm_content_skydive"_J, + "fm_content_cerberus"_J, + "fm_content_parachuter"_J, + "fm_content_crime_scene"_J, + "fm_content_bar_resupply"_J, + "fm_content_bike_shop_delivery"_J, + "fm_content_clubhouse_contracts"_J, + "fm_content_cargo"_J, + "fm_content_export_cargo"_J, + "fm_content_ammunation"_J, + "fm_content_gunrunning"_J, + "fm_content_source_research"_J, + "fm_content_club_management"_J, + "fm_content_club_odd_jobs"_J, + "fm_content_club_source"_J, + "fm_content_convoy"_J, + "fm_content_robbery"_J, + "fm_content_acid_lab_setup"_J, + "fm_content_acid_lab_source"_J, + "fm_content_acid_lab_sell"_J, + "fm_content_drug_lab_work"_J, + "fm_content_stash_house"_J, + "fm_content_taxi_driver"_J, + "fm_content_xmas_mugger"_J, + "fm_content_bank_shootout"_J, + "fm_content_armoured_truck"_J, + "fm_content_ghosthunt"_J, + "fm_content_ufo_abduction"_J, + "fm_content_smuggler_sell"_J, + "fm_content_smuggler_resupply"_J, + "fm_content_smuggler_ops"_J, + "fm_content_bicycle_time_trial"_J, + "fm_content_possessed_animals"_J, + "fm_content_chop_shop_delivery"_J, + "fm_content_xmas_truck"_J, + "fm_content_tow_truck_work"_J, + "fm_content_vehrob_scoping"_J, + "fm_content_vehrob_task"_J, + "fm_content_vehrob_prep"_J, + "fm_content_vehrob_disrupt"_J, + "fm_content_vehrob_cargo_ship"_J, + "fm_content_vehrob_police"_J, + "fm_content_vehrob_arena"_J, + "fm_content_vehrob_casino_prize"_J, + "fm_content_vehrob_submarine"_J, + "fm_content_bounty_targets"_J, + "fm_content_daily_bounty"_J, + "fm_content_dispatch_work"_J, + "fm_content_pizza_delivery"_J, + "fm_content_hacker_cargo_finale"_J, + "fm_content_hacker_zancudo_fin"_J, + "fm_content_hacker_house_finale"_J, + "fm_content_hacker_whistle_fin"_J, + "fm_content_hacker_cargo_prep"_J, + "fm_content_hacker_zancudo_prep"_J, + "fm_content_hacker_house_prep"_J, + "fm_content_hacker_whistle_prep"_J, + "fm_content_arms_trafficking"_J, + "AM_MP_HOTWIRE"_J, + "fm_content_community_outreach"_J, + "fm_content_car_wash_work"_J, + "fm_content_car_wash_detailing"_J, + "fm_content_helitours_work"_J, + "fm_content_helitours_tour"_J, + "fm_content_weed_shop_work"_J, + "fm_content_weed_shop_delivery"_J, + "fm_content_tycoon_odd_jobs"_J, + "fm_content_cutscene"_J, + "AM_BOAT_TAXI"_J, + "AM_HELI_TAXI"_J, + "fm_hold_up_tut"_J, + "AM_CAR_MOD_TUT"_J, + "AM_CONTACT_REQUESTS"_J, + "am_mission_launch"_J, + "am_npc_invites"_J, + "am_lester_cut"_J, + "am_heist_int"_J, + "am_lowrider_int"_J, + "AM_VEHICLE_SPAWN"_J, + "am_ronTrevor_Cut"_J, + "AM_ARMYBASE"_J, + "AM_PRISON"_J, + "am_rollercoaster"_J, + "am_ferriswheel"_J, + "AM_LAUNCHER"_J, + "AM_DAILY_OBJECTIVES"_J, + "AM_ArmWrestling"_J, + "AM_Darts"_J, + "golf_mp"_J, + "Range_Modern_MP"_J, + "tennis_network_mp"_J, + "Pilot_School_MP"_J, + "FM_Impromptu_DM_Controler"_J, + "fm_Bj_race_controler"_J, + "fm_deathmatch_controler"_J, + "fm_hideout_controler"_J, + "fm_mission_controller"_J, + "FM_Race_Controler"_J, + "FM_Horde_Controler"_J, + "dont_cross_the_line"_J, + "am_darts_apartment"_J, + "AM_Armwrestling_Apartment"_J, + "grid_arcade_cabinet"_J, + "scroll_arcade_cabinet"_J, + "example_arcade"_J, + "road_arcade"_J, + "gunslinger_arcade"_J, + "wizard_arcade"_J, + "AM_CASINO_LIMO"_J, + "AM_CASINO_LUXURY_CAR"_J, + "Degenatron Games"_J, + "ggsm_arcade"_J, + "puzzle"_J, + "camhedz_arcade"_J, + "SCTV"_J, + }); +} \ No newline at end of file diff --git a/src/game/gta/data/ScriptNames.hpp b/src/game/gta/data/ScriptNames.hpp index a8eafc8..1481f7d 100644 --- a/src/game/gta/data/ScriptNames.hpp +++ b/src/game/gta/data/ScriptNames.hpp @@ -2,7 +2,8 @@ namespace YimMenu { - static constexpr auto scriptNames = std::to_array({"abigail1", + static constexpr auto scriptNames = std::to_array({ + "abigail1", "abigail2", "achievement_controller", "activity_creator_prototype_launcher", @@ -25,8 +26,8 @@ namespace YimMenu "ambient_tonya", "ambient_tonyacall", "ambient_tonyacall2", - "ambient_ufos", "ambient_tonyacall5", + "ambient_ufos", "am_agency_suv", "am_airstrike", "am_ammo_drop", @@ -34,8 +35,8 @@ namespace YimMenu "am_armwrestling", "am_armwrestling_apartment", "am_armybase", - "am_beach_washup_cinematic", "am_backup_heli", + "am_beach_washup_cinematic", "am_boat_taxi", "am_bru_box", "am_car_mod_tut", @@ -45,8 +46,8 @@ namespace YimMenu "am_challenges", "am_contact_requests", "am_cp_collection", - "am_criminal_damage", "am_crate_drop", + "am_criminal_damage", "am_darts", "am_darts_apartment", "am_dead_drop", @@ -69,13 +70,13 @@ namespace YimMenu "am_hs4_lsa_take_vel", "am_hs4_nimb_isd_lsa_leave", "am_hs4_nimb_lsa_isd_arrive", - "am_hs4_vel_lsa_isd", "am_hs4_nimb_lsa_isd_leave", + "am_hs4_vel_lsa_isd", "am_hunt_the_beast", "am_imp_exp", "am_island_backup_heli", - "am_kill_list", "am_joyrider", + "am_kill_list", "am_king_of_the_castle", "am_launcher", "am_lester_cut", @@ -89,21 +90,21 @@ namespace YimMenu "am_mp_arcade_fortune_teller", "am_mp_arcade_love_meter", "am_mp_arcade_peds", - "am_mp_arc_cab_manager", "am_mp_arcade_strength_test", + "am_mp_arc_cab_manager", "am_mp_arena_box", "am_mp_arena_garage", - "am_mp_armory_truck", "am_mp_armory_aircraft", + "am_mp_armory_truck", "am_mp_auto_shop", "am_mp_bail_office", - "am_mp_boardroom_seating", "am_mp_biker_warehouse", + "am_mp_boardroom_seating", "am_mp_bunker", "am_mp_business_hub", "am_mp_carwash_launch", - "am_mp_car_meet_sandbox", "am_mp_car_meet_property", + "am_mp_car_meet_sandbox", "am_mp_casino", "am_mp_casino_apartment", "am_mp_casino_nightclub", @@ -124,14 +125,17 @@ namespace YimMenu "am_mp_juggalo_hideout", "am_mp_multistorey_garage", "am_mp_music_studio", - "am_mp_orbital_cannon", "am_mp_nightclub", + "am_mp_orbital_cannon", "am_mp_peds", "am_mp_property_ext", "am_mp_property_int", "am_mp_rc_vehicle", "am_mp_rpa_menu", "am_mp_salvage_yard", + "am_mp_sb_car_wash", + "am_mp_sb_heli_tours", + "am_mp_sb_weed_shop", "am_mp_shooting_range", "am_mp_simeon_showroom", "am_mp_smoking_activity", @@ -143,10 +147,10 @@ namespace YimMenu "am_mp_vehicle_organization_menu", "am_mp_vehicle_reward", "am_mp_vehicle_weapon", - "am_mp_vinewood_premium_modshop", "am_mp_vinewood_premium_garage", - "am_mp_yacht", + "am_mp_vinewood_premium_modshop", "am_mp_warehouse", + "am_mp_yacht", "am_npc_invites", "am_pass_the_parcel", "am_penned_in", @@ -158,8 +162,8 @@ namespace YimMenu "am_rollercoaster", "am_rontrevor_cut", "am_simosa", - "am_vehicle_spawn", "am_taxi", + "am_vehicle_spawn", "animal_controller", "apartment_minigame_launcher", "apparcadebusiness", @@ -174,8 +178,8 @@ namespace YimMenu "appchecklist", "appcontacts", "appcovertops", - "appextraction", "appemail", + "appextraction", "appfixersecurity", "apphackerden", "apphackertruck", @@ -183,9 +187,9 @@ namespace YimMenu "appimportexport", "appinternet", "appjipmp", - "appmpemail", - "appmpbossagency", "appmedia", + "appmpbossagency", + "appmpemail", "appmpjoblistnew", "apporganiser", "appprogresshub", @@ -219,15 +223,15 @@ namespace YimMenu "autosave_controller", "auto_shop_seating", "bailbond1", - "bailbond4", - "bailbond3", "bailbond2", + "bailbond3", + "bailbond4", "bailbond_launcher", "bail_office_seating", "barry1", "barry2", - "barry3a", "barry3", + "barry3a", "barry3c", "barry4", "base_carmod", @@ -251,8 +255,8 @@ namespace YimMenu "bugstar_mission_export", "buildingsiteambience", "building_controller", - "business_battles_defend", "business_battles", + "business_battles_defend", "business_battles_sell", "business_hub_carmod", "business_hub_garage_seats", @@ -263,8 +267,8 @@ namespace YimMenu "candidate_controller", "carmod_shop", "carsteal1", - "carsteal3", "carsteal2", + "carsteal3", "carsteal4", "carwash1", "carwash2", @@ -286,12 +290,12 @@ namespace YimMenu "cellphone_controller", "cellphone_flashhand", "charactergoals", - "cheat_controller", "charanimtest", + "cheat_controller", "chinese1", "chinese2", - "circuitblockhack", "chop", + "circuitblockhack", "clothes_shop_mp", "clothes_shop_sp", "code_controller", @@ -307,8 +311,8 @@ namespace YimMenu "controller_trafficking", "coordinate_recorder", "country_race", - "creation_startup", "country_race_controller", + "creation_startup", "creator", "custom_config", "cutscenemetrics", @@ -322,32 +326,32 @@ namespace YimMenu "debug_ped_data", "degenatron_games", "density_test", - "director_mode", "dialogue_handler", + "director_mode", "docks2asubhandler", "docks_heista", - "docks_prep1", "docks_heistb", + "docks_prep1", "docks_prep2b", "docks_setup", "dont_cross_the_line", "dreyfuss1", - "drf2", "drf1", + "drf2", "drf3", - "drf5", "drf4", + "drf5", "drunk", "drunk_controller", "dynamixtest", - "emergencycall", "email_controller", + "emergencycall", "emergencycalllauncher", "epscars", "epsdesert", "epsilon1", - "epsilon3", "epsilon2", + "epsilon3", "epsilon4", "epsilon5", "epsilon6", @@ -359,11 +363,11 @@ namespace YimMenu "error_thrower", "event_controller", "exile1", - "exile_city_denial", "exile2", "exile3", - "extreme2", + "exile_city_denial", "extreme1", + "extreme2", "extreme3", "extreme4", "fairgroundhub", @@ -371,13 +375,13 @@ namespace YimMenu "fameorshame_eps", "fameorshame_eps_1", "fame_or_shame_set", + "family1", "family1taxi", "family2", - "family1", "family3", - "family6", "family4", "family5", + "family6", "family_scene_f0", "family_scene_f1", "family_scene_m", @@ -397,10 +401,10 @@ namespace YimMenu "fbi4_prep3amb", "fbi4_prep4", "fbi4_prep5", - "field_hangar_seating", "fbi5a", - "finaleb", + "field_hangar_seating", "finalea", + "finaleb", "finalec1", "finalec2", "finale_choice", @@ -410,8 +414,8 @@ namespace YimMenu "finale_heist2a", "finale_heist2b", "finale_heist2_intro", - "finale_heist_prepb", "finale_heist_prepa", + "finale_heist_prepb", "finale_heist_prepc", "finale_heist_prepd", "finale_heist_prepeamb", @@ -433,8 +437,8 @@ namespace YimMenu "fm_bj_race_controler", "fm_capture_creator", "fm_content_acid_lab_sell", - "fm_content_acid_lab_source", "fm_content_acid_lab_setup", + "fm_content_acid_lab_source", "fm_content_ammunation", "fm_content_armoured_truck", "fm_content_arms_trafficking", @@ -446,6 +450,8 @@ namespace YimMenu "fm_content_bounty_targets", "fm_content_business_battles", "fm_content_cargo", + "fm_content_car_wash_detailing", + "fm_content_car_wash_work", "fm_content_cerberus", "fm_content_chop_shop_delivery", "fm_content_clubhouse_contracts", @@ -455,6 +461,7 @@ namespace YimMenu "fm_content_community_outreach", "fm_content_convoy", "fm_content_crime_scene", + "fm_content_cutscene", "fm_content_daily_bounty", "fm_content_dispatch_work", "fm_content_drone", @@ -472,6 +479,8 @@ namespace YimMenu "fm_content_hacker_whistle_prep", "fm_content_hacker_zancudo_fin", "fm_content_hacker_zancudo_prep", + "fm_content_helitours_tour", + "fm_content_helitours_work", "fm_content_hsw_setup", "fm_content_hsw_time_trial", "fm_content_island_dj", @@ -479,44 +488,47 @@ namespace YimMenu "fm_content_metal_detector", "fm_content_movie_props", "fm_content_mp_intro", - "fm_content_payphone_hit", "fm_content_parachuter", + "fm_content_payphone_hit", "fm_content_phantom_car", "fm_content_pizza_delivery", - "fm_content_security_contract", - "fm_content_robbery", "fm_content_possessed_animals", + "fm_content_robbery", + "fm_content_security_contract", "fm_content_sightseeing", - "fm_content_slasher", "fm_content_skydive", + "fm_content_slasher", "fm_content_smuggler_ops", "fm_content_smuggler_plane", "fm_content_smuggler_resupply", - "fm_content_smuggler_trail", "fm_content_smuggler_sell", + "fm_content_smuggler_trail", "fm_content_source_research", "fm_content_stash_house", "fm_content_taxi_driver", "fm_content_test", "fm_content_tow_truck_work", "fm_content_tuner_robbery", + "fm_content_tycoon_odd_jobs", "fm_content_ufo_abduction", "fm_content_vehicle_list", "fm_content_vehrob_arena", "fm_content_vehrob_cargo_ship", "fm_content_vehrob_casino_prize", - "fm_content_vehrob_police", "fm_content_vehrob_disrupt", + "fm_content_vehrob_police", "fm_content_vehrob_prep", "fm_content_vehrob_scoping", "fm_content_vehrob_submarine", - "fm_content_vip_contract_1", "fm_content_vehrob_task", + "fm_content_vip_contract_1", + "fm_content_weed_shop_delivery", + "fm_content_weed_shop_work", "fm_content_xmas_mugger", "fm_content_xmas_truck", "fm_deathmatch_controler", - "fm_hideout_controler", "fm_deathmatch_creator", + "fm_hideout_controler", "fm_hold_up_tut", "fm_horde_controler", "fm_impromptu_dm_controler", @@ -538,22 +550,22 @@ namespace YimMenu "fps_test", "fps_test_mag", "franklin0", - "franklin2", "franklin1", + "franklin2", "freemode", "freemode_clearglobals", "freemode_creator", "freemode_init", - "friends_controller", "friendactivity", + "friends_controller", "friends_debug_controller", "fullmap_test", "fullmap_test_flow", "game_server_test", "gb_airfreight", "gb_amphibious_assault", - "gb_bank_job", "gb_assault", + "gb_bank_job", "gb_bellybeast", "gb_biker_bad_deal", "gb_biker_burn_assets", @@ -574,11 +586,11 @@ namespace YimMenu "gb_biker_shuttle", "gb_biker_stand_your_ground", "gb_biker_steal_bikes", - "gb_biker_unload_weapons", "gb_biker_target_rival", + "gb_biker_unload_weapons", "gb_biker_wheelie_rider", - "gb_cashing_out", "gb_carjacking", + "gb_cashing_out", "gb_casino", "gb_casino_heist", "gb_casino_heist_planning", @@ -602,8 +614,8 @@ namespace YimMenu "gb_headhunter", "gb_hunt_the_boss", "gb_ie_delivery_cutscene", - "gb_infiltration", "gb_illicit_goods_resupply", + "gb_infiltration", "gb_jewel_store_grab", "gb_ploughed", "gb_point_to_point", @@ -615,15 +627,16 @@ namespace YimMenu "gb_smuggler", "gb_stockpiling", "gb_target_pursuit", - "gb_transporter", "gb_terminate", + "gb_transporter", "gb_vehicle_export", "gb_velocity", - "general_test", "gb_yacht_rob", + "general_test", "ggsm_arcade", - "globals_fmmc_struct_registration", "globals_fmmcstruct2_registration", + "globals_fmmcstruct3_registration", + "globals_fmmc_struct_registration", "golf", "golf_ai_foursome", "golf_ai_foursome_putting", @@ -649,20 +662,20 @@ namespace YimMenu "gtest_divingfromcar", "gtest_divingfromcarwhilefleeing", "gtest_helicopter", - "gunclub_shop", "gtest_nearlymissedbycar", + "gunclub_shop", "gunfighttest", "gunslinger_arcade", "hacker_den_carmod", "hacker_den_ext_seating", "hacker_den_seating", - "hairdo_shop_mp", "hacker_truck_carmod", + "hairdo_shop_mp", "hairdo_shop_sp", "hangar_carmod", + "hao1", "headertest", "heatmap_test", - "hao1", "heatmap_test_flow", "heist_ctrl_agency", "heist_ctrl_docks", @@ -670,16 +683,16 @@ namespace YimMenu "heist_ctrl_jewel", "heist_ctrl_rural", "heist_island_planning", - "heli_streaming", "heli_gun", + "heli_streaming", "hud_creator", + "hunting1", + "hunting2", "hunting_ambient", "idlewarper", - "hunting2", - "hunting1", "ingamehud", - "item_ownership_output", "initial", + "item_ownership_output", "jewelry_heist", "jewelry_prep1a", "jewelry_prep1b", @@ -700,13 +713,13 @@ namespace YimMenu "launcher_basejumppack", "launcher_carwash", "launcher_darts", - "launcher_epsilon", "launcher_dreyfuss", + "launcher_epsilon", "launcher_extreme", "launcher_fanatic", - "launcher_hunting", "launcher_golf", "launcher_hao", + "launcher_hunting", "launcher_hunting_ambient", "launcher_josh", "launcher_maude", @@ -722,34 +735,34 @@ namespace YimMenu "launcher_range", "launcher_stunts", "launcher_tennis", - "launcher_tonya", "launcher_thelastone", + "launcher_tonya", "launcher_triathlon", "launcher_yoga", - "lesterhandler", "lester1", + "lesterhandler", "letterscraps", "line_activation_test", "liverecorder", "localpopulator", - "luxe_veh_activity", "locates_tester", + "luxe_veh_activity", "magdemo", - "main", - "main_install", "magdemo2", + "main", "maintransition", + "main_install", "main_persistent", "martin1", "maude1", "maude_postbailbond", "me_amanda1", "me_jimmy1", - "mg_race_to_point", "me_tracey1", + "mg_race_to_point", "michael1", - "michael3", "michael2", + "michael3", "michael4", "michael4leadout", "minigame_ending_stinger", @@ -776,21 +789,21 @@ namespace YimMenu "mp_menuped", "mp_player_damage_numbers", "mp_prop_global_block", - "mp_registration", "mp_prop_special_global_block", - "mp_skycam_stuck_wiggler", + "mp_registration", "mp_save_game_global_block", + "mp_skycam_stuck_wiggler", "mp_unlocks", "mp_weapons", - "mrsphilips2", "mrsphilips1", + "mrsphilips2", "multistorey_garage_ext_seating", "multistorey_garage_seating", "murdermystery", "music_studio_seating", "music_studio_seating_external", - "navmeshtest", "music_studio_smoking", + "navmeshtest", "net_activity_creator_ui", "net_apartment_activity", "net_apartment_activity_light", @@ -801,6 +814,7 @@ namespace YimMenu "net_freemode_debug_2023", "net_freemode_debug_stat_2023", "net_jacking_soaktest", + "net_rank_tunable_loader", "net_session_soaktest", "net_test_drive", "net_tunable_check", @@ -821,8 +835,8 @@ namespace YimMenu "ob_abattoircut", "ob_airdancer", "ob_bong", - "ob_drinking_shots", "ob_cashregister", + "ob_drinking_shots", "ob_foundry_cauldron", "ob_franklin_beer", "ob_franklin_tv", @@ -852,42 +866,42 @@ namespace YimMenu "paparazzo3a", "paparazzo3b", "paparazzo4", - "paradise2", "paradise", + "paradise2", "pausemenu", "pausemenucareerhublaunch", "pausemenu_example", "pausemenu_map", "pausemenu_multiplayer", "pausemenu_sp_repeat", - "pb_homeless", "pb_busker", + "pb_homeless", "pb_preacher", "pb_prostitute", "personal_carmod_shop", "photographymonkey", - "physics_perf_test", "photographywildlife", + "physics_perf_test", "physics_perf_test_launcher", "pickuptest", - "pickup_controller", "pickupvehicles", + "pickup_controller", "pilot_school", - "placeholdermission", "pilot_school_mp", "pi_menu", + "placeholdermission", "placementtest", - "player_controller_b", "planewarptest", "player_controller", + "player_controller_b", "player_scene_ft_franklin1", "player_scene_f_lamgraff", "player_scene_f_lamtaunt", "player_scene_f_taxi", "player_scene_mf_traffic", "player_scene_m_cinema", - "player_scene_m_kids", "player_scene_m_fbi2", + "player_scene_m_kids", "player_scene_m_shopping", "player_scene_t_bbfight", "player_scene_t_chasecar", @@ -898,17 +912,18 @@ namespace YimMenu "playthrough_builder", "pm_defend", "pm_delivery", - "pm_plane_promotion", "pm_gang_attack", - "postkilled_bailbond2", + "pm_plane_promotion", "pm_recover_stolen", - "postrc_barry4", + "postkilled_bailbond2", "postrc_barry1and2", + "postrc_barry4", "postrc_epsilon4", "postrc_nigel3", "profiler_registration", "prologue1", "prop_drop", + "public_mission_creator", "puzzle", "racetest", "rampage1", @@ -918,10 +933,10 @@ namespace YimMenu "rampage5", "rampage_controller", "randomchar_controller", - "range_modern_mp", "range_modern", - "replay_controller", + "range_modern_mp", "rcpdata", + "replay_controller", "rerecord_recording", "respawn_controller", "restrictedareas", @@ -937,12 +952,12 @@ namespace YimMenu "re_cartheft", "re_chasethieves", "re_crashrescue", - "re_dealgonewrong", "re_cultshootout", + "re_dealgonewrong", "re_domestic", "re_drunkdriver", - "re_gangfight", "re_duel", + "re_gangfight", "re_gang_intimidation", "re_getaway_driver", "re_hitch_lift", @@ -952,8 +967,8 @@ namespace YimMenu "re_monkey", "re_mountdance", "re_muggings", - "re_prison", "re_paparazzi", + "re_prison", "re_prisonerlift", "re_prisonvanbreak", "re_rescuehostage", @@ -968,12 +983,14 @@ namespace YimMenu "rollercoaster", "rural_bank_heist", "rural_bank_prep1", - "salvage_yard_seating", "rural_bank_setup", + "salvage_yard_seating", "savegame_bed", "save_anywhere", - "scaleformminigametest", + "sb_heli_tours_seating", + "sb_weed_shop_seating", "scaleformgraphictest", + "scaleformminigametest", "scaleformprofiling", "scaleformtest", "scene_builder", @@ -986,8 +1003,8 @@ namespace YimMenu "scripttest4", "script_metrics", "scroll_arcade_cabinet", - "sc_lb_global_block", "sctv", + "sc_lb_global_block", "selector", "selector_example", "selling_short_1", @@ -999,27 +1016,27 @@ namespace YimMenu "shrinkletter", "sh_intro_f_hills", "sh_intro_m_home", - "smoketest", "simeon_showroom_seating", + "smoketest", "social_controller", "solomon1", "solomon2", "solomon3", "spaceshipparts", "spawn_activities", - "spmc_instancer", "speech_reverb_tracker", + "spmc_instancer", "spmc_preloader", "sp_dlc_registration", "sp_editor_mission_instance", - "sp_pilotschool_reg", "sp_menuped", + "sp_pilotschool_reg", "standard_global_init", "standard_global_reg", "startup", "startup_install", - "startup_positioning", "startup_locationtest", + "startup_positioning", "startup_smoketest", "stats_controller", "stock_controller", @@ -1045,8 +1062,8 @@ namespace YimMenu "taxi_takeiteasy", "taxi_taketobest", "tempalpha", - "tennis", "temptest", + "tennis", "tennis_ambient", "tennis_family", "tennis_network_mp", @@ -1054,13 +1071,13 @@ namespace YimMenu "thelastone", "three_card_poker", "timershud", - "title_update_registration_2", "title_update_registration", + "title_update_registration_2", "tonya1", "tonya2", - "tonya5", "tonya3", "tonya4", + "tonya5", "towing", "traffickingsettings", "traffickingteleport", @@ -1069,26 +1086,26 @@ namespace YimMenu "train_create_widget", "train_tester", "trevor1", - "trevor3", "trevor2", + "trevor3", "trevor4", "triathlonsp", "tunables_registration", - "tuner_planning", "tuneables_processing", + "tuner_planning", "tuner_property_carmod", "tuner_sandbox_activity", - "ufo", "turret_cam_script", + "ufo", "ugc_global_registration", "ugc_global_registration_2", "underwaterpickups", - "vehiclespawning", "utvc", + "vehiclespawning", "vehicle_ai_test", "vehicle_force_widget", - "vehicle_plate", "vehicle_gen_controller", + "vehicle_plate", "vehicle_stealth_mode", "vehrob_planning", "veh_play_widget", @@ -1101,5 +1118,6 @@ namespace YimMenu "word_hack", "wp_partyboombox", "xml_menus", - "yoga"}); + "yoga", + }); } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 0bc4008..d7cd07d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,6 +10,7 @@ #include "core/hooking/CallHook.hpp" #include "core/memory/ModuleMgr.hpp" #include "core/renderer/Renderer.hpp" +#include "core/scripting/LuaManager.hpp" #include "game/backend/AnticheatBypass.hpp" #include "game/backend/Players.hpp" #include "game/backend/SavedLocations.hpp" @@ -70,6 +71,7 @@ namespace YimMenu ScriptMgr::AddScript(std::make_unique