diff --git a/src/core/hooking/DetourHook.hpp b/src/core/hooking/DetourHook.hpp index 2b9af82..fa3820c 100644 --- a/src/core/hooking/DetourHook.hpp +++ b/src/core/hooking/DetourHook.hpp @@ -35,7 +35,7 @@ namespace YimMenu inline DetourHook::DetourHook(const std::string_view name, void* target, T detour) : BaseHook(name), m_TargetFunc(target), - m_DetourFunc(detour), + m_DetourFunc(reinterpret_cast(detour)), m_OriginalFunc(nullptr) { OptimizeHook(); diff --git a/src/core/hooking/Hooking.cpp b/src/core/hooking/Hooking.cpp index 8d966af..98001cd 100644 --- a/src/core/hooking/Hooking.cpp +++ b/src/core/hooking/Hooking.cpp @@ -17,6 +17,8 @@ namespace YimMenu BaseHook::Add(new DetourHook("ResizeBuffers", swapchain_vft[Hooks::SwapChain::VMTResizeBuffersIdx], Hooks::SwapChain::ResizeBuffers)); BaseHook::Add(new DetourHook("RunScriptThreads", Pointers.RunScriptThreads, Hooks::Script::RunScriptThreads)); + + BaseHook::Add(new DetourHook("AssignPhysicalIndex", Pointers.AssignPhysicalIndex, Hooks::Info::AssignPhysicalIndex)); } Hooking::~Hooking() diff --git a/src/core/hooking/Hooking.hpp b/src/core/hooking/Hooking.hpp index 4c30473..75e2ae5 100644 --- a/src/core/hooking/Hooking.hpp +++ b/src/core/hooking/Hooking.hpp @@ -30,6 +30,5 @@ namespace YimMenu static Hooking i{}; return i; } - }; } \ No newline at end of file diff --git a/src/core/logger/ExceptionHandler.cpp b/src/core/logger/ExceptionHandler.cpp index 4dd1c67..1fedeff 100644 --- a/src/core/logger/ExceptionHandler.cpp +++ b/src/core/logger/ExceptionHandler.cpp @@ -20,7 +20,7 @@ namespace YimMenu { LOG(INFO) << "ExceptionHandler initialized"; m_OldErrorMode = SetErrorMode(0); - m_Handler = SetUnhandledExceptionFilter(&VectoredExceptionHandler); + m_Handler = reinterpret_cast(SetUnhandledExceptionFilter(&VectoredExceptionHandler)); } ExceptionHandler::~ExceptionHandler() diff --git a/src/core/memory/Pattern.hpp b/src/core/memory/Pattern.hpp index 05f15dc..5047790 100644 --- a/src/core/memory/Pattern.hpp +++ b/src/core/memory/Pattern.hpp @@ -124,8 +124,9 @@ namespace YimMenu continue; } - - m_Signature[pos++] = static_cast(StrToHex(S.Get()[i]) * 0x10 + StrToHex(S.Get()[++i])); + int next = i + 1; + m_Signature[pos++] = static_cast(StrToHex(S.Get()[i]) * 0x10 + StrToHex(S.Get()[next])); + i++; } } diff --git a/src/core/util/Math.hpp b/src/core/util/Math.hpp new file mode 100644 index 0000000..8218058 --- /dev/null +++ b/src/core/util/Math.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "types/rage/vector.hpp" + +namespace YimMenu::Math +{ + inline float DegToRad(float deg) + { + double radian = (3.14159265359 / 180) * deg; + return static_cast(radian); + } + + inline rage::fvector3 RotationToDirection(rage::fvector3 rotation) + { + float x = DegToRad(rotation.x); + float z = DegToRad(rotation.z); + + float num = abs(cos(x)); + + return rage::fvector3{-sin(z) * num, cos(z) * num, sin(x)}; + } +} \ No newline at end of file diff --git a/src/game/backend/PlayerData.hpp b/src/game/backend/PlayerData.hpp new file mode 100644 index 0000000..db1fc7e --- /dev/null +++ b/src/game/backend/PlayerData.hpp @@ -0,0 +1,12 @@ +#pragma once +#include +#include + +namespace YimMenu +{ + class PlayerData + { + public: + // nothing yet? + }; +} \ No newline at end of file diff --git a/src/game/backend/Players.cpp b/src/game/backend/Players.cpp new file mode 100644 index 0000000..94278ff --- /dev/null +++ b/src/game/backend/Players.cpp @@ -0,0 +1,72 @@ +#include "Players.hpp" +#include "game/pointers/Pointers.hpp" +#include "types/network/CNetGamePlayer.hpp" +#include "types/network/rlGamerInfo.hpp" + + +namespace YimMenu +{ + Players::Players() + { + for (uint8_t idx = 0; idx < 32u; idx++) + { + if (const auto& netPlayer = Pointers.GetNetPlayerFromPid(idx); netPlayer && netPlayer->GetGamerInfo() && netPlayer->IsPhysical()) + { + OnPlayerJoin(netPlayer); + } + } + } + + void Players::OnPlayerJoinImpl(CNetGamePlayer* player) + { + auto new_player = Player(player); + + m_Players[player->m_PlayerIndex] = new_player; + m_PlayerDatas[player->m_PlayerIndex] = PlayerData(); + } + + void Players::OnPlayerLeaveImpl(CNetGamePlayer* player) + { + m_Players.erase(player->m_PlayerIndex); + m_PlayerDatas.erase(player->m_PlayerIndex); + } + + Player Players::GetByRIDImpl(uint64_t rid) + { + for (auto& [idx, player] : Players::GetPlayers()) + { + if (player.GetGamerInfo()->m_GamerHandle.m_RockstarId == rid) + { + return player; + } + } + + return nullptr; + } + + Player Players::GetByHostTokenImpl(uint64_t token) + { + for (auto& [idx, player] : Players::GetPlayers()) + { + if (player.GetGamerInfo()->m_HostToken == token) + { + return player; + } + } + + return nullptr; + } + + Player Players::GetByMessageIdImpl(int id) + { + for (auto& [idx, player] : Players::GetPlayers()) + { + if (player.GetHandle()->m_MessageId == id) + { + return player; + } + } + + return nullptr; + } +} \ No newline at end of file diff --git a/src/game/backend/Players.hpp b/src/game/backend/Players.hpp new file mode 100644 index 0000000..3b23d46 --- /dev/null +++ b/src/game/backend/Players.hpp @@ -0,0 +1,88 @@ +#pragma once +#include "PlayerData.hpp" +#include "game/gta/Player.hpp" + +namespace YimMenu +{ + class Players + { + std::unordered_map m_Players{}; + std::unordered_map m_PlayerDatas{}; + Player m_SelectedPlayer = Player((uint8_t)0); + + public: + static void OnPlayerJoin(CNetGamePlayer* player) + { + GetInstance().OnPlayerJoinImpl(player); + } + + static void OnPlayerLeave(CNetGamePlayer* player) + { + GetInstance().OnPlayerLeaveImpl(player); + } + + static Player GetSelected() + { + return GetInstance().m_SelectedPlayer; + } + + static void SetSelected(Player player) + { + GetInstance().m_SelectedPlayer = player; + } + + static std::unordered_map& GetPlayers() + { + return GetInstance().m_Players; + } + + static Player GetByRID(uint64_t rid) + { + return GetInstance().GetByRIDImpl(rid); + } + + static Player GetByHostToken(uint64_t token) + { + return GetInstance().GetByHostTokenImpl(token); + } + + static Player GetByMessageId(int id) + { + return GetInstance().GetByMessageIdImpl(id); + } + + static PlayerData& GetPlayerData(uint8_t idx) + { + return GetInstance().m_PlayerDatas[idx]; + } + + static Player GetRandom() + { + auto& players = GetPlayers(); + + if (players.empty()) + { + return Player((uint8_t)0); + } + + uint8_t random = static_cast(rand() % players.size()); + auto it = std::next(players.begin(), random); + return it->second; + } + + private: + Players(); + + static Players& GetInstance() + { + static Players Instance; + return Instance; + } + + void OnPlayerJoinImpl(CNetGamePlayer* player); + void OnPlayerLeaveImpl(CNetGamePlayer* player); + Player GetByRIDImpl(uint64_t rid); + Player GetByHostTokenImpl(uint64_t token); + Player GetByMessageIdImpl(int id); + }; +} \ No newline at end of file diff --git a/src/game/backend/Self.cpp b/src/game/backend/Self.cpp index 9a9c098..8c58a7d 100644 --- a/src/game/backend/Self.cpp +++ b/src/game/backend/Self.cpp @@ -3,12 +3,13 @@ #include "core/backend/ScriptMgr.hpp" #include "game/pointers/Pointers.hpp" #include "game/gta/Natives.hpp" +#include "types/ped/CPedFactory.hpp" namespace YimMenu { Self::Self() : m_SelfPed(nullptr), - // m_SelfPlayer(nullptr), + m_SelfPlayer(nullptr), m_Vehicle(nullptr) { } @@ -17,8 +18,11 @@ namespace YimMenu { while (g_Running) { - m_SelfPed = Ped(/*Pointers.GetLocalPed()*/ nullptr, PLAYER::PLAYER_PED_ID()); - // m_SelfPlayer = Player(PLAYER::PLAYER_ID()); + CPed* ped_ptr = nullptr; + if (auto factory = *Pointers.PedFactory) + ped_ptr = factory->m_LocalPed; + m_SelfPed = Ped(ped_ptr, PLAYER::PLAYER_PED_ID()); + m_SelfPlayer = Player(PLAYER::PLAYER_ID()); if (m_SelfPed.IsValid()) { m_Vehicle = m_SelfPed.GetVehicle(); diff --git a/src/game/backend/Self.hpp b/src/game/backend/Self.hpp index aad6741..7197abe 100644 --- a/src/game/backend/Self.hpp +++ b/src/game/backend/Self.hpp @@ -1,7 +1,7 @@ #pragma once #include "game/gta/Entity.hpp" #include "game/gta/Ped.hpp" -// #include "game/gta/Player.hpp" +#include "game/gta/Player.hpp" #include "game/gta/Vehicle.hpp" namespace YimMenu @@ -9,7 +9,7 @@ namespace YimMenu class Self { Ped m_SelfPed; - // Player m_SelfPlayer; + Player m_SelfPlayer; Vehicle m_Vehicle; public: @@ -18,12 +18,10 @@ namespace YimMenu return GetInstance().m_SelfPed; } - /* static Player GetPlayer() { return GetInstance().m_SelfPlayer; } - */ static Vehicle GetVehicle() { diff --git a/src/game/features/players/info/Spectate.cpp b/src/game/features/players/info/Spectate.cpp new file mode 100644 index 0000000..1dcdef3 --- /dev/null +++ b/src/game/features/players/info/Spectate.cpp @@ -0,0 +1,37 @@ +#include "core/commands/LoopedCommand.hpp" +#include "game/backend/Players.hpp" +#include "game/gta/Natives.hpp" + +namespace YimMenu::Features +{ + class Spectate : public LoopedCommand + { + using LoopedCommand::LoopedCommand; + + Player m_SpectatingPlayer{nullptr}; + + virtual void OnTick() override + { + auto selected = Players::GetSelected(); + if (selected != m_SpectatingPlayer) + { + NETWORK::NETWORK_SET_IN_SPECTATOR_MODE(false, 0); + HUD::SET_MINIMAP_IN_SPECTATOR_MODE(false, 0); + if (selected) + { + NETWORK::NETWORK_SET_IN_SPECTATOR_MODE(true, selected.GetPed().GetHandle()); + HUD::SET_MINIMAP_IN_SPECTATOR_MODE(true, selected.GetPed().GetHandle()); + } + m_SpectatingPlayer = selected; + } + } + + virtual void OnDisable() override + { + NETWORK::NETWORK_SET_IN_SPECTATOR_MODE(false, 0); + HUD::SET_MINIMAP_IN_SPECTATOR_MODE(false, 0); + } + }; + + static Spectate _Spectate{"spectate", "Spectate", "Spectates the selected player"}; +} \ No newline at end of file diff --git a/src/game/features/self/Freecam.cpp b/src/game/features/self/Freecam.cpp new file mode 100644 index 0000000..63dd4f1 --- /dev/null +++ b/src/game/features/self/Freecam.cpp @@ -0,0 +1,147 @@ +#include "core/commands/FloatCommand.hpp" +#include "core/commands/LoopedCommand.hpp" +#include "core/util/Math.hpp" +#include "game/backend/Self.hpp" +#include "game/frontend/GUI.hpp" +#include "game/gta/Natives.hpp" +#include "types/pad/ControllerInputs.hpp" + + +namespace YimMenu::Features +{ + static FloatCommand _FreecamSpeed{"freecamspeed", "Freecam Speed", "How fast the freecam will move positions", 0.01f, 10.0f, 0.10f}; + + class Freecam : public LoopedCommand + { + using LoopedCommand::LoopedCommand; + + static inline int camEntity = 0; + static inline Vector3 position{}; + static inline Vector3 rotation{}; + + void CreateFreecam() + { + if (camEntity) + return; + + camEntity = CAM::CREATE_CAM("DEFAULT_SCRIPTED_CAMERA", 0); + position = CAM::GET_GAMEPLAY_CAM_COORD(); + rotation = CAM::GET_GAMEPLAY_CAM_ROT(2); + + CAM::SET_CAM_COORD(camEntity, position.x, position.y, position.z); + CAM::SET_CAM_ROT(camEntity, rotation.x, rotation.y, rotation.z, 2); + CAM::SET_CAM_ACTIVE(camEntity, true); + CAM::RENDER_SCRIPT_CAMS(true, true, 500, true, true, 0); + } + + void UpdateFreecamPosition() + { + if (GUI::IsOpen()) + return; + Vector3 PosChange{}; + static float accel = 0.0f; + + // Left Shift + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (Hash)ControllerInputs::INPUT_SPRINT)) + { + PosChange.z += _FreecamSpeed.GetState() / 2; + } + // Left Control + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_DUCK) /* || PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_HORSE_STOP) */) + { + PosChange.z -= _FreecamSpeed.GetState() / 2; + } + // Forward + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (Hash)ControllerInputs::INPUT_MOVE_UP_ONLY)) + { + PosChange.y += _FreecamSpeed.GetState(); + } + // Backward + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (Hash)ControllerInputs::INPUT_MOVE_DOWN_ONLY)) + { + PosChange.y -= _FreecamSpeed.GetState(); + } + // Left + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (Hash)ControllerInputs::INPUT_MOVE_LEFT_ONLY)) + { + PosChange.x -= _FreecamSpeed.GetState(); + } + // Right + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (Hash)ControllerInputs::INPUT_MOVE_RIGHT_ONLY)) + { + PosChange.x += _FreecamSpeed.GetState(); + } + + + if (PosChange.x == 0.0f && PosChange.y == 0.0f && PosChange.z == 0.0f) + { + accel = 0.0f; + } + else if (accel < 10) + { + accel += 0.15f; + } + + Vector3 rot = CAM::GET_CAM_ROT(camEntity, 2); + float yaw = Math::DegToRad(rot.z); + + position.x += (PosChange.x * cos(yaw) - PosChange.y * sin(yaw)) * accel; + position.y += (PosChange.x * sin(yaw) + PosChange.y * cos(yaw)) * accel; + position.z += PosChange.z * accel; + + CAM::SET_CAM_COORD(camEntity, position.x, position.y, position.z); + STREAMING::SET_FOCUS_POS_AND_VEL(position.x, position.y, position.z, 0.0f, 0.0f, 0.0f); + } + + virtual void OnTick() override + { + CreateFreecam(); + UpdateFreecamPosition(); + + rotation = CAM::GET_GAMEPLAY_CAM_ROT(2); + CAM::SET_CAM_ROT(camEntity, rotation.x, rotation.y, rotation.z, 2); + + TASK::CLEAR_PED_TASKS(Self::GetPed().GetHandle()); + TASK::CLEAR_PED_SECONDARY_TASK(Self::GetPed().GetHandle()); + TASK::CLEAR_PED_TASKS_IMMEDIATELY(Self::GetPed().GetHandle()); + Self::GetPed().SetFrozen(true); + Self::GetPed().SetVisible(false); + + if (!GUI::IsOpen()) + { + static Hash controls[]{ + (Hash)ControllerInputs::INPUT_LOOK_LR, + (Hash)ControllerInputs::INPUT_LOOK_UD, + (Hash)ControllerInputs::INPUT_LOOK_UP_ONLY, + (Hash)ControllerInputs::INPUT_LOOK_DOWN_ONLY, + (Hash)ControllerInputs::INPUT_LOOK_LEFT_ONLY, + (Hash)ControllerInputs::INPUT_LOOK_RIGHT_ONLY, + }; + PAD::DISABLE_ALL_CONTROL_ACTIONS(0); + + for (Hash c : controls) + { + PAD::ENABLE_CONTROL_ACTION(0, c, true); + } + } + } + + virtual void OnDisable() override + { + if (!camEntity) + return; + + CAM::SET_CAM_ACTIVE(camEntity, false); + CAM::RENDER_SCRIPT_CAMS(false, true, 500, true, true, 0); + CAM::DESTROY_CAM(camEntity, false); + STREAMING::CLEAR_FOCUS(); + + Self::GetPed().SetFrozen(false); + Self::GetPed().SetVisible(true); + + camEntity = 0; + } + }; + + static Freecam _Freecam{"freecam", "Freecam", "Detaches your camera and allows you to go anywhere!"}; +} \ No newline at end of file diff --git a/src/game/features/self/InfiniteAmmo.cpp b/src/game/features/self/InfiniteAmmo.cpp index cb58823..5ceca04 100644 --- a/src/game/features/self/InfiniteAmmo.cpp +++ b/src/game/features/self/InfiniteAmmo.cpp @@ -1,6 +1,5 @@ #include "core/commands/LoopedCommand.hpp" #include "game/backend/Self.hpp" -#include "game/gta/Natives.hpp" namespace YimMenu::Features { @@ -11,13 +10,13 @@ namespace YimMenu::Features virtual void OnTick() override { if (Self::GetPed()) - WEAPON::SET_PED_INFINITE_AMMO(Self::GetPed().GetHandle(), true, 0); + Self::GetPed().SetInfiniteAmmo(true); } virtual void OnDisable() override { if (Self::GetPed()) - WEAPON::SET_PED_INFINITE_AMMO(Self::GetPed().GetHandle(), false, 0); + Self::GetPed().SetInfiniteAmmo(false); } }; diff --git a/src/game/features/self/InfiniteClip.cpp b/src/game/features/self/InfiniteClip.cpp index 4d79962..ad0eaa2 100644 --- a/src/game/features/self/InfiniteClip.cpp +++ b/src/game/features/self/InfiniteClip.cpp @@ -1,6 +1,5 @@ #include "core/commands/LoopedCommand.hpp" #include "game/backend/Self.hpp" -#include "game/gta/Natives.hpp" namespace YimMenu::Features { @@ -10,12 +9,14 @@ namespace YimMenu::Features virtual void OnTick() override { - WEAPON::SET_PED_INFINITE_AMMO_CLIP(Self::GetPed().GetHandle(), TRUE); + if (Self::GetPed()) + Self::GetPed().SetInfiniteClip(true); } virtual void OnDisable() override { - WEAPON::SET_PED_INFINITE_AMMO_CLIP(Self::GetPed().GetHandle(), FALSE); + if (Self::GetPed()) + Self::GetPed().SetInfiniteClip(false); } }; diff --git a/src/game/features/self/Invis.cpp b/src/game/features/self/Invis.cpp new file mode 100644 index 0000000..9df42a0 --- /dev/null +++ b/src/game/features/self/Invis.cpp @@ -0,0 +1,30 @@ +#include "core/commands/LoopedCommand.hpp" +#include "game/backend/Self.hpp" + +namespace YimMenu::Features +{ + class Invis : public LoopedCommand + { + using LoopedCommand::LoopedCommand; + + virtual void OnTick() override + { + if (Self::GetPed()) + { + Self::GetPed().SetVisible(false); + Self::GetPlayer().SetVisibleLocally(true); + } + } + + virtual void OnDisable() override + { + if (Self::GetPed()) + { + Self::GetPed().SetVisible(true); + Self::GetPlayer().SetVisibleLocally(false); + } + } + }; + + static Invis _Invis{"invis", "Invisibility", "Be invisible"}; +} \ No newline at end of file diff --git a/src/game/features/self/Noclip.cpp b/src/game/features/self/Noclip.cpp new file mode 100644 index 0000000..3841e3d --- /dev/null +++ b/src/game/features/self/Noclip.cpp @@ -0,0 +1,97 @@ +#include "core/commands/FloatCommand.hpp" +#include "core/commands/LoopedCommand.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Natives.hpp" +#include "types/pad/ControllerInputs.hpp" + +namespace YimMenu::Features +{ + static constexpr ControllerInputs controls[] = {ControllerInputs::INPUT_SPRINT, ControllerInputs::INPUT_MOVE_UP_ONLY, ControllerInputs::INPUT_MOVE_DOWN_ONLY, ControllerInputs::INPUT_MOVE_LEFT_ONLY, ControllerInputs::INPUT_MOVE_RIGHT_ONLY, ControllerInputs::INPUT_DUCK, ControllerInputs::INPUT_VEH_HORN}; + static FloatCommand _NoclipSpeed{"noclipspeed", "Noclip Speed", "Features", 0.1f, 2.0f, 0.14f}; + + class Noclip : public LoopedCommand + { + using LoopedCommand::LoopedCommand; + + Entity m_Entity{nullptr}; + float m_SpeedMultiplier; + + virtual void OnTick() override + { + for (const auto& control : controls) + PAD::DISABLE_CONTROL_ACTION(0, static_cast(control), true); + + Entity ent = Self::GetPed(); + if (auto veh = Self::GetVehicle()) + ent = veh; + + const auto location = ent.GetPosition(); + + // cleanup when changing entities + if (m_Entity != ent) + { + m_Entity.SetFrozen(false); + m_Entity.SetCollision(true); + + m_Entity = ent; + } + + rage::fvector3 vel{}; + + // Left Shift + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_SPRINT)) + vel.z += _NoclipSpeed.GetState() / 2; + // Left Control + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_DUCK) || PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_VEH_HORN)) + vel.z -= _NoclipSpeed.GetState() / 2; + // Forward + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_UP_ONLY)) + vel.y += _NoclipSpeed.GetState(); + // Backward + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_DOWN_ONLY)) + vel.y -= _NoclipSpeed.GetState(); + // Left + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_LEFT_ONLY)) + vel.x -= _NoclipSpeed.GetState(); + // Right + if (PAD::IS_DISABLED_CONTROL_PRESSED(0, (int)ControllerInputs::INPUT_MOVE_RIGHT_ONLY)) + vel.x += _NoclipSpeed.GetState(); + + auto rot = CAM::GET_GAMEPLAY_CAM_ROT(2); + ent.SetRotation({0.0f, rot.y, rot.z}); + ent.SetCollision(false); + + if (vel.x == 0.f && vel.y == 0.f && vel.z == 0.f) + { + // freeze entity to prevent drifting when standing still + ent.SetFrozen(true); + m_SpeedMultiplier = 0.f; + } + else + { + if (m_SpeedMultiplier < 20.f) + m_SpeedMultiplier += 0.07f; + + ent.SetFrozen(false); + + + { + const auto offset = ENTITY::GET_OFFSET_FROM_ENTITY_IN_WORLD_COORDS(ent.GetHandle(), vel.x * m_SpeedMultiplier, vel.y * m_SpeedMultiplier, vel.z * m_SpeedMultiplier); + ent.SetVelocity({}); + ent.SetPosition({offset.x, offset.y, offset.z}); + } + } + } + + virtual void OnDisable() override + { + if (m_Entity) + { + m_Entity.SetFrozen(false); + m_Entity.SetCollision(true); + } + } + }; + + static Noclip _NoClip{"noclip", "No Clip", "Allows you to fly through the map"}; +} \ No newline at end of file diff --git a/src/game/frontend/Menu.cpp b/src/game/frontend/Menu.cpp index 1246391..d362d77 100644 --- a/src/game/frontend/Menu.cpp +++ b/src/game/frontend/Menu.cpp @@ -8,6 +8,7 @@ #include "game/frontend/fonts/Fonts.hpp" #include "game/pointers/Pointers.hpp" #include "submenus/Self.hpp" +#include "submenus/Players.hpp" namespace YimMenu { @@ -15,6 +16,7 @@ namespace YimMenu { // Arguably the only place this file should be edited at for more menus UIManager::AddSubmenu(std::make_shared()); + UIManager::AddSubmenu(std::make_shared()); Renderer::AddRendererCallBack( [&] { diff --git a/src/game/frontend/submenus/Player/Info.cpp b/src/game/frontend/submenus/Player/Info.cpp new file mode 100644 index 0000000..1cec476 --- /dev/null +++ b/src/game/frontend/submenus/Player/Info.cpp @@ -0,0 +1,119 @@ +#include "Info.hpp" + +#include "core/frontend/Notifications.hpp" +#include "core/backend/FiberPool.hpp" +#include "game/backend/Players.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/Natives.hpp" +#include "types/network/CNetGamePlayer.hpp" +#include "types/network/rlGamerInfo.hpp" + +namespace YimMenu::Submenus +{ + static std::string BuildIPStr(int field1, int field2, int field3, int field4) + { + std::ostringstream oss; + oss << field1 << '.' << field2 << '.' << field3 << '.' << field4; + return oss.str(); + } + + std::shared_ptr BuildInfoMenu() + { + auto menu = std::make_shared("Info"); + + auto teleportGroup = std::make_shared("Teleport"); + auto playerOptionsGroup = std::make_shared("Info"); + + playerOptionsGroup->AddItem(std::make_shared([] { + if (Players::GetSelected().IsValid()) + ImGui::Text("%s", Players::GetSelected().GetName()); + })); + playerOptionsGroup->AddItem(std::make_shared("spectate"_J)); + playerOptionsGroup->AddItem(std::make_shared([] { + if (Players::GetSelected().IsValid()) + { + if (Players::GetSelected().GetPed()) + { + auto health = Players::GetSelected().GetPed().GetHealth(); + auto maxHealth = Players::GetSelected().GetPed().GetMaxHealth(); + std::string healthStr = std::format("HP: {}/{} ({:.2f}%)", health, maxHealth, (float)health / maxHealth * 100.0f); + ImGui::Text("%s", healthStr.c_str()); + + auto coords = Players::GetSelected().GetPed().GetPosition(); + ImGui::Text("Coords: %.2f, %.2f, %.2f", coords.x, coords.y, coords.z); + + auto distance = Players::GetSelected().GetPed().GetPosition().GetDistance(Self::GetPed().GetPosition()); + ImGui::Text("Distance: %.2f", distance); + } + else + { + ImGui::Text("Ped missing or deleted"); + } + + auto rid1 = Players::GetSelected().GetRID(); + + std::string ridStr = std::to_string(rid1); + + ImGui::Text("RID:"); + ImGui::SameLine(); + if (ImGui::Button(std::to_string(rid1).c_str())) + { + ImGui::SetClipboardText(std::to_string(rid1).c_str()); + } + + + auto ip = Players::GetSelected().GetExternalAddress(); + + auto addr2 = BuildIPStr(ip.m_IpAddress.m_Field1, ip.m_IpAddress.m_Field2, ip.m_IpAddress.m_Field3, ip.m_IpAddress.m_Field4); + + ImGui::Text("IP Address:"); + ImGui::SameLine(); + if (ImGui::Button(addr2.c_str())) + { + ImGui::SetClipboardText(addr2.c_str()); + } + + if (ImGui::Button("View SC Profile")) + FiberPool::Push([] { + uint64_t handle[13]; + NETWORK::NETWORK_HANDLE_FROM_PLAYER(Players::GetSelected().GetId(), (Any*)&handle, sizeof(handle)); + NETWORK::NETWORK_SHOW_PROFILE_UI((Any*)&handle); + }); + ImGui::SameLine(); + if (ImGui::Button("Add Friend")) + FiberPool::Push([] { + uint64_t handle[13]; + NETWORK::NETWORK_HANDLE_FROM_PLAYER(Players::GetSelected().GetId(), (Any*)&handle, sizeof(handle)); + NETWORK::NETWORK_ADD_FRIEND((Any*)&handle, ""); + }); + + if (ImGui::Button("More Info")) + ImGui::OpenPopup("More Info"); + + ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); + if (ImGui::BeginPopupModal("More Info", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_Modal | ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Text("Average Latency: %.2f", Players::GetSelected().GetAverageLatency()); + ImGui::Text("Packet Loss: %.2f", Players::GetSelected().GetAveragePacketLoss()); + + ImGui::Spacing(); + + if (ImGui::Button("Close") || ((!ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered()) && ImGui::IsMouseClicked(ImGuiMouseButton_Left))) + ImGui::CloseCurrentPopup(); + + ImGui::EndPopup(); + } + } + else + { + Players::SetSelected(Self::GetPlayer()); + ImGui::Text("No players yet!"); + } + })); + + menu->AddItem(playerOptionsGroup); + menu->AddItem(teleportGroup); + + return menu; + } +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Player/Info.hpp b/src/game/frontend/submenus/Player/Info.hpp new file mode 100644 index 0000000..805c940 --- /dev/null +++ b/src/game/frontend/submenus/Player/Info.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "core/frontend/manager/Category.hpp" +#include "game/frontend/items/Items.hpp" + +namespace YimMenu::Submenus +{ + std::shared_ptr BuildInfoMenu(); +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Players.cpp b/src/game/frontend/submenus/Players.cpp new file mode 100644 index 0000000..7a8a708 --- /dev/null +++ b/src/game/frontend/submenus/Players.cpp @@ -0,0 +1,123 @@ +#include "Players.hpp" + +#include "Player/Info.hpp" +#include "core/frontend/widgets/imgui_colors.h" +#include "game/backend/PlayerData.hpp" +#include "game/backend/Players.hpp" +#include "game/frontend/items/Items.hpp" + +namespace YimMenu::Submenus +{ + struct Tag + { + std::string Name; + ImVec4 Color; + }; + + static std::vector GetPlayerTags(YimMenu::Player player) + { + std::vector tags; + + if (player.IsHost()) + tags.push_back({"HOST", ImGui::Colors::DeepSkyBlue}); + + if (false) + tags.push_back({"MOD", ImGui::Colors::DeepPink}); + + if (player.GetPed() && player.GetPed().IsInvincible()) + tags.push_back({"GOD", ImGui::Colors::Crimson}); + + if (player.GetPed() && !player.GetPed().IsVisible()) + tags.push_back({"INVIS", ImGui::Colors::MediumPurple}); + + return tags; + } + + static void DrawPlayerList(bool external = true, float offset = 15.0f) + { + struct ComparePlayerNames + { + bool operator()(YimMenu::Player a, YimMenu::Player b) const + { + std::string nameA = a.GetName(); + std::string nameB = b.GetName(); + return nameA < nameB; + } + }; + + std::map sortedPlayers(YimMenu::Players::GetPlayers().begin(), + YimMenu::Players::GetPlayers().end()); + + if (external) + { + ImGui::SetNextWindowPos( + ImVec2(ImGui::GetWindowPos().x + ImGui::GetWindowSize().x + offset, ImGui::GetWindowPos().y)); + ImGui::SetNextWindowSize(ImVec2(215, ImGui::GetWindowSize().y)); + ImGui::Begin("Player List", nullptr, ImGuiWindowFlags_NoDecoration); + + BoolCommandItem("spectate"_J).Draw(); + for (auto& [id, player] : sortedPlayers) + { + std::string display_name = player.GetName(); + + ImGui::PushID(id); + if (ImGui::Selectable(display_name.c_str(), (YimMenu::Players::GetSelected() == player))) + { + YimMenu::Players::SetSelected(id); + } + ImGui::PopID(); + +#if 0 + if (player.IsModder() && ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + for (auto detection : player.GetData().m_Detections) + ImGui::BulletText("%s", g_PlayerDatabase->ConvertDetectionToDescription(detection).c_str()); + ImGui::EndTooltip(); + } +#endif + + auto tags = GetPlayerTags(player); + + auto old_item_spacing = ImGui::GetStyle().ItemSpacing.x; + + for (auto& tag : tags) + { + ImGui::SameLine(); + ImGui::PushStyleColor(ImGuiCol_Text, tag.Color); + ImGui::Text("%s", ("[" + tag.Name + "]").c_str()); + ImGui::PopStyleColor(); + ImGui::GetStyle().ItemSpacing.x = 1; + } + + ImGui::GetStyle().ItemSpacing.x = old_item_spacing; + } + ImGui::End(); + } + else + { + if (ImGui::BeginCombo("Players", YimMenu::Players::GetSelected().GetName())) + { + for (auto& [id, player] : sortedPlayers) + { + if (ImGui::Selectable(player.GetName(), (YimMenu::Players::GetSelected() == player))) + { + YimMenu::Players::SetSelected(id); + } + } + ImGui::EndCombo(); + } + } + } + + Players::Players() : + Submenu::Submenu("Players") + { + AddCategory(std::move(BuildInfoMenu())); + + for (auto& category : m_Categories) + category->PrependItem(std::make_shared([] { + DrawPlayerList(); + })); + } +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Players.hpp b/src/game/frontend/submenus/Players.hpp new file mode 100644 index 0000000..5a1a1af --- /dev/null +++ b/src/game/frontend/submenus/Players.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "core/frontend/manager/UIManager.hpp" + +namespace YimMenu::Submenus +{ + class Players : public Submenu + { + public: + Players(); + }; +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Self.cpp b/src/game/frontend/submenus/Self.cpp index 5ed45f5..fe8d8a9 100644 --- a/src/game/frontend/submenus/Self.cpp +++ b/src/game/frontend/submenus/Self.cpp @@ -25,6 +25,7 @@ namespace YimMenu::Submenus auto toolsGroup = std::make_shared("Tools"); globalsGroup->AddItem(std::make_shared("godmode"_J)); + globalsGroup->AddItem(std::make_shared("invis"_J)); toolsGroup->AddItem(std::make_shared("suicide"_J)); diff --git a/src/game/gta/Entity.cpp b/src/game/gta/Entity.cpp index 92e09d5..3c6a2f7 100644 --- a/src/game/gta/Entity.cpp +++ b/src/game/gta/Entity.cpp @@ -51,13 +51,10 @@ namespace YimMenu { if (m_Handle) { - // TODO: does this work? is this UB? - [[assume((IsValid(), IsValid() && m_Handle != 0))]]; // https://en.cppreference.com/w/cpp/language/attributes/assume return ENTITY::DOES_ENTITY_EXIST(m_Handle); } else if (m_Pointer) { - [[assume((IsValid(), IsValid() && m_Pointer != nullptr))]]; return true; // TODO: potential use after free } diff --git a/src/game/gta/Natives.hpp b/src/game/gta/Natives.hpp index 271a5ce..2920ce1 100644 --- a/src/game/gta/Natives.hpp +++ b/src/game/gta/Natives.hpp @@ -1,5 +1,5 @@ #pragma once -#include "invoker/invoker.hpp" +#include "invoker/Invoker.hpp" #include "types/script/types.hpp" // clang-format off diff --git a/src/game/gta/Ped.cpp b/src/game/gta/Ped.cpp index 77b28fa..ec8911c 100644 --- a/src/game/gta/Ped.cpp +++ b/src/game/gta/Ped.cpp @@ -118,9 +118,25 @@ namespace YimMenu #ifdef ENTITY_DEBUG if (!IsPlayer()) { - LOG(WARNING) << __FUNCTION__ ": ped is not a player!"; + LOG(WARNING) << __FUNCTION__ << ": ped is not a player!"; } #endif return NETWORK::NETWORK_GET_PLAYER_INDEX_FROM_PED(GetHandle()); } + + void Ped::SetInfiniteAmmo(bool infinite) + { + ENTITY_ASSERT_VALID(); + ENTITY_ASSERT_CONTROL(); + + WEAPON::SET_PED_INFINITE_AMMO(GetHandle(), infinite, NULL); + } + + void Ped::SetInfiniteClip(bool infinite) + { + ENTITY_ASSERT_VALID(); + ENTITY_ASSERT_CONTROL(); + + WEAPON::SET_PED_INFINITE_AMMO_CLIP(GetHandle(), infinite); // is this networked? + } } \ No newline at end of file diff --git a/src/game/gta/Ped.hpp b/src/game/gta/Ped.hpp index d009a0a..12563a0 100644 --- a/src/game/gta/Ped.hpp +++ b/src/game/gta/Ped.hpp @@ -36,5 +36,9 @@ namespace YimMenu // player // We're returning a handle here and not a Player because we don't want to create a cyclic import dependency int GetPlayer(); + + // weapons + void SetInfiniteAmmo(bool infinite); + void SetInfiniteClip(bool infinite); }; } \ No newline at end of file diff --git a/src/game/gta/Player.cpp b/src/game/gta/Player.cpp new file mode 100644 index 0000000..5bb2d63 --- /dev/null +++ b/src/game/gta/Player.cpp @@ -0,0 +1,160 @@ +#include "Player.hpp" + +#include "Natives.hpp" +#include "game/pointers/Pointers.hpp" +#include "types/network/rlGamerInfo.hpp" +#include "types/network/CNetGamePlayer.hpp" + +namespace YimMenu +{ + Player::Player(uint8_t id) + { + m_Handle = Pointers.GetNetPlayerFromPid(id); + } + + bool Player::IsValid() const + { + return m_Handle && m_Handle->IsPhysical() && m_Handle->m_PlayerInfo; + } + + int Player::GetId() + { + if (!IsValid()) + { + if (!*Pointers.IsSessionStarted) + return 0; + + return 255; + } + + return m_Handle->m_PlayerIndex; + } + + const char* Player::GetName() + { + if (!IsValid()) + { + return "Invalid"; + } + + return m_Handle->GetName(); + } + + CNetGamePlayer* Player::GetHandle() + { + return m_Handle; + } + + rage::rlGamerInfo* Player::GetGamerInfo() + { + if (!IsValid()) + return nullptr; + + return m_Handle->GetGamerInfo(); + } + + Ped Player::GetPed() + { + if (!IsValid()) + return nullptr; + + return PLAYER::GET_PLAYER_PED_SCRIPT_INDEX(m_Handle->m_PlayerIndex); + // return m_Handle->m_PlayerInfo->m_Ped; + } + + bool Player::IsHost() + { + if (IsValid()) + return m_Handle->IsHost(); + + return false; + } + +#if 0 + bool Player::IsFriend() + { + if (!IsValid()) + return false; + + for (int i = 0; i < 250; i++) + { + if (!Pointers.FriendRegistry[i]) + break; + + if (Pointers.FriendRegistry[i]->m_RockstarId == GetRID()) + return true; + } + + return false; + } +#endif + + uint32_t Player::GetMessageId() + { + return m_Handle->m_MessageId; + } + + uint64_t Player::GetRID() + { + if (!IsValid()) + return 0; + + return m_Handle->GetGamerInfo()->m_GamerHandle.m_RockstarId; + } + + netSocketAddress Player::GetExternalAddress() + { +#if 0 + if (auto addr = GetConnectPeerAddress()) + return addr->m_ExternalAddress; +#endif + if (auto gamer_info = m_Handle->GetGamerInfo()) + return gamer_info->m_ExternalAddress; + + return {}; + } + + netSocketAddress Player::GetInternalAddress() + { +#if 0 + if (auto addr = GetConnectPeerAddress()) + return addr->m_InternalAddress; +#endif + if (auto gamer_info = m_Handle->GetGamerInfo()) + return gamer_info->m_InternalAddress; + + return {}; + } + + float Player::GetAverageLatency() + { + if (!IsValid()) + return -1.f; + + return NETWORK::NETWORK_GET_AVERAGE_LATENCY(GetId()); + } + + float Player::GetAveragePacketLoss() + { + if (!IsValid()) + return -1.f; + + return NETWORK::NETWORK_GET_AVERAGE_PACKET_LOSS(GetId()); + } + + void Player::SetVisibleLocally(bool visible) + { + if (!IsValid()) + return; + + if (visible) + NETWORK::SET_PLAYER_VISIBLE_LOCALLY(GetId(), false); + else + NETWORK::SET_PLAYER_INVISIBLE_LOCALLY(GetId(), false); + } + + bool Player::operator==(Player other) + { + return m_Handle == other.m_Handle; + } +} \ No newline at end of file diff --git a/src/game/gta/Player.hpp b/src/game/gta/Player.hpp new file mode 100644 index 0000000..87d0a7d --- /dev/null +++ b/src/game/gta/Player.hpp @@ -0,0 +1,75 @@ +#pragma once +#include "Ped.hpp" +#include "types/network/netSocketAddress.hpp" + +class CNetGamePlayer; +union netAddress; + +namespace rage +{ + class rlGamerInfo; + class rlGamerInfoBase; + class netAddress; +} + +namespace YimMenu +{ + class PlayerData; + + class Player + { + CNetGamePlayer* m_Handle; + + public: + Player() : + m_Handle(nullptr) + { + } + + Player(uint8_t id); + + constexpr Player(CNetGamePlayer* netGamePlayer) : + m_Handle(netGamePlayer) + { + } + + // object + bool IsValid() const; + int GetId(); + const char* GetName(); + CNetGamePlayer* GetHandle(); + rage::rlGamerInfo* GetGamerInfo(); + // rage::rlGamerInfoBase* GetConnectPeerAddress(); + // rage::netAddress* GetAddress(); + Ped GetPed(); + bool IsHost(); + // bool IsFriend(); + uint32_t GetMessageId(); + uint64_t GetRID(); + netSocketAddress GetExternalAddress(); + netSocketAddress GetInternalAddress(); + // uint32_t GetConnectionType(); + float GetAverageLatency(); + float GetAveragePacketLoss(); + +#if 0 + // backend/data store (should be refactored?) + PlayerData& GetData(); + bool IsModder(); + void AddDetection(Detection det); +#endif + + // visibility + void SetVisibleLocally(bool visible); + + bool operator==(Player other); + + inline operator bool() + { + return IsValid(); + } + + inline operator int() = delete; + }; + static_assert(sizeof(Player) == 8, "don't add anything else to Player"); +} \ No newline at end of file diff --git a/src/game/gta/invoker/GenerateNatives.py b/src/game/gta/invoker/GenerateNatives.py index b632597..c7d82dc 100644 --- a/src/game/gta/invoker/GenerateNatives.py +++ b/src/game/gta/invoker/GenerateNatives.py @@ -107,7 +107,7 @@ def write_natives_header(): natives_buf = natives_buf[:-2] open("../Natives.hpp", "w+").write(f"""#pragma once -#include "invoker/invoker.hpp" +#include "invoker/Invoker.hpp" #include "types/script/types.hpp" // clang-format off diff --git a/src/game/hooks/Hooks.hpp b/src/game/hooks/Hooks.hpp index 8a58447..acd53db 100644 --- a/src/game/hooks/Hooks.hpp +++ b/src/game/hooks/Hooks.hpp @@ -1,6 +1,9 @@ #pragma once #include +class CNetworkPlayerMgr; +class CNetGamePlayer; + namespace YimMenu::Hooks { namespace SwapChain @@ -12,6 +15,11 @@ namespace YimMenu::Hooks extern HRESULT ResizeBuffers(IDXGISwapChain* that, UINT bufferCount, UINT width, UINT height, DXGI_FORMAT newFormat, UINT swapChainFlags); } + namespace Info + { + extern void AssignPhysicalIndex(CNetworkPlayerMgr* mgr, CNetGamePlayer* player, std::uint8_t index); + } + namespace Script { extern bool RunScriptThreads(int ops_to_execute); diff --git a/src/game/hooks/Info/AssignPhysicalIndex.cpp b/src/game/hooks/Info/AssignPhysicalIndex.cpp new file mode 100644 index 0000000..76fd199 --- /dev/null +++ b/src/game/hooks/Info/AssignPhysicalIndex.cpp @@ -0,0 +1,23 @@ +#include "core/hooking/DetourHook.hpp" +#include "game/hooks/Hooks.hpp" +#include "game/backend/Players.hpp" + +namespace YimMenu::Hooks +{ + void Info::AssignPhysicalIndex(CNetworkPlayerMgr* mgr, CNetGamePlayer* player, std::uint8_t index) + { + if (!g_Running) + return BaseHook::Get>()->Original()(mgr, player, index); + + if (index != 255) + { + BaseHook::Get>()->Original()(mgr, player, index); + Players::OnPlayerJoin(player); + } + else + { + Players::OnPlayerLeave(player); + BaseHook::Get>()->Original()(mgr, player, index); + } + } +} \ No newline at end of file diff --git a/src/game/hooks/Script/RunScriptThreads.cpp b/src/game/hooks/Script/RunScriptThreads.cpp index 25ba8df..abcbb21 100644 --- a/src/game/hooks/Script/RunScriptThreads.cpp +++ b/src/game/hooks/Script/RunScriptThreads.cpp @@ -7,6 +7,7 @@ namespace YimMenu::Hooks { bool Script::RunScriptThreads(int ops_to_execute) { + auto res = BaseHook::Get>()->Original()(ops_to_execute); // let's see what happens if we run our stuff after the game code instead of before if (g_Running) { auto thread = Scripts::FindScriptThread("freemode"_J); @@ -21,6 +22,6 @@ namespace YimMenu::Hooks }); } } - return BaseHook::Get>()->Original()(ops_to_execute); + return res; } } \ No newline at end of file diff --git a/src/game/pointers/Pointers.cpp b/src/game/pointers/Pointers.cpp index e1cf07a..3bfb7b9 100644 --- a/src/game/pointers/Pointers.cpp +++ b/src/game/pointers/Pointers.cpp @@ -28,7 +28,7 @@ namespace YimMenu constexpr auto wndProcPtrn = Pattern<"3D 85 00 00 00 0F 87 2D 02 00 00">("WndProc"); scanner.Add(wndProcPtrn, [this](PointerCalculator ptr) { - WndProc = ptr.Sub(0x4F).As(); + WndProc = ptr.Sub(0x4F).As(); }); constexpr auto hWndPtrn = Pattern<"E8 ? ? ? ? 84 C0 74 25 48 8B 0D">("HWND"); @@ -63,6 +63,26 @@ namespace YimMenu PtrToHandle = ptr.Sub(0xB).Add(3).Rip().As(); }); + constexpr auto pedFactoryPtrn = Pattern<"C7 40 30 03 00 00 00 48 8B 0D">("PedFactory"); + scanner.Add(pedFactoryPtrn, [this](PointerCalculator ptr) { + PedFactory = ptr.Add(7).Add(3).Rip().As(); + }); + + constexpr auto getNetPlayerFromPidPtrn = Pattern<"83 FB 20 74 2A 89 D9">("GetNetPlayerFromPID"); + scanner.Add(getNetPlayerFromPidPtrn, [this](PointerCalculator ptr) { + GetNetPlayerFromPid = ptr.Add(8).Rip().As(); + }); + + constexpr auto isSessionStarted = Pattern<"0F B6 05 ? ? ? ? 0A 05 ? ? ? ? 75 2A">("IsSessionStarted"); + scanner.Add(isSessionStarted, [this](PointerCalculator addr) { + IsSessionStarted = addr.Add(3).Rip().As(); + }); + + constexpr auto assignPhysicalIndexPtrn = Pattern<"41 8D 47 01 3C 20 0F 87 68 01 00 00">("AssignPhysicalIndex"); + scanner.Add(assignPhysicalIndexPtrn, [this](PointerCalculator ptr) { + AssignPhysicalIndex = ptr.Sub(0x13).As(); + }); + if (!scanner.Scan()) { LOG(FATAL) << "Some patterns could not be found, unloading."; diff --git a/src/game/pointers/Pointers.hpp b/src/game/pointers/Pointers.hpp index 8e099fe..9d9dfa9 100644 --- a/src/game/pointers/Pointers.hpp +++ b/src/game/pointers/Pointers.hpp @@ -11,6 +11,8 @@ namespace rage class scrThread; class scrProgram; } +class CPedFactory; +class CNetGamePlayer; namespace YimMenu { @@ -19,6 +21,7 @@ namespace YimMenu using PopulateNatives = void (*)(rage::scrProgram* program); using HandleToPtr = void* (*)(int handle); using PtrToHandle = int (*)(void* pointer); + using GetNetPlayerFromPid = CNetGamePlayer* (*)(int id); } struct PointerData @@ -26,7 +29,7 @@ namespace YimMenu IDXGISwapChain1** SwapChain; ID3D12CommandQueue** CommandQueue; HWND* Hwnd; - WNDPROC WndProc; + PVOID WndProc; std::uint32_t* ScreenResX; std::uint32_t* ScreenResY; rage::atArray* ScriptThreads; @@ -35,6 +38,10 @@ namespace YimMenu PVOID RunScriptThreads; Functions::HandleToPtr HandleToPtr; Functions::PtrToHandle PtrToHandle; + CPedFactory** PedFactory; + Functions::GetNetPlayerFromPid GetNetPlayerFromPid; + bool* IsSessionStarted; + PVOID AssignPhysicalIndex; }; struct Pointers : PointerData diff --git a/src/types/network/CNetGamePlayer.hpp b/src/types/network/CNetGamePlayer.hpp new file mode 100644 index 0000000..c23456f --- /dev/null +++ b/src/types/network/CNetGamePlayer.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "netPlayer.hpp" + +class CPlayerInfo; +class CNetGamePlayer : public rage::netPlayer +{ +public: + void* m_Unk; // 0xA0 + CPlayerInfo* m_PlayerInfo; // 0xA8 + char m_Pad2[0x280]; // 0xB0 +}; //Size: 0x02C0 +static_assert(sizeof(CNetGamePlayer) == 0x330); \ No newline at end of file diff --git a/src/types/network/netAddress.hpp b/src/types/network/netAddress.hpp new file mode 100644 index 0000000..2765883 --- /dev/null +++ b/src/types/network/netAddress.hpp @@ -0,0 +1,17 @@ +#pragma once +#include "netSocketAddress.hpp" + +namespace rage +{ + // TODO: verify for Enhanced + class netAddress + { + public: + netSocketAddress m_InternalIp; // 0x00 + netSocketAddress m_ExternalIp; // 0x08 + uint64_t m_PeerId; // 0x10 for peer relay cxns + char m_Pad[6]; // 0x18 TODO: what is this? it's not a usual address (padding would exist otherwise) + uint8_t m_ConnectionType; // 0x1E 1 = direct 2 = relay 3 = peer relays + }; + static_assert(sizeof(netAddress) == 0x20); +} \ No newline at end of file diff --git a/src/types/network/netPlayer.hpp b/src/types/network/netPlayer.hpp new file mode 100644 index 0000000..2bafd1f --- /dev/null +++ b/src/types/network/netPlayer.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "types/rage/RTTI.hpp" + +namespace rage +{ + class rlGamerInfo; +} +class CNonPhysicalPlayerData; + +namespace rage +{ +#pragma pack(push, 8) + class netPlayer + { + public: + DEFINE_RAGE_RTTI(netPlayer); + + virtual void Reset(); + virtual bool IsPhysical(); + virtual const char* GetName(); + virtual std::uint64_t GetHostToken(); + virtual void UpdatePermissions(); // dev status, comm perms, etc. + virtual bool IsHost(); + virtual rage::rlGamerInfo* GetGamerInfo(); + virtual void UpdateUnk(); // force updates a player ped data node + + char pad_0008[8]; //0x0008 + CNonPhysicalPlayerData* m_NonPhysicalPlayer; //0x0010 + uint32_t m_MessageId; //0x0018 + char pad_001C[4]; //0x001C + uint8_t m_ActiveId; //0x0020 + uint8_t m_PlayerIndex; //0x0021 + char pad_0022[0x7E]; //0x0022 + }; //Size: 0x00A0 + static_assert(sizeof(netPlayer) == 0xA0); +#pragma pack(pop) +} \ No newline at end of file diff --git a/src/types/network/netSocketAddress.hpp b/src/types/network/netSocketAddress.hpp new file mode 100644 index 0000000..97987c7 --- /dev/null +++ b/src/types/network/netSocketAddress.hpp @@ -0,0 +1,18 @@ +#pragma once +#include + +struct netSocketAddress +{ + union { + uint32_t m_Packed; + struct + { + uint8_t m_Field4; + uint8_t m_Field3; + uint8_t m_Field2; + uint8_t m_Field1; + }; + } m_IpAddress; + std::uint16_t m_Port; +}; +static_assert(sizeof(netSocketAddress) == 0x08); \ No newline at end of file diff --git a/src/types/network/rlGamerHandle.hpp b/src/types/network/rlGamerHandle.hpp new file mode 100644 index 0000000..ec7b330 --- /dev/null +++ b/src/types/network/rlGamerHandle.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace rage +{ + // this appears to have been unchanged in E&E + enum rlPlatforms : uint8_t + { + UNK0, + XBOX, + PLAYSTATION, + PC, + }; + + class rlGamerHandle + { + public: + int64_t m_RockstarId; // 0x00 + uint8_t m_Platform; // 0x08 + uint8_t m_ProfileIndex; // 0x09 (maybe, or some kind of discriminator) + + inline rlGamerHandle() = default; + + inline rlGamerHandle(int64_t rockstar_id) : + m_RockstarId(rockstar_id), + m_Platform(rlPlatforms::PC), + m_ProfileIndex(0) + { + } + }; //Size: 0x0010 + static_assert(sizeof(rlGamerHandle) == 0x10); +} \ No newline at end of file diff --git a/src/types/network/rlGamerInfo.hpp b/src/types/network/rlGamerInfo.hpp new file mode 100644 index 0000000..f077b5e --- /dev/null +++ b/src/types/network/rlGamerInfo.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "rlGamerInfoBase.hpp" + +namespace rage +{ + class rlGamerInfo : public rlGamerInfoBase + { + public: + uint64_t m_HostToken; // 0xC0 + + union { + rlGamerHandle m_GamerHandle2; + uint32_t m_PeerId2; // not found in all instances (TODO I don't think it's found at all anymore) + }; // 0xC8 + uint32_t m_ROSPrivilege; // 0xD8 + char m_name[17]; // 0xDC + }; + static_assert(sizeof(rlGamerInfo) == 0xF0); +} \ No newline at end of file diff --git a/src/types/network/rlGamerInfoBase.hpp b/src/types/network/rlGamerInfoBase.hpp new file mode 100644 index 0000000..88a4a85 --- /dev/null +++ b/src/types/network/rlGamerInfoBase.hpp @@ -0,0 +1,23 @@ +#pragma once +#include "netSocketAddress.hpp" +#include "netAddress.hpp" +#include "rlGamerHandle.hpp" + +namespace rage +{ + class rlGamerInfoBase + { + public: + bool m_SecurityEnabled; // 0x00 + uint64_t m_PeerId; // 0x08 + rlGamerHandle m_GamerHandle; // 0x10 + char m_AESKey[0x28]; // 0x20 + netAddress m_RelayAddress; // 0x48 + char m_RelaySignature[0x40]; // 0x68 + netSocketAddress m_ExternalAddress; // 0xA8 + netSocketAddress m_InternalAddress; // 0xB0 + uint32_t m_NatType; // 0xB8 + bool m_ForceRelays; // 0xBC + }; + static_assert(sizeof(rlGamerInfoBase) == 0xC0); +} \ No newline at end of file diff --git a/src/types/pad/ControllerInputs.hpp b/src/types/pad/ControllerInputs.hpp new file mode 100644 index 0000000..654d4f0 --- /dev/null +++ b/src/types/pad/ControllerInputs.hpp @@ -0,0 +1,370 @@ +#pragma once + +enum class ControllerInputs : uint32_t +{ + INPUT_NEXT_CAMERA, + INPUT_LOOK_LR, + INPUT_LOOK_UD, + INPUT_LOOK_UP_ONLY, + INPUT_LOOK_DOWN_ONLY, + INPUT_LOOK_LEFT_ONLY, + INPUT_LOOK_RIGHT_ONLY, + INPUT_CINEMATIC_SLOWMO, + INPUT_SCRIPTED_FLY_UD, + INPUT_SCRIPTED_FLY_LR, + INPUT_SCRIPTED_FLY_ZUP, + INPUT_SCRIPTED_FLY_ZDOWN, + INPUT_WEAPON_WHEEL_UD, + INPUT_WEAPON_WHEEL_LR, + INPUT_WEAPON_WHEEL_NEXT, + INPUT_WEAPON_WHEEL_PREV, + INPUT_SELECT_NEXT_WEAPON, + INPUT_SELECT_PREV_WEAPON, + INPUT_SKIP_CUTSCENE, + INPUT_CHARACTER_WHEEL, + INPUT_MULTIPLAYER_INFO, + INPUT_SPRINT, + INPUT_JUMP, + INPUT_ENTER, + INPUT_ATTACK, + INPUT_AIM, + INPUT_LOOK_BEHIND, + INPUT_PHONE, + INPUT_SPECIAL_ABILITY, + INPUT_SPECIAL_ABILITY_SECONDARY, + INPUT_MOVE_LR, + INPUT_MOVE_UD, + INPUT_MOVE_UP_ONLY, + INPUT_MOVE_DOWN_ONLY, + INPUT_MOVE_LEFT_ONLY, + INPUT_MOVE_RIGHT_ONLY, + INPUT_DUCK, + INPUT_SELECT_WEAPON, + INPUT_PICKUP, + INPUT_SNIPER_ZOOM, + INPUT_SNIPER_ZOOM_IN_ONLY, + INPUT_SNIPER_ZOOM_OUT_ONLY, + INPUT_SNIPER_ZOOM_IN_SECONDARY, + INPUT_SNIPER_ZOOM_OUT_SECONDARY, + INPUT_COVER, + INPUT_RELOAD, + INPUT_TALK, + INPUT_DETONATE, + INPUT_HUD_SPECIAL, + INPUT_ARREST, + INPUT_ACCURATE_AIM, + INPUT_CONTEXT, + INPUT_CONTEXT_SECONDARY, + INPUT_WEAPON_SPECIAL, + INPUT_WEAPON_SPECIAL_TWO, + INPUT_DIVE, + INPUT_DROP_WEAPON, + INPUT_DROP_AMMO, + INPUT_THROW_GRENADE, + INPUT_VEH_MOVE_LR, + INPUT_VEH_MOVE_UD, + INPUT_VEH_MOVE_UP_ONLY, + INPUT_VEH_MOVE_DOWN_ONLY, + INPUT_VEH_MOVE_LEFT_ONLY, + INPUT_VEH_MOVE_RIGHT_ONLY, + INPUT_VEH_SPECIAL, + INPUT_VEH_GUN_LR, + INPUT_VEH_GUN_UD, + INPUT_VEH_AIM, + INPUT_VEH_ATTACK, + INPUT_VEH_ATTACK2, + INPUT_VEH_ACCELERATE, + INPUT_VEH_BRAKE, + INPUT_VEH_DUCK, + INPUT_VEH_HEADLIGHT, + INPUT_VEH_EXIT, + INPUT_VEH_HANDBRAKE, + INPUT_VEH_HOTWIRE_LEFT, + INPUT_VEH_HOTWIRE_RIGHT, + INPUT_VEH_LOOK_BEHIND, + INPUT_VEH_CIN_CAM, + INPUT_VEH_NEXT_RADIO, + INPUT_VEH_PREV_RADIO, + INPUT_VEH_NEXT_RADIO_TRACK, + INPUT_VEH_PREV_RADIO_TRACK, + INPUT_VEH_RADIO_WHEEL, + INPUT_VEH_HORN, + INPUT_VEH_FLY_THROTTLE_UP, + INPUT_VEH_FLY_THROTTLE_DOWN, + INPUT_VEH_FLY_YAW_LEFT, + INPUT_VEH_FLY_YAW_RIGHT, + INPUT_VEH_PASSENGER_AIM, + INPUT_VEH_PASSENGER_ATTACK, + INPUT_VEH_SPECIAL_ABILITY_FRANKLIN, + INPUT_VEH_STUNT_UD, + INPUT_VEH_CINEMATIC_UD, + INPUT_VEH_CINEMATIC_UP_ONLY, + INPUT_VEH_CINEMATIC_DOWN_ONLY, + INPUT_VEH_CINEMATIC_LR, + INPUT_VEH_SELECT_NEXT_WEAPON, + INPUT_VEH_SELECT_PREV_WEAPON, + INPUT_VEH_ROOF, + INPUT_VEH_JUMP, + INPUT_VEH_GRAPPLING_HOOK, + INPUT_VEH_SHUFFLE, + INPUT_VEH_DROP_PROJECTILE, + INPUT_VEH_MOUSE_CONTROL_OVERRIDE, + INPUT_VEH_FLY_ROLL_LR, + INPUT_VEH_FLY_ROLL_LEFT_ONLY, + INPUT_VEH_FLY_ROLL_RIGHT_ONLY, + INPUT_VEH_FLY_PITCH_UD, + INPUT_VEH_FLY_PITCH_UP_ONLY, + INPUT_VEH_FLY_PITCH_DOWN_ONLY, + INPUT_VEH_FLY_UNDERCARRIAGE, + INPUT_VEH_FLY_ATTACK, + INPUT_VEH_FLY_SELECT_NEXT_WEAPON, + INPUT_VEH_FLY_SELECT_PREV_WEAPON, + INPUT_VEH_FLY_SELECT_TARGET_LEFT, + INPUT_VEH_FLY_SELECT_TARGET_RIGHT, + INPUT_VEH_FLY_VERTICAL_FLIGHT_MODE, + INPUT_VEH_FLY_DUCK, + INPUT_VEH_FLY_ATTACK_CAMERA, + INPUT_VEH_FLY_MOUSE_CONTROL_OVERRIDE, + INPUT_VEH_SUB_TURN_LR, + INPUT_VEH_SUB_TURN_LEFT_ONLY, + INPUT_VEH_SUB_TURN_RIGHT_ONLY, + INPUT_VEH_SUB_PITCH_UD, + INPUT_VEH_SUB_PITCH_UP_ONLY, + INPUT_VEH_SUB_PITCH_DOWN_ONLY, + INPUT_VEH_SUB_THROTTLE_UP, + INPUT_VEH_SUB_THROTTLE_DOWN, + INPUT_VEH_SUB_ASCEND, + INPUT_VEH_SUB_DESCEND, + INPUT_VEH_SUB_TURN_HARD_LEFT, + INPUT_VEH_SUB_TURN_HARD_RIGHT, + INPUT_VEH_SUB_MOUSE_CONTROL_OVERRIDE, + INPUT_VEH_PUSHBIKE_PEDAL, + INPUT_VEH_PUSHBIKE_SPRINT, + INPUT_VEH_PUSHBIKE_FRONT_BRAKE, + INPUT_VEH_PUSHBIKE_REAR_BRAKE, + INPUT_MELEE_ATTACK_LIGHT, + INPUT_MELEE_ATTACK_HEAVY, + INPUT_MELEE_ATTACK_ALTERNATE, + INPUT_MELEE_BLOCK, + INPUT_PARACHUTE_DEPLOY, + INPUT_PARACHUTE_DETACH, + INPUT_PARACHUTE_TURN_LR, + INPUT_PARACHUTE_TURN_LEFT_ONLY, + INPUT_PARACHUTE_TURN_RIGHT_ONLY, + INPUT_PARACHUTE_PITCH_UD, + INPUT_PARACHUTE_PITCH_UP_ONLY, + INPUT_PARACHUTE_PITCH_DOWN_ONLY, + INPUT_PARACHUTE_BRAKE_LEFT, + INPUT_PARACHUTE_BRAKE_RIGHT, + INPUT_PARACHUTE_SMOKE, + INPUT_PARACHUTE_PRECISION_LANDING, + INPUT_MAP, + INPUT_SELECT_WEAPON_UNARMED, + INPUT_SELECT_WEAPON_MELEE, + INPUT_SELECT_WEAPON_HANDGUN, + INPUT_SELECT_WEAPON_SHOTGUN, + INPUT_SELECT_WEAPON_SMG, + INPUT_SELECT_WEAPON_AUTO_RIFLE, + INPUT_SELECT_WEAPON_SNIPER, + INPUT_SELECT_WEAPON_HEAVY, + INPUT_SELECT_WEAPON_SPECIAL, + INPUT_SELECT_CHARACTER_MICHAEL, + INPUT_SELECT_CHARACTER_FRANKLIN, + INPUT_SELECT_CHARACTER_TREVOR, + INPUT_SELECT_CHARACTER_MULTIPLAYER, + INPUT_SAVE_REPLAY_CLIP, + INPUT_SPECIAL_ABILITY_PC, + INPUT_CELLPHONE_UP, + INPUT_CELLPHONE_DOWN, + INPUT_CELLPHONE_LEFT, + INPUT_CELLPHONE_RIGHT, + INPUT_CELLPHONE_SELECT, + INPUT_CELLPHONE_CANCEL, + INPUT_CELLPHONE_OPTION, + INPUT_CELLPHONE_EXTRA_OPTION, + INPUT_CELLPHONE_SCROLL_FORWARD, + INPUT_CELLPHONE_SCROLL_BACKWARD, + INPUT_CELLPHONE_CAMERA_FOCUS_LOCK, + INPUT_CELLPHONE_CAMERA_GRID, + INPUT_CELLPHONE_CAMERA_SELFIE, + INPUT_CELLPHONE_CAMERA_DOF, + INPUT_CELLPHONE_CAMERA_EXPRESSION, + INPUT_FRONTEND_DOWN, + INPUT_FRONTEND_UP, + INPUT_FRONTEND_LEFT, + INPUT_FRONTEND_RIGHT, + INPUT_FRONTEND_RDOWN, + INPUT_FRONTEND_RUP, + INPUT_FRONTEND_RLEFT, + INPUT_FRONTEND_RRIGHT, + INPUT_FRONTEND_AXIS_X, + INPUT_FRONTEND_AXIS_Y, + INPUT_FRONTEND_RIGHT_AXIS_X, + INPUT_FRONTEND_RIGHT_AXIS_Y, + INPUT_FRONTEND_PAUSE, + INPUT_FRONTEND_PAUSE_ALTERNATE, + INPUT_FRONTEND_ACCEPT, + INPUT_FRONTEND_CANCEL, + INPUT_FRONTEND_X, + INPUT_FRONTEND_Y, + INPUT_FRONTEND_LB, + INPUT_FRONTEND_RB, + INPUT_FRONTEND_LT, + INPUT_FRONTEND_RT, + INPUT_FRONTEND_LS, + INPUT_FRONTEND_RS, + INPUT_FRONTEND_LEADERBOARD, + INPUT_FRONTEND_SOCIAL_CLUB, + INPUT_FRONTEND_SOCIAL_CLUB_SECONDARY, + INPUT_FRONTEND_DELETE, + INPUT_FRONTEND_ENDSCREEN_ACCEPT, + INPUT_FRONTEND_ENDSCREEN_EXPAND, + INPUT_FRONTEND_SELECT, + INPUT_SCRIPT_LEFT_AXIS_X, + INPUT_SCRIPT_LEFT_AXIS_Y, + INPUT_SCRIPT_RIGHT_AXIS_X, + INPUT_SCRIPT_RIGHT_AXIS_Y, + INPUT_SCRIPT_RUP, + INPUT_SCRIPT_RDOWN, + INPUT_SCRIPT_RLEFT, + INPUT_SCRIPT_RRIGHT, + INPUT_SCRIPT_LB, + INPUT_SCRIPT_RB, + INPUT_SCRIPT_LT, + INPUT_SCRIPT_RT, + INPUT_SCRIPT_LS, + INPUT_SCRIPT_RS, + INPUT_SCRIPT_PAD_UP, + INPUT_SCRIPT_PAD_DOWN, + INPUT_SCRIPT_PAD_LEFT, + INPUT_SCRIPT_PAD_RIGHT, + INPUT_SCRIPT_SELECT, + INPUT_CURSOR_ACCEPT, + INPUT_CURSOR_CANCEL, + INPUT_CURSOR_X, + INPUT_CURSOR_Y, + INPUT_CURSOR_SCROLL_UP, + INPUT_CURSOR_SCROLL_DOWN, + INPUT_ENTER_CHEAT_CODE, + INPUT_INTERACTION_MENU, + INPUT_MP_TEXT_CHAT_ALL, + INPUT_MP_TEXT_CHAT_TEAM, + INPUT_MP_TEXT_CHAT_FRIENDS, + INPUT_MP_TEXT_CHAT_CREW, + INPUT_PUSH_TO_TALK, + INPUT_CREATOR_LS, + INPUT_CREATOR_RS, + INPUT_CREATOR_LT, + INPUT_CREATOR_RT, + INPUT_CREATOR_MENU_TOGGLE, + INPUT_CREATOR_ACCEPT, + INPUT_CREATOR_DELETE, + INPUT_ATTACK2, + INPUT_RAPPEL_JUMP, + INPUT_RAPPEL_LONG_JUMP, + INPUT_RAPPEL_SMASH_WINDOW, + INPUT_PREV_WEAPON, + INPUT_NEXT_WEAPON, + INPUT_MELEE_ATTACK1, + INPUT_MELEE_ATTACK2, + INPUT_WHISTLE, + INPUT_MOVE_LEFT, + INPUT_MOVE_RIGHT, + INPUT_MOVE_UP, + INPUT_MOVE_DOWN, + INPUT_LOOK_LEFT, + INPUT_LOOK_RIGHT, + INPUT_LOOK_UP, + INPUT_LOOK_DOWN, + INPUT_SNIPER_ZOOM_IN, + INPUT_SNIPER_ZOOM_OUT, + INPUT_SNIPER_ZOOM_IN_ALTERNATE, + INPUT_SNIPER_ZOOM_OUT_ALTERNATE, + INPUT_VEH_MOVE_LEFT, + INPUT_VEH_MOVE_RIGHT, + INPUT_VEH_MOVE_UP, + INPUT_VEH_MOVE_DOWN, + INPUT_VEH_GUN_LEFT, + INPUT_VEH_GUN_RIGHT, + INPUT_VEH_GUN_UP, + INPUT_VEH_GUN_DOWN, + INPUT_VEH_LOOK_LEFT, + INPUT_VEH_LOOK_RIGHT, + INPUT_REPLAY_START_STOP_RECORDING, + INPUT_REPLAY_START_STOP_RECORDING_SECONDARY, + INPUT_SCALED_LOOK_LR, + INPUT_SCALED_LOOK_UD, + INPUT_SCALED_LOOK_UP_ONLY, + INPUT_SCALED_LOOK_DOWN_ONLY, + INPUT_SCALED_LOOK_LEFT_ONLY, + INPUT_SCALED_LOOK_RIGHT_ONLY, + INPUT_REPLAY_MARKER_DELETE, + INPUT_REPLAY_CLIP_DELETE, + INPUT_REPLAY_PAUSE, + INPUT_REPLAY_REWIND, + INPUT_REPLAY_FFWD, + INPUT_REPLAY_NEWMARKER, + INPUT_REPLAY_RECORD, + INPUT_REPLAY_SCREENSHOT, + INPUT_REPLAY_HIDEHUD, + INPUT_REPLAY_STARTPOINT, + INPUT_REPLAY_ENDPOINT, + INPUT_REPLAY_ADVANCE, + INPUT_REPLAY_BACK, + INPUT_REPLAY_TOOLS, + INPUT_REPLAY_RESTART, + INPUT_REPLAY_SHOWHOTKEY, + INPUT_REPLAY_CYCLEMARKERLEFT, + INPUT_REPLAY_CYCLEMARKERRIGHT, + INPUT_REPLAY_FOVINCREASE, + INPUT_REPLAY_FOVDECREASE, + INPUT_REPLAY_CAMERAUP, + INPUT_REPLAY_CAMERADOWN, + INPUT_REPLAY_SAVE, + INPUT_REPLAY_TOGGLETIME, + INPUT_REPLAY_TOGGLETIPS, + INPUT_REPLAY_PREVIEW, + INPUT_REPLAY_TOGGLE_TIMELINE, + INPUT_REPLAY_TIMELINE_PICKUP_CLIP, + INPUT_REPLAY_TIMELINE_DUPLICATE_CLIP, + INPUT_REPLAY_TIMELINE_PLACE_CLIP, + INPUT_REPLAY_CTRL, + INPUT_REPLAY_TIMELINE_SAVE, + INPUT_REPLAY_PREVIEW_AUDIO, + INPUT_VEH_DRIVE_LOOK, + INPUT_VEH_DRIVE_LOOK2, + INPUT_VEH_FLY_ATTACK2, + INPUT_RADIO_WHEEL_UD, + INPUT_RADIO_WHEEL_LR, + INPUT_VEH_SLOWMO_UD, + INPUT_VEH_SLOWMO_UP_ONLY, + INPUT_VEH_SLOWMO_DOWN_ONLY, + INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE, + INPUT_VEH_HYDRAULICS_CONTROL_LEFT, + INPUT_VEH_HYDRAULICS_CONTROL_RIGHT, + INPUT_VEH_HYDRAULICS_CONTROL_UP, + INPUT_VEH_HYDRAULICS_CONTROL_DOWN, + INPUT_VEH_HYDRAULICS_CONTROL_LR, + INPUT_VEH_HYDRAULICS_CONTROL_UD, + INPUT_SWITCH_VISOR, + INPUT_VEH_MELEE_HOLD, + INPUT_VEH_MELEE_LEFT, + INPUT_VEH_MELEE_RIGHT, + INPUT_MAP_POI, + INPUT_REPLAY_SNAPMATIC_PHOTO, + INPUT_VEH_CAR_JUMP, + INPUT_VEH_ROCKET_BOOST, + INPUT_VEH_FLY_BOOST, + INPUT_VEH_PARACHUTE, + INPUT_VEH_BIKE_WINGS, + INPUT_VEH_FLY_BOMB_BAY, + INPUT_VEH_FLY_COUNTER, + INPUT_VEH_TRANSFORM, + MAX_INPUTS, + UNDEFINED_INPUT, + DYNAMIC_MAPPING_MOUSE_X, + DYNAMIC_MAPPING_MOUSE_Y, + FIRST_INPUT, + SCRIPTED_INPUT_FIRST, + SCRIPTED_INPUT_LAST +}; \ No newline at end of file diff --git a/src/types/ped/CPedFactory.hpp b/src/types/ped/CPedFactory.hpp new file mode 100644 index 0000000..5078c94 --- /dev/null +++ b/src/types/ped/CPedFactory.hpp @@ -0,0 +1,24 @@ +#pragma once + +class CPed; +class CPlayerInfo; +class CPedFactory +{ +public: + enum class PedCreateFlags + { + IS_NETWORKED = (1 << 0), + IS_PLAYER = (1 << 1) + }; + + virtual ~CPedFactory() = default; + virtual CPed* CreatePed(std::uint8_t* flags, std::uint16_t* model_index, void* matrix, bool default_component_variation, bool register_network_object, bool give_default_loadout, bool, bool) = 0; // 0x08 + virtual CPed* CreateClone(std::uint8_t* flags, std::uint16_t* model_index, void* matrix, bool default_component_variation, bool, bool register_network_object, bool) = 0; // 0x10 + virtual CPed* ClonePed(CPed* ped, bool register_network_object, bool link_blends, bool clone_compressed_damage) = 0; // 0x18 + virtual CPed* ClonePedToTarget(CPed* source, CPed* target, bool clone_compressed_damage) = 0; // 0x20 + virtual CPed* CreatePlayer(std::uint8_t* flags, std::uint16_t model_index, void* matrix, CPlayerInfo* player_info) = 0; // 0x28 + virtual void DestroyPed(CPed* ped) = 0; // 0x30 + + class CPed* m_LocalPed; //0x0008 +}; //Size: 0x0010 +static_assert(sizeof(CPedFactory) == 0x10); \ No newline at end of file diff --git a/src/types/script/scrThread.cpp b/src/types/script/scrThread.cpp new file mode 100644 index 0000000..1758940 --- /dev/null +++ b/src/types/script/scrThread.cpp @@ -0,0 +1,10 @@ +#include "scrThread.hpp" +#include "types/rage/tlsContext.hpp" + +namespace rage +{ + rage::scrThread* scrThread::GetRunningThread() + { + return rage::tlsContext::Get()->m_CurrentScriptThread; + } +} \ No newline at end of file diff --git a/src/types/script/scrThread.hpp b/src/types/script/scrThread.hpp index d4c0b4a..ebffb45 100644 --- a/src/types/script/scrThread.hpp +++ b/src/types/script/scrThread.hpp @@ -48,6 +48,8 @@ namespace rage char m_ErrorMessage[128]; // 0xD0 finally works now (size 124, 4 padding) std::uint32_t m_ScriptHash; // 0x150 char m_ScriptName[64]; // 0x154 + + static rage::scrThread* GetRunningThread(); }; static_assert(sizeof(scrThread) == 0x198); } \ No newline at end of file