diff --git a/docs/lua/classes/script_util.md b/docs/lua/classes/script_util.md new file mode 100644 index 00000000..841e2d24 --- /dev/null +++ b/docs/lua/classes/script_util.md @@ -0,0 +1,28 @@ +# Class: script_util + +Class for gta script utils, the instance is usually given to you. + +## Functions (2) + +### `yield()` + +Yield execution. + +**Exemple Usage:** +```lua +script_util:yield() +``` + +### `sleep(ms)` + +Sleep for the given amount of time, time is in milliseconds. + +- **Parameters:** + - `ms` (integer): The amount of time in milliseconds that we will sleep for. + +**Exemple Usage:** +```lua +script_util:sleep(ms) +``` + + diff --git a/docs/lua/tables/script.md b/docs/lua/tables/script.md index 7184c730..ac351bd7 100644 --- a/docs/lua/tables/script.md +++ b/docs/lua/tables/script.md @@ -2,11 +2,34 @@ Table containing helper functions related to gta scripts. -## Functions (4) +## Functions (2) ### `register_looped(name, func)` Registers a function that will be looped as a gta script. +**Exemple Usage:** +```lua +script.register_looped("nameOfMyLoopedScript", function (script) + -- sleep until next game frame + script:yield() + + local ModelHash = joaat("adder") + if not STREAMING.IS_MODEL_IN_CDIMAGE(ModelHash) then return end + STREAMING.REQUEST_MODEL(ModelHash) -- Request the model + while not STREAMING.HAS_MODEL_LOADED(ModelHash) do -- Waits for the model to load + script:yield() + end + local myPed = PLAYER.PLAYER_PED_ID() + local myCoords = ENTITY.GET_ENTITY_COORDS(myPed, true) + -- Spawns a networked vehicle on your current coords + local spawnedVehicle = VEHICLE.CREATE_VEHICLE(ModelHash, myCoords.x, myCoords.y, myCoords.z, ENTITY.GET_ENTITY_HEADING(myPed), true, false) + -- removes model from game memory as we no longer need it + STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(ModelHash) + -- sleep for 2s + script:sleep(2000) + ENTITY.DELETE_ENTITY(spawnedVehicle) +end) +``` - **Parameters:** - `name` (string): name of your new looped script @@ -19,35 +42,37 @@ script.register_looped(name, func) ### `run_in_fiber(func)` -Executes a function inside the fiber pool, you can call natives inside it. +Executes a function once inside the fiber pool, you can call natives inside it and yield or sleep. +**Exemple Usage:** +```lua +script.run_in_fiber(function (script) + -- sleep until next game frame + script:yield() + + local ModelHash = joaat("adder") + if not STREAMING.IS_MODEL_IN_CDIMAGE(ModelHash) then return end + STREAMING.REQUEST_MODEL(ModelHash) -- Request the model + while not STREAMING.HAS_MODEL_LOADED(ModelHash) do -- Waits for the model to load + script:yield() + end + local myPed = PLAYER.PLAYER_PED_ID() + local myCoords = ENTITY.GET_ENTITY_COORDS(myPed, true) + -- Spawns a networked vehicle on your current coords + local spawnedVehicle = VEHICLE.CREATE_VEHICLE(ModelHash, myCoords.x, myCoords.y, myCoords.z, ENTITY.GET_ENTITY_HEADING(myPed), true, false) + -- removes model from game memory as we no longer need it + STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(ModelHash) + -- sleep for 2s + script:sleep(2000) + ENTITY.DELETE_ENTITY(spawnedVehicle) +end) +``` - **Parameters:** - - `func` (function): function that will be executed once in the fiber pool, you can call natives inside it. + - `func` (function): function that will be executed once in the fiber pool. **Exemple Usage:** ```lua script.run_in_fiber(func) ``` -### `yield()` - -Yield execution. - -**Exemple Usage:** -```lua -script.yield() -``` - -### `sleep(ms)` - -Sleep for the given amount of time, time is in milliseconds. - -- **Parameters:** - - `ms` (integer): The amount of time in milliseconds that we will sleep for. - -**Exemple Usage:** -```lua -script.sleep(ms) -``` - diff --git a/src/lua/bindings/script.hpp b/src/lua/bindings/script.hpp index 990d388c..8b913d8a 100644 --- a/src/lua/bindings/script.hpp +++ b/src/lua/bindings/script.hpp @@ -6,6 +6,33 @@ namespace lua::script { + // Lua API: Class + // Name: script_util + // Class for gta script utils, the instance is usually given to you. + class script_util + { + public: + // Lua API: Function + // Class: script_util + // Name: yield + // Yield execution. + void yield() + { + big::script::get_current()->yield(); + } + + // Lua API: Function + // Class: script_util + // Name: sleep + // Param: ms: integer: The amount of time in milliseconds that we will sleep for. + // Sleep for the given amount of time, time is in milliseconds. + void sleep(int ms) + { + big::script::get_current()->yield(std::chrono::milliseconds(ms)); + } + }; + static script_util dummy_script_util; + // Lua API: Table // Name: script // Table containing helper functions related to gta scripts. @@ -16,6 +43,29 @@ namespace lua::script // Param: name: string: name of your new looped script // Param: func: function: function that will be executed in a forever loop. // Registers a function that will be looped as a gta script. + // **Exemple Usage:** + // ```lua + // script.register_looped("nameOfMyLoopedScript", function (script) + // -- sleep until next game frame + // script:yield() + // + // local ModelHash = joaat("adder") + // if not STREAMING.IS_MODEL_IN_CDIMAGE(ModelHash) then return end + // STREAMING.REQUEST_MODEL(ModelHash) -- Request the model + // while not STREAMING.HAS_MODEL_LOADED(ModelHash) do -- Waits for the model to load + // script:yield() + // end + // local myPed = PLAYER.PLAYER_PED_ID() + // local myCoords = ENTITY.GET_ENTITY_COORDS(myPed, true) + // -- Spawns a networked vehicle on your current coords + // local spawnedVehicle = VEHICLE.CREATE_VEHICLE(ModelHash, myCoords.x, myCoords.y, myCoords.z, ENTITY.GET_ENTITY_HEADING(myPed), true, false) + // -- removes model from game memory as we no longer need it + // STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(ModelHash) + // -- sleep for 2s + // script:sleep(2000) + // ENTITY.DELETE_ENTITY(spawnedVehicle) + // end) + // ``` static void register_looped(const std::string& name, sol::function func, sol::this_state state) { auto module = sol::state_view(state)["!this"].get(); @@ -24,7 +74,8 @@ namespace lua::script [func] { while (big::g_running) { - auto res = func(); + auto res = func(dummy_script_util); + if (!res.valid()) big::g_lua_manager->handle_error(res, res.lua_state()); @@ -37,42 +88,51 @@ namespace lua::script // Lua API: Function // Table: script // Name: run_in_fiber - // Param: func: function: function that will be executed once in the fiber pool, you can call natives inside it. - // Executes a function inside the fiber pool, you can call natives inside it. + // Param: func: function: function that will be executed once in the fiber pool. + // Executes a function once inside the fiber pool, you can call natives inside it and yield or sleep. + // **Exemple Usage:** + // ```lua + // script.run_in_fiber(function (script) + // -- sleep until next game frame + // script:yield() + // + // local ModelHash = joaat("adder") + // if not STREAMING.IS_MODEL_IN_CDIMAGE(ModelHash) then return end + // STREAMING.REQUEST_MODEL(ModelHash) -- Request the model + // while not STREAMING.HAS_MODEL_LOADED(ModelHash) do -- Waits for the model to load + // script:yield() + // end + // local myPed = PLAYER.PLAYER_PED_ID() + // local myCoords = ENTITY.GET_ENTITY_COORDS(myPed, true) + // -- Spawns a networked vehicle on your current coords + // local spawnedVehicle = VEHICLE.CREATE_VEHICLE(ModelHash, myCoords.x, myCoords.y, myCoords.z, ENTITY.GET_ENTITY_HEADING(myPed), true, false) + // -- removes model from game memory as we no longer need it + // STREAMING.SET_MODEL_AS_NO_LONGER_NEEDED(ModelHash) + // -- sleep for 2s + // script:sleep(2000) + // ENTITY.DELETE_ENTITY(spawnedVehicle) + // end) + // ``` static void run_in_fiber(sol::function func) { big::g_fiber_pool->queue_job([func] { - auto res = func(); + auto res = func(dummy_script_util); + if (!res.valid()) big::g_lua_manager->handle_error(res, res.lua_state()); }); } - // Lua API: Function - // Table: script - // Name: yield - // Yield execution. - static void yield() - { - big::script::get_current()->yield(); - } - - // Lua API: Function - // Table: script - // Name: sleep - // Param: ms: integer: The amount of time in milliseconds that we will sleep for. - // Sleep for the given amount of time, time is in milliseconds. - static void sleep(int ms) - { - big::script::get_current()->yield(std::chrono::milliseconds(ms)); - } - static void bind(sol::state& state) { auto ns = state["script"].get_or_create(); ns["register_looped"] = register_looped; ns["run_in_fiber"] = run_in_fiber; - ns["yield"] = yield; - ns["sleep"] = sleep; + + //clang-format off + state.new_usertype("script_util", + "yield", &script_util::yield, + "sleep", &script_util::sleep); + //clang-format on } } \ No newline at end of file diff --git a/src/lua/lua_manager.cpp b/src/lua/lua_manager.cpp index 2bbbbe88..d430aae3 100644 --- a/src/lua/lua_manager.cpp +++ b/src/lua/lua_manager.cpp @@ -4,16 +4,17 @@ namespace big { - lua_manager::lua_manager() + lua_manager::lua_manager(folder scripts_folder) : + m_scripts_folder(scripts_folder) { m_schedule_reload_modules = false; m_wake_time_changed_scripts_check = std::chrono::high_resolution_clock::now() + m_delay_between_changed_scripts_check; - load_all_modules(); - g_lua_manager = this; + + load_all_modules(); } lua_manager::~lua_manager() @@ -70,7 +71,7 @@ namespace big if (m_wake_time_changed_scripts_check <= std::chrono::high_resolution_clock::now()) { - for (const auto& entry : std::filesystem::directory_iterator(g_file_manager->get_project_folder("scripts").get_path())) + for (const auto& entry : std::filesystem::directory_iterator(m_scripts_folder.get_path())) { if (entry.is_regular_file()) { @@ -134,7 +135,7 @@ namespace big void lua_manager::load_all_modules() { - for (const auto& entry : std::filesystem::directory_iterator(g_file_manager->get_project_folder("scripts").get_path())) + for (const auto& entry : std::filesystem::directory_iterator(m_scripts_folder.get_path())) if (entry.is_regular_file()) load_module(entry.path().filename().string()); } diff --git a/src/lua/lua_manager.hpp b/src/lua/lua_manager.hpp index 78221b50..57b83379 100644 --- a/src/lua/lua_manager.hpp +++ b/src/lua/lua_manager.hpp @@ -20,11 +20,13 @@ namespace big static constexpr std::chrono::seconds m_delay_between_changed_scripts_check = 3s; std::chrono::high_resolution_clock::time_point m_wake_time_changed_scripts_check; + folder m_scripts_folder; + public: bool m_schedule_reload_modules; public: - lua_manager(); + lua_manager(folder scripts_folder); ~lua_manager(); void load_all_modules(); @@ -35,6 +37,11 @@ namespace big return m_modules.size(); } + inline const folder& get_scripts_folder() const + { + return m_scripts_folder; + } + void draw_gui(rage::joaat_t tab_hash); void unload_module(rage::joaat_t module_id); diff --git a/src/lua/lua_module.cpp b/src/lua/lua_module.cpp index 7a9ae4a2..44704d38 100644 --- a/src/lua/lua_module.cpp +++ b/src/lua/lua_module.cpp @@ -51,7 +51,7 @@ namespace big { m_state.open_libraries(); - const auto scripts_folder = g_file_manager->get_project_folder("scripts"); + const auto& scripts_folder = g_lua_manager->get_scripts_folder(); add_folder_to_require_available_paths(scripts_folder); diff --git a/src/main.cpp b/src/main.cpp index efa2d7b8..a4e9d044 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -136,7 +136,7 @@ BOOL APIENTRY DllMain(HMODULE hmod, DWORD reason, PVOID) auto native_hooks_instance = std::make_unique(); LOG(INFO) << "Dynamic native hooker initialized."; - auto lua_manager_instance = std::make_unique(); + auto lua_manager_instance = std::make_unique(g_file_manager->get_project_folder("scripts")); LOG(INFO) << "Lua manager initialized."; g_running = true; diff --git a/src/views/settings/view_lua_scripts.cpp b/src/views/settings/view_lua_scripts.cpp index c3da27fa..fb73629d 100644 --- a/src/views/settings/view_lua_scripts.cpp +++ b/src/views/settings/view_lua_scripts.cpp @@ -53,7 +53,14 @@ namespace big { g_lua_manager->m_schedule_reload_modules = true; } - + ImGui::SameLine(); ImGui::Checkbox("Auto Reload Changed Scripts", &g.lua.enable_auto_reload_changed_scripts); + + if (components::button("Open Lua Scripts Folder")) + { + std::string command = "explorer.exe /select," + g_lua_manager->get_scripts_folder().get_path().string(); + + std::system(command.c_str()); + } } }