From e7ddb5fcf1559d3a8b2570ea85326952be039d30 Mon Sep 17 00:00:00 2001 From: Rohit Lalwani Date: Mon, 9 Jun 2025 01:27:15 +0530 Subject: [PATCH] Features in esp, teleport, world (#384) * Refactor Entity::Kill to use shooting mechanism The `Kill` method in the `Entity` class has been updated to remove the previous health-setting logic. Instead of setting the entity's health to zero or triggering a weapon damage event, it now retrieves the current weapon hash and uses the `MISC::SHOOT_SINGLE_BULLET_BETWEEN_COORDS` function to simulate a shooting action around the entity's position. * Enhance ESP functionality and object handling - Added checks for entity validity in Noclip.cpp and ESP.cpp. - Introduced m_objectNames map for better object name display. - Implemented DrawObject function for object rendering in ESP. - Created Object ESP settings group in Settings.cpp. - Refactored relationship checking logic in Ped.cpp for clarity. - Updated weapon firing coordinate calculations in Entity.cpp. * fix noclip. add delete cctv camera option. add esp option for cctv camera and gcache along with generic. added helper method to find if object is camera or gcache. * add back esp draw ped fix. add cctv missing hash and option to show signal jammer collectible. * support for teleport to objective. add option to draw signal jammer collection. * revert some changes not required. CR feedback changes. * redundant check. using just valid method. * rename to camera. * updated missing ref. * change color to green * tp to arcade option. computer screens options. move run script into method. minor esp changes for objects. dont kill specific enemies in kill option. additional hash check for camera. * feedback changes --- src/game/features/teleport/TpToObjective.cpp | 41 ++++++++ src/game/features/world/Computer.cpp | 99 ++++++++++++++++++++ src/game/features/world/Delete.cpp | 16 ++++ src/game/features/world/Kill.cpp | 8 +- src/game/frontend/ESP.cpp | 90 +++++++++++++++++- src/game/frontend/ESP.hpp | 8 ++ src/game/frontend/submenus/Debug/Scripts.cpp | 45 +-------- src/game/frontend/submenus/Settings.cpp | 7 ++ src/game/frontend/submenus/Teleport.cpp | 1 + src/game/frontend/submenus/World.cpp | 15 ++- src/game/gta/Object.cpp | 68 ++++++++++++++ src/game/gta/Object.hpp | 3 + src/game/gta/Ped.cpp | 11 ++- src/game/gta/Scripts.cpp | 51 ++++++++++ src/game/gta/Scripts.hpp | 1 + 15 files changed, 412 insertions(+), 52 deletions(-) create mode 100644 src/game/features/teleport/TpToObjective.cpp create mode 100644 src/game/features/world/Computer.cpp diff --git a/src/game/features/teleport/TpToObjective.cpp b/src/game/features/teleport/TpToObjective.cpp new file mode 100644 index 0000000..f8633fe --- /dev/null +++ b/src/game/features/teleport/TpToObjective.cpp @@ -0,0 +1,41 @@ +#include "core/commands/Command.hpp" +#include "core/frontend/Notifications.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Natives.hpp" + +namespace YimMenu::Features +{ + bool GetBlipLocationOfType(Vector3& location, int sprite) + { + Blip blip = HUD::GET_CLOSEST_BLIP_INFO_ID(sprite); + if (blip) + { + location = HUD::GET_BLIP_COORDS(blip); + location.z += 1.0f; + return true; + } + return false; + } + + class TpToObjective : public Command + { + using Command::Command; + + + virtual void OnCall() override + { + static const auto sprites = {1, 0, 2, 38, 143, 144, 145, 146, 161, 478, 501, 514, 521, 535, 536, 537, 538, 539, 540, 541, 542, 549, 556, 568, 615, 761, 762, 763, 764, 765, 780, 817, 842, 844, 845, 850}; + Vector3 location; + for (const auto sprite : sprites) + { + if (GetBlipLocationOfType(location, sprite)) + { + Self::GetPed().TeleportTo(location); + return; + } + } + } + }; + + static TpToObjective _TpToObjective{"tptoobjective", "Teleport to Objective", "Teleports you to the Objective"}; +} diff --git a/src/game/features/world/Computer.cpp b/src/game/features/world/Computer.cpp new file mode 100644 index 0000000..4162143 --- /dev/null +++ b/src/game/features/world/Computer.cpp @@ -0,0 +1,99 @@ +#include "../../gta/Scripts.hpp" +#include "core/backend/FiberPool.hpp" +#include "core/commands/Command.hpp" +#include "game/gta/Scripts.hpp" + +namespace YimMenu::Features +{ + class OpenMCT : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("apparcadebusinesshub", 1424); + }); + } + }; + + class OpenTerrorByte : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("apphackertruck", 4592); + }); + } + }; + + class OpenAvengerOperations : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("appavengeroperations", 4592); + }); + } + }; + + class OpenContracts : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("appfixersecurity", 4592); + }); + } + }; + + class OpenNightclub : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("appbusinesshub", 4592); + }); + } + }; + + class OpenBunker : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("appbunkerbusiness", 1424); + }); + } + }; + + class OpenHangar : public Command + { + using Command::Command; + + virtual void OnCall() override + { + FiberPool::Push([] { + Scripts::RunScript("appsmuggler", 4592); + }); + } + }; + + static OpenMCT _OpenMCT{"openmct", "Open Master Control Terminal", "Opens Master Control Terminal"}; + static OpenTerrorByte _OpenTerrorByte{"openterrorbyte", "Open Terrorbyte", "Opens Terrorbyte Computer"}; + static OpenAvengerOperations _OpenAvengerOperations{"openavengeroperations", "Open Avenger Operations", "Opens Avenger Operations Computer"}; + static OpenContracts _OpenContracts{"opencontracts", "Open Franklin Contracts", "Opens Franklins Contracts Computer"}; + static OpenNightclub _OpenNightclub{"opennightclub", "Open Nightclub", "Opens Nightclub Computer"}; + static OpenBunker _OpenBunker{"openbunker", "Open Bunker", "Opens Bunker Computer"}; + static OpenHangar _OpenHangar{"openhangar", "Open Hangar", "Opens Hangar Computer"}; +} \ No newline at end of file diff --git a/src/game/features/world/Delete.cpp b/src/game/features/world/Delete.cpp index a649f25..e69bbe1 100644 --- a/src/game/features/world/Delete.cpp +++ b/src/game/features/world/Delete.cpp @@ -1,5 +1,6 @@ #include "core/commands/Command.hpp" #include "game/gta/Pools.hpp" +#include "game/gta/Object.hpp" namespace YimMenu::Features { @@ -17,6 +18,20 @@ namespace YimMenu::Features } }; + class DeleteAllCameras : public Command + { + using Command::Command; + + virtual void OnCall() override + { + for (auto obj : Pools::GetObjects()) + { + if (obj && Object::IsCamera(obj.GetModel())) + obj.Delete(); + } + } + }; + class DeleteAllPeds : public Command { using Command::Command; @@ -44,6 +59,7 @@ namespace YimMenu::Features } }; + static DeleteAllCameras _DeleteAllCameras("delcams", "Delete All Camera", "Deletes all Camera cameras in the game world, including mission critical Camera"); static DeleteAllObjects _DeleteAllObjects{"delobjs", "Delete All Objects", "Deletes all objects in the game world, including mission critical objects"}; static DeleteAllPeds _DeleteAllPeds{"delpeds", "Delete All Peds", "Deletes all peds in the game world, including mission critical peds"}; static DeleteAllVehs _DeleteAllVehs{"delvehs", "Delete All Vehicles", "Deletes all vehicles in the game world, including mission critical vehicles"}; diff --git a/src/game/features/world/Kill.cpp b/src/game/features/world/Kill.cpp index e5e2003..58c605e 100644 --- a/src/game/features/world/Kill.cpp +++ b/src/game/features/world/Kill.cpp @@ -23,9 +23,15 @@ namespace YimMenu::Features virtual void OnCall() override { + const std::unordered_set enemiesNotToKill = { + 600300561, + 658984954, + 3678516463 + }; + for (auto ped : Pools::GetPeds()) { - if (!ped.IsPlayer() && ped.IsEnemy()) + if (!ped.IsPlayer() && ped.IsEnemy() && !enemiesNotToKill.contains(ped.GetModel())) ped.Kill(); } } diff --git a/src/game/frontend/ESP.cpp b/src/game/frontend/ESP.cpp index 321697b..31e3d09 100644 --- a/src/game/frontend/ESP.cpp +++ b/src/game/frontend/ESP.cpp @@ -1,5 +1,5 @@ #include "ESP.hpp" - +#include "game/gta/Object.hpp" #include "common.hpp" #include "core/commands/BoolCommand.hpp" #include "core/commands/ColorCommand.hpp" @@ -65,6 +65,12 @@ namespace YimMenu::Features // Random Events BoolCommand _ESPDrawRandomEvents("esprandomevents", "Random Events ESP", "Should the ESP draw Random Events?"); + + // objects + BoolCommand _ESPDrawObjects("espdrawobjects", "Show Object Model", "Should the ESP draw objects model?"); + BoolCommand _ESPDrawCameras("espdrawcameras", "Show Cameras", "Should the ESP draw Camera cameras?"); + BoolCommand _ESPDrawCache("espdrawcache", "Show G's Cache", "Should the ESP draw G's Cache?"); + BoolCommand _ESPDrawSignalJammers("espdrawsignaljammers", "Show Signal Jammers", "Should the ESP draw Signal Jammers?"); } namespace YimMenu @@ -95,6 +101,8 @@ namespace YimMenu void DrawSkeleton(Ped ped, ImDrawList* drawList, ImColor color) { + if (!ped.IsValid()) + return; drawList->AddLine(worldToScreen(ped.GetBonePosition(headBone)), worldToScreen(ped.GetBonePosition(neckBone)), color, 1.5f); drawList->AddLine(worldToScreen(ped.GetBonePosition(neckBone)), worldToScreen(ped.GetBonePosition(leftShoulderBone)), color, 1.5f); @@ -269,6 +277,52 @@ namespace YimMenu } } + void ESP::DrawObject(Entity object, ImDrawList* drawList, ObjectType objectType) + { + if (HUD::IS_PAUSE_MENU_ACTIVE() || NETWORK::NETWORK_IS_IN_MP_CUTSCENE()) + return; + + if (!object.IsValid()) + return; + + int objectHash = object.GetModel(); + + if (objectType == Camera && !Object::IsCamera(objectHash)) + return; + + if (objectType == Cache && !Object::IsCache(objectHash)) + return; + + if (objectType == SignalJammer && !Object::IsSignalJammer(objectHash)) + return; + + Vector3 coords = object.GetPosition(); + float distance = Self::GetPed().GetPosition().GetDistance(coords); + float formattedDistance = (distance < 1000.0f) ? distance : (distance / 1000.0f); + ImColor color = Green; + std::string unit = (distance < 1000.0f) ? "m" : "km"; + std::string objectName = std::to_string(objectHash); + if (Object::IsCamera(objectHash)) + { + objectName += " (Camera)"; + } + else if (Object::IsCache(objectHash)) + { + objectName += " (G's Cache)"; + } + else if (Object::IsSignalJammer(objectHash)) + { + objectName += " (Signal Jammer)"; + } + else if (object.IsMissionEntity()) + { + objectName += " (Mission Object)"; + } + std::string text = std::format("{}\n{:.2f}{} ", objectName, formattedDistance, unit); + + drawList->AddText({worldToScreen(coords).x, worldToScreen(coords).y}, color, text.c_str()); + } + void ESP::Draw() { if (!NativeInvoker::AreHandlersCached() || CAM::IS_SCREEN_FADED_OUT() || HUD::IS_WARNING_MESSAGE_ACTIVE()) @@ -287,7 +341,7 @@ namespace YimMenu { for (Ped ped : Pools::GetPeds()) { - if (ped.GetPointer()) + if (ped && ped.GetPointer()) DrawPed(ped, drawList); } } @@ -298,6 +352,38 @@ namespace YimMenu DrawRandomEvent(event, drawList); } } + if (Features::_ESPDrawObjects.GetState()) + { + for (auto obj : Pools::GetObjects()) + { + if (obj) + DrawObject(obj, drawList); + } + } + if (Features::_ESPDrawCameras.GetState()) + { + for (auto obj : Pools::GetObjects()) + { + if (obj && Object::IsCamera(obj.GetModel())) + DrawObject(obj, drawList, Camera); + } + } + if (Features::_ESPDrawCache.GetState()) + { + for (auto obj : Pools::GetObjects()) + { + if (obj && Object::IsCache(obj.GetModel())) + DrawObject(obj, drawList, Cache); + } + } + if (Features::_ESPDrawSignalJammers.GetState()) + { + for (auto obj : Pools::GetObjects()) + { + if (obj && Object::IsSignalJammer(obj.GetModel())) + DrawObject(obj, drawList, SignalJammer); + } + } } } diff --git a/src/game/frontend/ESP.hpp b/src/game/frontend/ESP.hpp index 823cadb..e2a4b58 100644 --- a/src/game/frontend/ESP.hpp +++ b/src/game/frontend/ESP.hpp @@ -3,6 +3,13 @@ namespace YimMenu { + enum ObjectType + { + Generic, + Camera, + Cache, + SignalJammer + }; class ESP { public: @@ -10,5 +17,6 @@ namespace YimMenu static void DrawPlayer(Player plyr, ImDrawList* draw_list); static void DrawPed(Ped plyr, ImDrawList* drawList); static void DrawRandomEvent(int event, ImDrawList* drawList); + static void DrawObject(Entity object, ImDrawList* drawList, ObjectType objectType = Generic); }; } \ 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 4b44860..c3433d7 100644 --- a/src/game/frontend/submenus/Debug/Scripts.cpp +++ b/src/game/frontend/submenus/Debug/Scripts.cpp @@ -329,50 +329,7 @@ namespace YimMenu::Submenus if (ImGui::Button("Start Script")) { FiberPool::Push([] { - auto hash = Joaat(scriptName); - - if (!SCRIPT::DOES_SCRIPT_WITH_NAME_HASH_EXIST(hash)) - { - Notifications::Show("Start Script", "Script does not exist.", NotificationType::Error); - return; - } - - if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(hash) > 0) - { - Notifications::Show("Start Script", "Script is already running.", NotificationType::Error); - return; - } - - if (MISC::GET_NUMBER_OF_FREE_STACKS_OF_THIS_SIZE(stackSize) == 0) - { - Notifications::Show("Start Script", "No free stack.", NotificationType::Error); - return; - } - - while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(hash)) - { - SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(hash); - ScriptMgr::Yield(); - } - - int id = 0; - if (args && argCount > 0) - { - id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS(hash, args, argCount, stackSize); - } - else - { - id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH(hash, stackSize); - } - - if (pauseAfterStarting) - { - if (auto thread = Scripts::FindScriptThreadByID(id)) - thread->m_Context.m_State = rage::scrThread::State::PAUSED; - } - - SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(hash); - Notifications::Show("Start Script", std::format("Started script with ID {}.", id), NotificationType::Success); + Scripts::RunScript(scriptName, stackSize, args, argCount, pauseAfterStarting); }); } })); diff --git a/src/game/frontend/submenus/Settings.cpp b/src/game/frontend/submenus/Settings.cpp index ede1276..eba4ac1 100644 --- a/src/game/frontend/submenus/Settings.cpp +++ b/src/game/frontend/submenus/Settings.cpp @@ -38,6 +38,7 @@ namespace YimMenu::Submenus auto gui = std::make_shared("GUI"); auto playerEsp = std::make_shared("Player ESP", 10); auto pedEsp = std::make_shared("Ped ESP", 10); + auto objectEsp = std::make_shared("Object ESP"); auto overlay = std::make_shared("Overlay"); auto chat = std::make_shared("Chat"); @@ -72,6 +73,11 @@ namespace YimMenu::Submenus pedEsp->AddItem(std::make_shared("espdrawpeds"_J, std::make_shared("espskeletonpeds"_J, "Ped Skeleton"))); pedEsp->AddItem(std::make_shared("espdrawpeds"_J, std::make_shared("skeletoncolorpeds"_J))); + objectEsp->AddItem(std::make_shared("espdrawobjects"_J)); + objectEsp->AddItem(std::make_shared("espdrawcameras"_J)); + objectEsp->AddItem(std::make_shared("espdrawcache"_J)); + objectEsp->AddItem(std::make_shared("espdrawsignaljammers"_J)); + overlay->AddItem(std::make_shared("overlay"_J)); overlay->AddItem(std::make_shared("overlay"_J, std::make_shared("overlayfps"_J))); @@ -79,6 +85,7 @@ namespace YimMenu::Submenus gui->AddItem(playerEsp); gui->AddItem(pedEsp); + gui->AddItem(objectEsp); gui->AddItem(overlay); gui->AddItem(chat); diff --git a/src/game/frontend/submenus/Teleport.cpp b/src/game/frontend/submenus/Teleport.cpp index c7b62ee..49d96d0 100644 --- a/src/game/frontend/submenus/Teleport.cpp +++ b/src/game/frontend/submenus/Teleport.cpp @@ -177,6 +177,7 @@ namespace YimMenu::Submenus // miscGroup->AddItem(std::make_shared("tptotraintrack"_J)); // miscGroup->AddItem(std::make_shared("tptomoonshineshack"_J)); // miscGroup->AddItem(std::make_shared("tptonazar"_J)); + miscGroup->AddItem(std::make_shared("tptoobjective"_J)); main->AddItem(miscGroup); diff --git a/src/game/frontend/submenus/World.cpp b/src/game/frontend/submenus/World.cpp index fe93c78..1b5069c 100644 --- a/src/game/frontend/submenus/World.cpp +++ b/src/game/frontend/submenus/World.cpp @@ -9,14 +9,16 @@ namespace YimMenu::Submenus auto main = std::make_shared("Main"); auto spawnersGroup = std::make_shared("Spawners"); auto iplsGroup = std::make_shared("IPLs"); - + auto computersGroup = std::make_shared("Computer"); + auto killPeds = std::make_shared("Kill", 1); killPeds->AddItem(std::make_shared("killallpeds"_J)); killPeds->AddItem(std::make_shared("killallenemies"_J)); - auto deleteOpts = std::make_shared("Delete", 1); + auto deleteOpts = std::make_shared("Delete", 2); deleteOpts->AddItem(std::make_shared("delpeds"_J)); deleteOpts->AddItem(std::make_shared("delvehs"_J)); deleteOpts->AddItem(std::make_shared("delobjs"_J)); + deleteOpts->AddItem(std::make_shared("delcams"_J)); auto bringOpts = std::make_shared("Bring", 1); bringOpts->AddItem(std::make_shared("bringpeds"_J)); bringOpts->AddItem(std::make_shared("bringvehs"_J)); @@ -69,8 +71,17 @@ namespace YimMenu::Submenus iplsGroup->AddItem(std::make_shared("unloadipl"_J)); iplsGroup->AddItem(std::make_shared("ipltp"_J)); + computersGroup->AddItem(std::make_shared("openmct"_J)); + computersGroup->AddItem(std::make_shared("openterrorbyte"_J)); + computersGroup->AddItem(std::make_shared("openavengeroperations"_J)); + computersGroup->AddItem(std::make_shared("opencontracts"_J)); + computersGroup->AddItem(std::make_shared("opennightclub"_J)); + computersGroup->AddItem(std::make_shared("openbunker"_J)); + computersGroup->AddItem(std::make_shared("openhangar"_J)); + AddCategory(std::move(main)); AddCategory(std::move(spawnersGroup)); AddCategory(std::move(iplsGroup)); + AddCategory(std::move(computersGroup)); } }; \ No newline at end of file diff --git a/src/game/gta/Object.cpp b/src/game/gta/Object.cpp index 6770a29..e306c27 100644 --- a/src/game/gta/Object.cpp +++ b/src/game/gta/Object.cpp @@ -2,9 +2,61 @@ #include "Natives.hpp" #include "core/backend/ScriptMgr.hpp" #include "game/pointers/Pointers.hpp" +#include "core/util/Joaat.hpp" + namespace YimMenu { + static std::unordered_set cameraHashes = { + Joaat("p_cctv_s"), + Joaat("prop_cctv_cam_01a"), + Joaat("prop_cctv_cam_01b"), + Joaat("prop_cctv_cam_02a"), + Joaat("prop_cctv_cam_03a"), + Joaat("prop_cctv_cam_04a"), + Joaat("prop_cctv_cam_04b"), + Joaat("prop_cctv_cam_04c"), + Joaat("prop_cctv_cam_05a"), + Joaat("prop_cctv_cam_06a"), + Joaat("prop_cctv_cam_07a"), + Joaat("prop_cs_cctv"), + Joaat("hei_prop_bank_cctv_01"), + Joaat("hei_prop_bank_cctv_02"), + Joaat("ch_prop_ch_cctv_cam_02a"), + Joaat("xm_prop_x17_server_farm_cctv_01"), + }; + + static std::unordered_set cameraHashesInt = { + -1007354661, + -1842407088, + 289451089, + 548760764, + -354221800, + -1159421424, + 1449155105, + -1095296451, + 1919058329, + -1884701657, + -173206916, + 168901740, + -1340405475, + 1927491455, + 299608302, + -6978462, + 2135655372, + -1233322078, + -247409812, + }; + + static std::unordered_set cacheHashes = { + 528555233, + -1620734287, + 138777325, + 765087784, + 188023466, + -413608921, + }; + Object Object::Create(uint32_t model, rage::fvector3 coords) { ENTITY_ASSERT_SCRIPT_CONTEXT(); @@ -48,4 +100,20 @@ namespace YimMenu return obj; } + + bool Object::IsCamera(int objectHash) + { + return cameraHashes.contains(objectHash) + || cameraHashesInt.contains(objectHash); + } + + bool Object::IsCache(int objectHash) + { + return cacheHashes.contains(objectHash); + } + + bool Object::IsSignalJammer(int objectHash) + { + return objectHash == -305186631; + } } \ No newline at end of file diff --git a/src/game/gta/Object.hpp b/src/game/gta/Object.hpp index 433a5e3..8255b64 100644 --- a/src/game/gta/Object.hpp +++ b/src/game/gta/Object.hpp @@ -9,5 +9,8 @@ namespace YimMenu using Entity::Entity; static Object Create(uint32_t model, rage::fvector3 coords); + static bool IsCamera(int objectHash); + static bool IsCache(int objectHash); + static bool IsSignalJammer(int objectHash); }; } \ No newline at end of file diff --git a/src/game/gta/Ped.cpp b/src/game/gta/Ped.cpp index ed3562e..25fcd25 100644 --- a/src/game/gta/Ped.cpp +++ b/src/game/gta/Ped.cpp @@ -124,9 +124,14 @@ namespace YimMenu auto r1 = PED::GET_RELATIONSHIP_BETWEEN_PEDS(GetHandle(), PLAYER::PLAYER_PED_ID()); auto r2 = PED::GET_RELATIONSHIP_BETWEEN_PEDS(PLAYER::PLAYER_PED_ID(), GetHandle()); auto r3 = PED::IS_PED_IN_COMBAT(GetHandle(), PLAYER::PLAYER_PED_ID()) ? 5 : 0; - auto rel = std::max({r1, r2, r3}); - - return rel == 3 || rel == 4 || rel == 5; + + if (r1 == 3 || r2 == 3) + return true; + if (r1 == 4 || r2 == 4) + return true; + if (r1 == 5 || r2 == 5 || r3 == 5) + return true; + return false; } int Ped::GetAccuracy() diff --git a/src/game/gta/Scripts.cpp b/src/game/gta/Scripts.cpp index 241a430..e5fbc9b 100644 --- a/src/game/gta/Scripts.cpp +++ b/src/game/gta/Scripts.cpp @@ -14,6 +14,9 @@ #include "game/backend/Players.hpp" #include "game/backend/Self.hpp" #include "core/memory/Pattern.hpp" +#include "game/gta/Natives.hpp" +#include "core/frontend/Notifications.hpp" +#include "core/backend/ScriptMgr.hpp" namespace YimMenu::Scripts { @@ -187,4 +190,52 @@ namespace YimMenu::Scripts pkt.Send(player.second.GetMessageId()); } } + + void RunScript(std::string scriptName, int stackSize, std::int64_t* args, int argCount, bool pauseAfterStarting) + { + auto hash = Joaat(scriptName); + + if (!SCRIPT::DOES_SCRIPT_WITH_NAME_HASH_EXIST(hash)) + { + Notifications::Show("Start Script", "Script does not exist.", NotificationType::Error); + return; + } + + if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(hash) > 0) + { + Notifications::Show("Start Script", "Script is already running.", NotificationType::Error); + return; + } + + if (MISC::GET_NUMBER_OF_FREE_STACKS_OF_THIS_SIZE(stackSize) == 0) + { + Notifications::Show("Start Script", "No free stack.", NotificationType::Error); + return; + } + + while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(hash)) + { + SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(hash); + ScriptMgr::Yield(); + } + + int id = 0; + if (args && argCount > 0) + { + id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS(hash, args, argCount, stackSize); + } + else + { + id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH(hash, stackSize); + } + + if (pauseAfterStarting) + { + if (auto thread = Scripts::FindScriptThreadByID(id)) + thread->m_Context.m_State = rage::scrThread::State::PAUSED; + } + + SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(hash); + Notifications::Show("Start Script", std::format("Started script with ID {}.", id), NotificationType::Success); + } } \ No newline at end of file diff --git a/src/game/gta/Scripts.hpp b/src/game/gta/Scripts.hpp index 366c358..558909f 100644 --- a/src/game/gta/Scripts.hpp +++ b/src/game/gta/Scripts.hpp @@ -22,4 +22,5 @@ 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 void RunScript(std::string scriptName, int stackSize, std::int64_t* args = nullptr, int argCount = 0, bool pauseAfterStarting = false); } \ No newline at end of file