mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-10 03:43:15 +08:00
feat(lua): initial lua scripting prototype
This commit is contained in:
+4
-1
@@ -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)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE AsyncLogger imgui minhook nlohmann_json::nlohmann_json dbghelp d3dcompiler dwmapi libluajit)
|
||||
@@ -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"
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
#include "LuaLibrary.hpp"
|
||||
#include "LuaManager.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
LuaLibrary::LuaLibrary()
|
||||
{
|
||||
LuaManager::RegisterLibrary(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "lua.hpp"
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
class LuaLibrary
|
||||
{
|
||||
public:
|
||||
LuaLibrary();
|
||||
|
||||
virtual void Register(lua_State* state) = 0;
|
||||
};
|
||||
}
|
||||
@@ -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<LuaScript>(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;
|
||||
}
|
||||
}
|
||||
@@ -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<std::shared_ptr<LuaScript>> m_LoadedScripts;
|
||||
std::vector<LuaLibrary*> m_Libraries;
|
||||
std::queue<std::string> 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();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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<LuaScript*>(lua_touserdata(state, -1));
|
||||
lua_pop(state, 1);
|
||||
return *script;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -242,21 +242,24 @@ namespace YimMenu::Submenus
|
||||
ImGui::EndGroup();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
RenderBytecode(curProgram);
|
||||
if (ImGui::TreeNode("Bytecode"))
|
||||
{
|
||||
RenderBytecode(curProgram);
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
script->AddItem(std::make_unique<ImGuiItem>([] {
|
||||
static std::string scriptSearch = "";
|
||||
static std::string scriptName = "";
|
||||
static std::string stackSizeName = stackSizes[0].first;
|
||||
static std::optional<int> 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<ImGuiItem>([] {
|
||||
|
||||
@@ -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<int> 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<GtaThread*>(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<int*>();
|
||||
*bypass_global.As<int*>() = 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<int*>() = old_val;
|
||||
}
|
||||
}
|
||||
@@ -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<std::uint32_t> GetCodeLocationByPattern(rage::scrProgram* program, SimplePattern pattern);
|
||||
extern void ForceScriptHost(rage::scrThread* thread); // likely unstable, beware!
|
||||
extern std::optional<int> GetLauncherIndexFromScript(joaat_t hash);
|
||||
extern void StartLauncherScript(joaat_t hash);
|
||||
extern void ForceScriptOnPlayer(joaat_t hash, int bits);
|
||||
}
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
+126
-108
@@ -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",
|
||||
});
|
||||
}
|
||||
@@ -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<Script>(&Self::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&GUI::RunScript));
|
||||
FiberPool::Init(16);
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&LuaManager::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&HotkeySystem::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&Commands::RunScript));
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&Features::SavePersonalVehicle::RunScript));
|
||||
|
||||
@@ -101,5 +101,10 @@ public:
|
||||
|
||||
return m_Host->m_Player;
|
||||
}
|
||||
|
||||
inline bool IsParticipant(int player_index) const
|
||||
{
|
||||
return (m_ParticipantBitset & (1 << player_index)) != 0;
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(CGameScriptHandlerNetComponent) == 0x1B0);
|
||||
@@ -1,11 +1,19 @@
|
||||
#pragma once
|
||||
#include "types.hpp"
|
||||
|
||||
// names taken from GTA5_Enhanced.exe+0x2252260 (0F 84 7F 01 00 00 4C 8B 47 20 48 8D 15 -0x21) (SCRIPT_EVENT_FPOM)
|
||||
struct MP_SCRIPT_DATA
|
||||
{
|
||||
SCR_INT Index; // this is an enum
|
||||
uint64_t Args[15];
|
||||
SCR_INT InstanceId;
|
||||
uint64_t MoreArgs[4];
|
||||
SCR_INT MissionIndex; // this is an enum
|
||||
SCR_INT Variation;
|
||||
SCR_INT Creator;
|
||||
TEXT_LABEL_23 CloudFileName;
|
||||
SCR_INT SharedRegId;
|
||||
uint64_t PAD_0005[6]; // not serialized in the metric
|
||||
SCR_INT InstanceId;
|
||||
SCR_INT UniqueId;
|
||||
SCR_INT BitSet;
|
||||
SCR_INT GenericInt;
|
||||
SCR_INT TruckBitSet;
|
||||
};
|
||||
static_assert(sizeof(MP_SCRIPT_DATA) == 21 * 8);
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "types.hpp"
|
||||
#include "MPScriptData.hpp"
|
||||
|
||||
#define REGISTER_SCRIPT_EVENT(classType, indexType) \
|
||||
constexpr static auto EVENT_INDEX = ScriptEventIndex::indexType; \
|
||||
@@ -77,7 +78,7 @@ enum class ScriptEventIndex
|
||||
TriggerCEORaid = -1906536929,
|
||||
|
||||
StartScriptBegin = -366707054,
|
||||
StartScriptProceed = 1757622014,
|
||||
StartScriptProceed = 1757622014,
|
||||
|
||||
RequestRandomEvent = -126218586,
|
||||
CollectCollectable = 968269233,
|
||||
@@ -97,7 +98,7 @@ public:
|
||||
return SenderIndex;
|
||||
}
|
||||
|
||||
Hash GetEventIndex() const
|
||||
Hash& GetEventIndex()
|
||||
{
|
||||
return EventIndex;
|
||||
}
|
||||
@@ -121,6 +122,11 @@ public:
|
||||
{
|
||||
PlayerBits |= (1 << player);
|
||||
}
|
||||
|
||||
void SetPlayerBits(int bits)
|
||||
{
|
||||
PlayerBits = bits;
|
||||
}
|
||||
|
||||
protected:
|
||||
void SendImpl(int size);
|
||||
@@ -255,4 +261,22 @@ struct SET_SKYDIVE_COMPLETED : public SCRIPT_EVENT
|
||||
SCR_BOOL AccurateLanding;
|
||||
};
|
||||
|
||||
// FPOM
|
||||
struct SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION : public SCRIPT_EVENT
|
||||
{
|
||||
REGISTER_SCRIPT_EVENT(SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION, StartScriptBegin);
|
||||
MP_SCRIPT_DATA ScriptData;
|
||||
SCR_INT Flags;
|
||||
SCR_INT ReplayProtectionValue;
|
||||
SCR_INT PAD_0026;
|
||||
};
|
||||
static_assert(sizeof(SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION) == 27 * 8);
|
||||
|
||||
struct SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION_SERVER_ACK : public SCRIPT_EVENT
|
||||
{
|
||||
REGISTER_SCRIPT_EVENT(SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION_SERVER_ACK, StartScriptProceed);
|
||||
MP_SCRIPT_DATA ScriptData;
|
||||
};
|
||||
static_assert(sizeof(SCRIPT_EVENT_FORCE_PLAYER_ON_MISSION_SERVER_ACK) == 24 * 8);
|
||||
|
||||
#undef REGISTER_SCRIPT_EVENT
|
||||
@@ -315,7 +315,7 @@ struct GBPD_FM_3_Entry
|
||||
SCR_BOOL TimeTrialActive; // verify
|
||||
BOSS_GOON BossGoon;
|
||||
uint64_t PAD_507[3]; // unused
|
||||
SCR_INT ScriptEventReplayProtectionCounter;
|
||||
SCR_INT ScriptEventReplayProtectionCounter; // "uniqueId"
|
||||
TIMER CoronaForcedLaunchTimer;
|
||||
LEAVE_IN_HELI LeaveInHeli;
|
||||
SCR_INT OfficeDesktopFlags; // bit 0 -> login, bit 1 -> map
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "DailyObjectivesState.hpp"
|
||||
#include "WeeklyChallenge.hpp"
|
||||
#include "FreemodeDelivery.hpp"
|
||||
#include "LauncherServerData.hpp"
|
||||
#include "game/gta/ScriptGlobal.hpp"
|
||||
|
||||
#define DEFINE_GLOBAL_ACCESSOR(str, global) \
|
||||
@@ -50,4 +51,5 @@ DEFINE_GLOBAL_ACCESSOR(g_SavedMPGlobals, 2359296);
|
||||
DEFINE_GLOBAL_ACCESSOR(FreemodeGeneral, 2740191);
|
||||
DEFINE_GLOBAL_ACCESSOR(DailyObjectivesState, 1574745);
|
||||
DEFINE_GLOBAL_ACCESSOR(WeeklyChallenge, 2739243);
|
||||
DEFINE_GLOBAL_ACCESSOR(FreemodeDelivery, 1953035);
|
||||
DEFINE_GLOBAL_ACCESSOR(FreemodeDelivery, 1953035);
|
||||
DEFINE_GLOBAL_ACCESSOR(LauncherServerData, 2699563);
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
#include "types/script/types.hpp"
|
||||
#include "types/script/Timer.hpp"
|
||||
|
||||
enum class eHostScriptState
|
||||
{
|
||||
INITIALIZING,
|
||||
RUNNING,
|
||||
PREPARING_TO_SHUT_DOWN,
|
||||
SHUTTING_DOWN
|
||||
};
|
||||
|
||||
enum class eLauncherFlags
|
||||
{
|
||||
RUN_IMMEDIATELY = 1
|
||||
};
|
||||
|
||||
enum class eLauncherState
|
||||
{
|
||||
EMPTY,
|
||||
FIND_SCRIPT,
|
||||
UNK_2, // unused
|
||||
PICK_MISSION_VARIATION,
|
||||
UNK_4,
|
||||
WAIT_FOR_ACK,
|
||||
START_SCRIPT,
|
||||
WAIT_FOR_TERMINATION,
|
||||
RESET
|
||||
};
|
||||
|
||||
struct LAUNCHER_SCRIPT
|
||||
{
|
||||
SCR_INT EventIndex;
|
||||
SCR_INT LauncherIndex; // this is the script index we want to set
|
||||
SCR_FLOAT Probability;
|
||||
SCR_INT PAD_0003; // unused
|
||||
SCR_BOOL Terminated;
|
||||
};
|
||||
static_assert(sizeof(LAUNCHER_SCRIPT) == 5 * 8);
|
||||
|
||||
struct LauncherServerData
|
||||
{
|
||||
alignas(8) eHostScriptState HostState;
|
||||
SCR_BITSET<eLauncherFlags> Flags;
|
||||
alignas(8) eLauncherState LauncherState;
|
||||
LAUNCHER_SCRIPT CurrentScript;
|
||||
SCR_ARRAY<LAUNCHER_SCRIPT, 21> QueuedScripts;
|
||||
SCR_ARRAY<uint64_t, 21> QueuedEvents;
|
||||
uint64_t PAD_0136[41]; // unused
|
||||
TIMER CrateDropTimer;
|
||||
TIMER ScriptLaunchTimer;
|
||||
SCR_INT TimeToWaitForLaunch;
|
||||
SCR_INT CurrentEvent;
|
||||
SCR_INT ScriptParam1;
|
||||
SCR_INT ScriptParam2;
|
||||
SCR_INT ScriptParam3;
|
||||
|
||||
static LauncherServerData* Get();
|
||||
};
|
||||
static_assert(sizeof(LauncherServerData) == 186 * 8);
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "../types.hpp"
|
||||
#include "../globals/LauncherServerData.hpp"
|
||||
|
||||
struct LauncherClientDataEntry
|
||||
{
|
||||
SCR_INT ClientState;
|
||||
SCR_INT Flags;
|
||||
alignas(8) eLauncherState LauncherState;
|
||||
};
|
||||
static_assert(sizeof(LauncherClientDataEntry) == 3 * 8);
|
||||
|
||||
struct LauncherClientData
|
||||
{
|
||||
SCR_ARRAY<LauncherClientDataEntry, 32> Entries;
|
||||
|
||||
static LauncherClientData* Get(rage::scrThread* thread);
|
||||
};
|
||||
static_assert(sizeof(LauncherClientData) == 97 * 8);
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "RCBanditoTimeTrialData.hpp"
|
||||
#include "HSWTimeTrialData.hpp"
|
||||
#include "BikeTimeTrialData.hpp"
|
||||
#include "LauncherClientData.hpp"
|
||||
#include "game/gta/ScriptLocal.hpp"
|
||||
|
||||
#define DEFINE_LOCAL_ACCESSOR(str, local) \
|
||||
@@ -20,4 +21,7 @@ DEFINE_LOCAL_ACCESSOR(RANDOM_EVENTS_FREEMODE_DATA, 16019);
|
||||
DEFINE_LOCAL_ACCESSOR(StandardTimeTrialData, 14640);
|
||||
DEFINE_LOCAL_ACCESSOR(RCBanditoTimeTrialData, 14690);
|
||||
DEFINE_LOCAL_ACCESSOR(HSWTimeTrialData, 14734);
|
||||
DEFINE_LOCAL_ACCESSOR(BikeTimeTrialData, 15529);
|
||||
DEFINE_LOCAL_ACCESSOR(BikeTimeTrialData, 15529);
|
||||
|
||||
// am_launcher
|
||||
DEFINE_LOCAL_ACCESSOR(LauncherClientData, 245);
|
||||
Reference in New Issue
Block a user