diff --git a/CMakeSettings.json b/CMakeSettings.json index 91d88ca..e19e406 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -9,7 +9,7 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", - "inheritEnvironments": [ "msvc_x64_x64" ] + "inheritEnvironments": [ "msvc_x64_x64" ], }, { "name": "x64-Release-Clang", @@ -20,7 +20,9 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "", - "inheritEnvironments": [ "clang_cl_x64_x64" ] + "inheritEnvironments": [ "clang_cl_x64_x64" ], + "enableClangTidyCodeAnalysis": true, + "clangTidyChecks": "clang-analyzer-*" } ] } \ No newline at end of file diff --git a/src/game/commands/PlayerCommand.cpp b/src/game/commands/PlayerCommand.cpp new file mode 100644 index 0000000..ab15eac --- /dev/null +++ b/src/game/commands/PlayerCommand.cpp @@ -0,0 +1,35 @@ +#include "PlayerCommand.hpp" + +#include "game/backend/Players.hpp" + +namespace YimMenu +{ + PlayerAllCommand::PlayerAllCommand(std::string name, std::string label, std::string description, int num_args, PlayerCommand* parent) : + Command(name + "all", label, description, num_args), + m_PlayerCommand(parent) + { + } + + void PlayerAllCommand::OnCall() + { + for (auto& p : Players::GetPlayers()) + m_PlayerCommand->Call(p.second); + } + + PlayerCommand::PlayerCommand(std::string name, std::string label, std::string description, int num_args, bool all_version) : + Command::Command(name, label, description, num_args + 1) + { + if (all_version) + m_AllCommand = std::make_unique(name, label, description, num_args, this); + } + + void PlayerCommand::OnCall() + { + LOG(WARNING) << GetName() << " requires a player argument"; + } + + void PlayerCommand::Call(Player target) + { + OnCall(target); + } +} \ No newline at end of file diff --git a/src/game/commands/PlayerCommand.hpp b/src/game/commands/PlayerCommand.hpp new file mode 100644 index 0000000..3cbff0a --- /dev/null +++ b/src/game/commands/PlayerCommand.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "core/commands/Command.hpp" +#include "game/gta/Player.hpp" + +namespace YimMenu +{ + class PlayerCommand; + class PlayerAllCommand : public Command + { + PlayerCommand* m_PlayerCommand; + + public: + PlayerAllCommand(std::string name, std::string label, std::string description, int num_args, PlayerCommand* parent); + virtual void OnCall() override; + }; + + class PlayerCommand : public Command + { + virtual void OnCall() override; + std::unique_ptr m_AllCommand; + + protected: + virtual void OnCall(Player) = 0; + + public: + PlayerCommand(std::string name, std::string label, std::string description, int num_args = 0, bool all_version = true); + void Call(Player target); // TODO + }; +} \ No newline at end of file diff --git a/src/game/features/players/toxic/Explode.cpp b/src/game/features/players/toxic/Explode.cpp new file mode 100644 index 0000000..d313c38 --- /dev/null +++ b/src/game/features/players/toxic/Explode.cpp @@ -0,0 +1,17 @@ +#include "game/commands/PlayerCommand.hpp" +#include "types/fx/ExplosionType.hpp" + +namespace YimMenu::Features +{ + class Explode : public PlayerCommand + { + using PlayerCommand::PlayerCommand; + + virtual void OnCall(Player player) override + { + player.GetPed().Explode(ExplosionType::ORBITAL_CANNON, 900.f); + } + }; + + static Explode _Explode{"explode", "Explode", "Blows the player up"}; +} \ No newline at end of file diff --git a/src/game/frontend/Menu.cpp b/src/game/frontend/Menu.cpp index d362d77..0d2fcea 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/Network.hpp" #include "submenus/Players.hpp" namespace YimMenu @@ -16,6 +17,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()); UIManager::AddSubmenu(std::make_shared()); Renderer::AddRendererCallBack( diff --git a/src/game/frontend/items/PlayerCommandItem.cpp b/src/game/frontend/items/PlayerCommandItem.cpp index d4880ee..9260227 100644 --- a/src/game/frontend/items/PlayerCommandItem.cpp +++ b/src/game/frontend/items/PlayerCommandItem.cpp @@ -1,10 +1,9 @@ #include "Items.hpp" -//#include "game/commands/PlayerCommand.hpp" +#include "game/commands/PlayerCommand.hpp" #include "core/commands/Commands.hpp" -//#include "game/backend/FiberPool.hpp" -//#include "game/backend/Players.hpp" +#include "core/backend/FiberPool.hpp" +#include "game/backend/Players.hpp" -#if 0 namespace YimMenu { PlayerCommandItem::PlayerCommandItem(joaat_t id, std::optional label_override) : @@ -31,8 +30,7 @@ namespace YimMenu if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(m_Command->GetDescription().data()); + ImGui::SetTooltip("%s", m_Command->GetDescription().data()); } } -} -#endif \ No newline at end of file +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Network.cpp b/src/game/frontend/submenus/Network.cpp new file mode 100644 index 0000000..cfb2c89 --- /dev/null +++ b/src/game/frontend/submenus/Network.cpp @@ -0,0 +1,19 @@ +#include "Network.hpp" +#include "game/frontend/items/Items.hpp" + +namespace YimMenu::Submenus +{ + Network::Network() : + Submenu::Submenu("Network") + { + // TODO: this needs a rework + auto session = std::make_shared("Session"); + auto toxicGroup = std::make_shared("Toxic"); + + toxicGroup->AddItem(std::make_shared("explodeall"_J, "Explode All")); + + session->AddItem(toxicGroup); + + AddCategory(std::move(session)); + } +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Network.hpp b/src/game/frontend/submenus/Network.hpp new file mode 100644 index 0000000..05fe4e8 --- /dev/null +++ b/src/game/frontend/submenus/Network.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "core/frontend/manager/UIManager.hpp" + +namespace YimMenu::Submenus +{ + class Network : public Submenu + { + public: + Network(); + }; +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Player/Info.cpp b/src/game/frontend/submenus/Player/Info.cpp index 1cec476..d4d7bd1 100644 --- a/src/game/frontend/submenus/Player/Info.cpp +++ b/src/game/frontend/submenus/Player/Info.cpp @@ -32,6 +32,9 @@ namespace YimMenu::Submenus playerOptionsGroup->AddItem(std::make_shared([] { if (Players::GetSelected().IsValid()) { + ImGui::Text("Rank: %d (%d RP)", Players::GetSelected().GetRank(), Players::GetSelected().GetRank()); + ImGui::Text("Money: %d", Players::GetSelected().GetMoney()); + if (Players::GetSelected().GetPed()) { auto health = Players::GetSelected().GetPed().GetHealth(); diff --git a/src/game/frontend/submenus/Player/Toxic.cpp b/src/game/frontend/submenus/Player/Toxic.cpp new file mode 100644 index 0000000..27212da --- /dev/null +++ b/src/game/frontend/submenus/Player/Toxic.cpp @@ -0,0 +1,17 @@ +#include "Toxic.hpp" + +namespace YimMenu::Submenus +{ + std::shared_ptr BuildToxicMenu() + { + auto menu = std::make_shared("Toxic"); + + auto general = std::make_shared("General"); + // general->AddItem(std::make_shared("kill"_J)); + general->AddItem(std::make_shared("explode"_J)); + + menu->AddItem(general); + + return menu; + } +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Player/Toxic.hpp b/src/game/frontend/submenus/Player/Toxic.hpp new file mode 100644 index 0000000..a8cdab9 --- /dev/null +++ b/src/game/frontend/submenus/Player/Toxic.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 BuildToxicMenu(); +} \ No newline at end of file diff --git a/src/game/frontend/submenus/Players.cpp b/src/game/frontend/submenus/Players.cpp index 7a8a708..4c7062d 100644 --- a/src/game/frontend/submenus/Players.cpp +++ b/src/game/frontend/submenus/Players.cpp @@ -1,6 +1,7 @@ #include "Players.hpp" #include "Player/Info.hpp" +#include "Player/Toxic.hpp" #include "core/frontend/widgets/imgui_colors.h" #include "game/backend/PlayerData.hpp" #include "game/backend/Players.hpp" @@ -114,6 +115,7 @@ namespace YimMenu::Submenus Submenu::Submenu("Players") { AddCategory(std::move(BuildInfoMenu())); + AddCategory(std::move(BuildToxicMenu())); for (auto& category : m_Categories) category->PrependItem(std::make_shared([] { diff --git a/src/game/gta/Entity.cpp b/src/game/gta/Entity.cpp index 3c6a2f7..977540a 100644 --- a/src/game/gta/Entity.cpp +++ b/src/game/gta/Entity.cpp @@ -4,6 +4,7 @@ #include "core/util/Joaat.hpp" #include "game/pointers/Pointers.hpp" #include "types/rage/tlsContext.hpp" +#include "game/gta/Scripts.hpp" namespace YimMenu { @@ -391,6 +392,21 @@ namespace YimMenu return INTERIOR::GET_INTERIOR_FROM_ENTITY(GetHandle()) != 0; } + void Entity::Explode(ExplosionType explosion, float damage, bool is_visible, bool is_audible, float camera_shake) + { + ENTITY_ASSERT_VALID(); + ENTITY_ASSERT_SCRIPT_CONTEXT(); + + if (!IsValid()) + return; + + auto pos = GetPosition(); + Scripts::RunWithSpoofedThreadName("am_mp_orbital_cannon"_J, [&] { + // add_owned_explosion is more or less useless now + FIRE::ADD_EXPLOSION(pos.x, pos.y, pos.z, static_cast(explosion), damage, is_audible, !is_visible, camera_shake, damage == 0.0f); + }); + } + bool Entity::operator==(const Entity& other) { if (m_Handle != 0 && other.m_Handle != 0) diff --git a/src/game/gta/Entity.hpp b/src/game/gta/Entity.hpp index 1aafe0e..48b8e28 100644 --- a/src/game/gta/Entity.hpp +++ b/src/game/gta/Entity.hpp @@ -14,6 +14,8 @@ #define ENTITY_ASSERT_SCRIPT_CONTEXT() #endif +enum class ExplosionType; + namespace rage { class netObject; @@ -141,6 +143,9 @@ namespace YimMenu bool HasInterior(); + // explosions + void Explode(ExplosionType explosion, float damage = 1.0f, bool is_visible = true, bool is_audible = true, float camera_shake = 1.0f); + bool operator==(const Entity& other); bool operator!=(const Entity& other) { diff --git a/src/game/gta/Player.cpp b/src/game/gta/Player.cpp index 5bb2d63..d0dbffb 100644 --- a/src/game/gta/Player.cpp +++ b/src/game/gta/Player.cpp @@ -5,6 +5,8 @@ #include "types/network/rlGamerInfo.hpp" #include "types/network/CNetGamePlayer.hpp" +#include "types/script/globals/GPBD_FM.hpp" + namespace YimMenu { Player::Player(uint8_t id) @@ -142,6 +144,39 @@ namespace YimMenu return NETWORK::NETWORK_GET_AVERAGE_PACKET_LOSS(GetId()); } + int Player::GetRank() + { + if (!IsValid()) + return 0; + + if (auto fm = GPBD_FM::Get()) + return fm->Entries[GetId()].PlayerStats.Rank; + + return 0; + } + + int Player::GetRP() + { + if (!IsValid()) + return 0; + + if (auto fm = GPBD_FM::Get()) + return fm->Entries[GetId()].PlayerStats.RP; + + return 0; + } + + int Player::GetMoney() + { + if (!IsValid()) + return 0; + + if (auto fm = GPBD_FM::Get()) + return fm->Entries[GetId()].PlayerStats.Money; + + return 0; + } + void Player::SetVisibleLocally(bool visible) { if (!IsValid()) diff --git a/src/game/gta/Player.hpp b/src/game/gta/Player.hpp index 87d0a7d..5bb0fc4 100644 --- a/src/game/gta/Player.hpp +++ b/src/game/gta/Player.hpp @@ -52,6 +52,10 @@ namespace YimMenu float GetAverageLatency(); float GetAveragePacketLoss(); + int GetRank(); + int GetRP(); + int GetMoney(); + #if 0 // backend/data store (should be refactored?) PlayerData& GetData(); diff --git a/src/game/gta/ScriptGlobal.cpp b/src/game/gta/ScriptGlobal.cpp index b0bdc30..b576b8f 100644 --- a/src/game/gta/ScriptGlobal.cpp +++ b/src/game/gta/ScriptGlobal.cpp @@ -7,4 +7,9 @@ namespace YimMenu { return Pointers.ScriptGlobals[m_Index >> 0x12 & 0x3F] + (m_Index & 0x3FFFF); } + + bool ScriptGlobal::CanAccess() const + { + return Pointers.ScriptGlobals && (m_Index >> 0x12 & 0x3F) < 0x40 && Pointers.ScriptGlobals[m_Index >> 0x12 & 0x3F]; + } } \ No newline at end of file diff --git a/src/game/gta/ScriptGlobal.hpp b/src/game/gta/ScriptGlobal.hpp index f0aa474..1d3b166 100644 --- a/src/game/gta/ScriptGlobal.hpp +++ b/src/game/gta/ScriptGlobal.hpp @@ -36,6 +36,8 @@ namespace YimMenu return *static_cast>>(Get()); } + bool CanAccess() const; + private: void* Get() const; diff --git a/src/game/gta/Scripts.cpp b/src/game/gta/Scripts.cpp index 8aa2ab8..7e9b46d 100644 --- a/src/game/gta/Scripts.cpp +++ b/src/game/gta/Scripts.cpp @@ -2,7 +2,9 @@ #include "game/pointers/Pointers.hpp" #include "types/rage/atArray.hpp" #include "types/rage/tlsContext.hpp" -#include "types/script/scrThread.hpp" +#include "types/script/GtaThread.hpp" +#include "types/script/CGameScriptHandler.hpp" +#include "types/script/CGameScriptId.hpp" namespace YimMenu::Scripts { @@ -30,4 +32,31 @@ namespace YimMenu::Scripts rage::tlsContext::Get()->m_ScriptThreadActive = og_running_in_scrthread; rage::tlsContext::Get()->m_CurrentScriptThread = og_thread; } + + void RunWithSpoofedThreadName(std::uint32_t name, std::function callback) + { + if (auto thread = reinterpret_cast(rage::tlsContext::Get()->m_CurrentScriptThread)) + { + auto hash_1 = thread->m_Context.m_ScriptHash; + auto hash_2 = thread->m_ScriptHash; + auto hash_3 = thread->m_ScriptHash2; + std::optional hash_4; + if (auto handler = thread->m_ScriptHandler) + hash_4 = handler->GetId()->m_Hash; + + thread->m_Context.m_ScriptHash = name; + thread->m_ScriptHash = name; + thread->m_ScriptHash2 = name; + if (hash_4) + thread->m_ScriptHandler->GetId()->m_Hash = name; + + callback(); + + thread->m_Context.m_ScriptHash = hash_1; + thread->m_ScriptHash = hash_2; + thread->m_ScriptHash2 = hash_3; + if (hash_4) + thread->m_ScriptHandler->GetId()->m_Hash = *hash_4; + } + } } \ No newline at end of file diff --git a/src/game/gta/Scripts.hpp b/src/game/gta/Scripts.hpp index 11ff515..278ecea 100644 --- a/src/game/gta/Scripts.hpp +++ b/src/game/gta/Scripts.hpp @@ -10,6 +10,6 @@ namespace rage namespace YimMenu::Scripts { extern rage::scrThread* FindScriptThread(joaat_t hash); - // extern rage::scrProgram* FindScriptProgram(joaat_t hash); extern void RunAsScript(rage::scrThread* thread, std::function callback); + extern void RunWithSpoofedThreadName(std::uint32_t name, std::function callback); // consider using RunAsScript if possible } \ No newline at end of file diff --git a/src/game/hooks/Hooks.hpp b/src/game/hooks/Hooks.hpp index acd53db..9fb68ec 100644 --- a/src/game/hooks/Hooks.hpp +++ b/src/game/hooks/Hooks.hpp @@ -3,6 +3,11 @@ class CNetworkPlayerMgr; class CNetGamePlayer; +namespace rage +{ + class netConnectionManager; + class netEvent; +} namespace YimMenu::Hooks { @@ -10,7 +15,6 @@ namespace YimMenu::Hooks { constexpr auto VMTPresentIdx = 8; constexpr auto VMTResizeBuffersIdx = 13; - constexpr auto VMTSize = 19; extern HRESULT Present(IDXGISwapChain* that, UINT syncInterval, UINT flags); extern HRESULT ResizeBuffers(IDXGISwapChain* that, UINT bufferCount, UINT width, UINT height, DXGI_FORMAT newFormat, UINT swapChainFlags); } diff --git a/src/game/pointers/Pointers.cpp b/src/game/pointers/Pointers.cpp index 3bfb7b9..72abf4e 100644 --- a/src/game/pointers/Pointers.cpp +++ b/src/game/pointers/Pointers.cpp @@ -83,6 +83,11 @@ namespace YimMenu AssignPhysicalIndex = ptr.Sub(0x13).As(); }); + constexpr auto scriptGlobalsPtrn = Pattern<"48 8B 8E B8 00 00 00 48 8D 15 ? ? ? ? 49 89 D8">("ScriptGlobals"); + scanner.Add(scriptGlobalsPtrn, [this](PointerCalculator ptr) { + ScriptGlobals = ptr.Add(7).Add(3).Rip().As(); + }); + if (!scanner.Scan()) { LOG(FATAL) << "Some patterns could not be found, unloading."; diff --git a/src/types/fx/ExplosionType.hpp b/src/types/fx/ExplosionType.hpp new file mode 100644 index 0000000..3cada93 --- /dev/null +++ b/src/types/fx/ExplosionType.hpp @@ -0,0 +1,90 @@ +#pragma once + +enum class ExplosionType +{ + DONTCARE = -1, + GRENADE, + GRENADELAUNCHER, + STICKYBOMB, + MOLOTOV, + ROCKET, + TANKSHELL, + HI_OCTANE, + CAR, + PLANE, + PETROL_PUMP, + BIKE, + DIR_STEAM, + DIR_FLAME, + DIR_WATER_HYDRANT, + DIR_GAS_CANISTER, + BOAT, + SHIP_DESTROY, + TRUCK, + BULLET, + SMOKEGRENADELAUNCHER, + SMOKEGRENADE, + BZGAS, + FLARE, + GAS_CANISTER, + EXTINGUISHER, + PROGRAMMABLEAR, + TRAIN, + BARREL, + PROPANE, + BLIMP, + DIR_FLAME_EXPLODE, + TANKER, + PLANE_ROCKET, + VEHICLE_BULLET, + GAS_TANK, + BIRD_CRAP, + RAILGUN, + BLIMP2, + FIREWORK, + SNOWBALL, + PROXMINE, + VALKYRIE_CANNON, + AIR_DEFENCE, + PIPEBOMB, + VEHICLEMINE, + EXPLOSIVEAMMO, + APCSHELL, + BOMB_CLUSTER, + BOMB_GAS, + BOMB_INCENDIARY, + BOMB_STANDARD, + TORPEDO, + TORPEDO_UNDERWATER, + BOMBUSHKA_CANNON, + BOMB_CLUSTER_SECONDARY, + HUNTER_BARRAGE, + HUNTER_CANNON, + ROGUE_CANNON, + MINE_UNDERWATER, + ORBITAL_CANNON, + BOMB_STANDARD_WIDE, + EXPLOSIVEAMMO_SHOTGUN, + OPPRESSOR2_CANNON, + MORTAR_KINETIC, + VEHICLEMINE_KINETIC, + VEHICLEMINE_EMP, + VEHICLEMINE_SPIKE, + VEHICLEMINE_SLICK, + VEHICLEMINE_TAR, + SCRIPT_DRONE, + RAYGUN, + BURIEDMINE, + SCRIPT_MISSILE, + RCTANK_ROCKET, + BOMB_WATER, + BOMB_WATER_SECONDARY, + _0xF728C4A9, + _0xBAEC056F, + FLASHGRENADE, + STUNGRENADE, + _0x763D3B3B, + SCRIPT_MISSILE_LARGE, + SUBMARINE_BIG, + EMPLAUNCHER_EMP +}; \ No newline at end of file diff --git a/src/types/network/netEvent.hpp b/src/types/network/netEvent.hpp new file mode 100644 index 0000000..2268859 --- /dev/null +++ b/src/types/network/netEvent.hpp @@ -0,0 +1,32 @@ +#pragma once + +namespace rage +{ + class netEvent + { + public: + enum class Type + { + ConnectionRequested = 0, // seems to be identical to rage::netConnection::InFrame + ConnectionError = 2, + ConnectionClosed = 3, + FrameReceived = 4, // rage::netConnection::InFrame + BandwidthExceeded = 6, + OutOfMemory = 7 + }; + + virtual ~netEvent() = default; + + virtual void Destroy() = 0; + virtual Type GetEventType() = 0; + virtual uint32_t _0x18() = 0; + + std::uint32_t m_Timestamp; // 0x0008 + char pad_0008[52]; // 0x000C + std::uint32_t m_MsgId; // 0x0040 + std::uint32_t m_CxnId; // 0x0044 + rage::netEvent* m_This; // 0x0048 + uint32_t m_PeerId; // 0x0050 + }; + static_assert(sizeof(rage::netEvent) == 0x58); +} \ No newline at end of file diff --git a/src/types/script/CGameScriptHandler.hpp b/src/types/script/CGameScriptHandler.hpp new file mode 100644 index 0000000..06b1be6 --- /dev/null +++ b/src/types/script/CGameScriptHandler.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "scriptHandler.hpp" + +class CGameScriptHandler : public rage::scriptHandler +{ +public: + // TODO +}; \ No newline at end of file diff --git a/src/types/script/CGameScriptId.hpp b/src/types/script/CGameScriptId.hpp new file mode 100644 index 0000000..16f5569 --- /dev/null +++ b/src/types/script/CGameScriptId.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "scriptId.hpp" + +class CGameScriptId : public rage::scriptId +{ +public: + std::int32_t m_Timestamp; // 0x30 + std::int32_t m_PositionHash; // 0x34 + std::int32_t m_InstanceId; // 0x38 + std::int32_t m_UniqueId; // 0x3C +}; +static_assert(sizeof(CGameScriptId) == 0x40); \ No newline at end of file diff --git a/src/types/script/globals/GPBD_FM.hpp b/src/types/script/globals/GPBD_FM.hpp index 3029adb..54bc5e1 100644 --- a/src/types/script/globals/GPBD_FM.hpp +++ b/src/types/script/globals/GPBD_FM.hpp @@ -691,5 +691,7 @@ static_assert(sizeof(GPBD_FM_Entry) == 892 * 8); struct GPBD_FM { SCR_ARRAY Entries; + + static GPBD_FM* Get(); }; static_assert(sizeof(GPBD_FM) == 28545 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GPBD_FM_3.hpp b/src/types/script/globals/GPBD_FM_3.hpp index efd2225..2d13991 100644 --- a/src/types/script/globals/GPBD_FM_3.hpp +++ b/src/types/script/globals/GPBD_FM_3.hpp @@ -353,5 +353,7 @@ static_assert(sizeof(GBPD_FM_3_Entry) == 611 * 8); struct GPBD_FM_3 { SCR_ARRAY Entries; + + static GPBD_FM_3* Get(); }; static_assert(sizeof(GPBD_FM_3) == 19553 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GPBD_Kicking.hpp b/src/types/script/globals/GPBD_Kicking.hpp index 86a1c56..d4d0a75 100644 --- a/src/types/script/globals/GPBD_Kicking.hpp +++ b/src/types/script/globals/GPBD_Kicking.hpp @@ -13,5 +13,7 @@ static_assert(sizeof(GPBD_KickingEntry) == 100 * 8); struct GPBD_Kicking { SCR_ARRAY Entries; + + static GPBD_Kicking* Get(); }; static_assert(sizeof(GPBD_Kicking) == 3201 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GPBD_MissionName.hpp b/src/types/script/globals/GPBD_MissionName.hpp index 954a71f..960f719 100644 --- a/src/types/script/globals/GPBD_MissionName.hpp +++ b/src/types/script/globals/GPBD_MissionName.hpp @@ -4,5 +4,7 @@ struct GPBD_MissionName { SCR_ARRAY MissionNames; + + static GPBD_MissionName* Get(); }; static_assert(sizeof(GPBD_MissionName) == 513 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GSBD.hpp b/src/types/script/globals/GSBD.hpp index 88b0361..0309545 100644 --- a/src/types/script/globals/GSBD.hpp +++ b/src/types/script/globals/GSBD.hpp @@ -91,5 +91,7 @@ struct GSBD NETWORK_INDEX IAATurretCameraVehicleId; // used by DDH act 1 uint64_t PAD_1399[97]; SCR_INT CayoPericoStrandedAnimalChoice; + + static GSBD* Get(); }; static_assert(sizeof(GSBD) == 1498 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GSBD_BlockB.hpp b/src/types/script/globals/GSBD_BlockB.hpp index 51a92f5..0cb4c2b 100644 --- a/src/types/script/globals/GSBD_BlockB.hpp +++ b/src/types/script/globals/GSBD_BlockB.hpp @@ -92,5 +92,7 @@ struct GSBD_BlockB SCR_ARRAY CarMeetModShopSlotIndices; SCR_ARRAY CarMeetModShopOccupiedGoons; SCR_ARRAY, 32> CarMeetModShopOccupiedVehicleSlots; + + static GSBD_BlockB* Get(); }; static_assert(sizeof(GSBD_BlockB) == 2156 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GSBD_FM.hpp b/src/types/script/globals/GSBD_FM.hpp index 2af73c5..ec658bd 100644 --- a/src/types/script/globals/GSBD_FM.hpp +++ b/src/types/script/globals/GSBD_FM.hpp @@ -63,5 +63,7 @@ struct GSBD_FM WEAPON_PICKUPS WeaponPickups; BIKER_CONTRACTS_SERVER BikerContracts; SCR_ARRAY DoubleActionCacheLocationRevealed; + + static GSBD_FM* Get(); }; static_assert(sizeof(GSBD_FM) == 648 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GSBD_Kicking.hpp b/src/types/script/globals/GSBD_Kicking.hpp index 31b2441..3d1efbf 100644 --- a/src/types/script/globals/GSBD_Kicking.hpp +++ b/src/types/script/globals/GSBD_Kicking.hpp @@ -4,5 +4,7 @@ struct GSBD_Kicking { SCR_ARRAY KickedPlayers; + + static GSBD_Kicking* Get(); }; static_assert(sizeof(GSBD_Kicking) == 33 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GSBD_PropertyInstances.hpp b/src/types/script/globals/GSBD_PropertyInstances.hpp index ca1e2d9..1e689e4 100644 --- a/src/types/script/globals/GSBD_PropertyInstances.hpp +++ b/src/types/script/globals/GSBD_PropertyInstances.hpp @@ -7,5 +7,7 @@ struct GSBD_PropertyInstances SCR_ARRAY PropertyOwners; uint64_t PAD_0417[14]; // unused SCR_ARRAY PropertyOwnerInstances; + + static GSBD_PropertyInstances* Get(); }; static_assert(sizeof(GSBD_PropertyInstances) == 464 * 8); \ No newline at end of file diff --git a/src/types/script/globals/GlobalPlayerBD.hpp b/src/types/script/globals/GlobalPlayerBD.hpp index f516f3e..cd84eac 100644 --- a/src/types/script/globals/GlobalPlayerBD.hpp +++ b/src/types/script/globals/GlobalPlayerBD.hpp @@ -686,5 +686,7 @@ static_assert(sizeof(GlobalPlayerBDEntry) == 467 * 8); struct GlobalPlayerBD { SCR_ARRAY Entries; + + static GlobalPlayerBD* Get(); }; static_assert(sizeof(GlobalPlayerBD) == 14945 * 8); \ No newline at end of file diff --git a/src/types/script/globals/Globals.cpp b/src/types/script/globals/Globals.cpp new file mode 100644 index 0000000..1060093 --- /dev/null +++ b/src/types/script/globals/Globals.cpp @@ -0,0 +1,32 @@ +#include "GlobalPlayerBD.hpp" +#include "GPBD_FM.hpp" +#include "GPBD_FM_3.hpp" +#include "GPBD_Kicking.hpp" +#include "GPBD_MissionName.hpp" +#include "GSBD.hpp" +#include "GSBD_BlockB.hpp" +#include "GSBD_FM.hpp" +#include "GSBD_Kicking.hpp" +#include "GSBD_PropertyInstances.hpp" +#include "g_AMC_playerBD.hpp" +#include "game/gta/ScriptGlobal.hpp" + +#define DEFINE_GLOBAL_ACCESSOR(str, global) str* str::Get()\ + { \ + auto glb = YimMenu::ScriptGlobal(global); \ + if (!glb.CanAccess()) \ + return nullptr; \ + return glb.As(); \ + } + +DEFINE_GLOBAL_ACCESSOR(GlobalPlayerBD, 2657994); +DEFINE_GLOBAL_ACCESSOR(GPBD_FM, 1845270); +DEFINE_GLOBAL_ACCESSOR(GPBD_FM_3, 1887694); +DEFINE_GLOBAL_ACCESSOR(GPBD_Kicking, 1874328); +DEFINE_GLOBAL_ACCESSOR(GPBD_MissionName, 1873815); +DEFINE_GLOBAL_ACCESSOR(GSBD, 2648917); +DEFINE_GLOBAL_ACCESSOR(GSBD_BlockB, 2650415); +DEFINE_GLOBAL_ACCESSOR(GSBD_FM, 1835557); +DEFINE_GLOBAL_ACCESSOR(GSBD_Kicking, 1877529); +DEFINE_GLOBAL_ACCESSOR(GSBD_PropertyInstances, 1937699); +DEFINE_GLOBAL_ACCESSOR(g_AMC_playerBD, 2699624); \ No newline at end of file diff --git a/src/types/script/globals/g_AMC_playerBD.hpp b/src/types/script/globals/g_AMC_playerBD.hpp index 1f33cd4..8331c79 100644 --- a/src/types/script/globals/g_AMC_playerBD.hpp +++ b/src/types/script/globals/g_AMC_playerBD.hpp @@ -12,5 +12,7 @@ static_assert(sizeof(g_AMC_playerBD_Entry) == 251 * 8); // -> 251 in b812g9 struct g_AMC_playerBD { SCR_ARRAY Entries; + + static g_AMC_playerBD* Get(); }; static_assert(sizeof(g_AMC_playerBD) == 8033 * 8); \ No newline at end of file diff --git a/src/types/script/scriptHandler.hpp b/src/types/script/scriptHandler.hpp new file mode 100644 index 0000000..6253543 --- /dev/null +++ b/src/types/script/scriptHandler.hpp @@ -0,0 +1,31 @@ +#pragma once +#include "scrThread.hpp" +#include "scriptId.hpp" + +#include + +#pragma pack(push, 1) +namespace rage +{ + class scriptHandlerObject; + class scriptHandler + { + + public: + virtual ~scriptHandler() = default; // 0 (0x00) + + virtual bool _0x08() = 0; // 1 (0x08) + + virtual void _0x10() = 0; // 2 (0x10) + + virtual void CleanupObjects() = 0; // 3 (0x18) + + virtual scriptId* _0x20() = 0; // 4 (0x20) + + virtual scriptId* GetId() = 0; // 5 (0x28) + + // TODO more fields + public: + // TODO + }; +} \ No newline at end of file diff --git a/src/types/script/scriptId.hpp b/src/types/script/scriptId.hpp new file mode 100644 index 0000000..4ee44f0 --- /dev/null +++ b/src/types/script/scriptId.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "scriptIdBase.hpp" + +namespace rage +{ + class scriptId : public scriptIdBase + { + public: + std::uint32_t m_Hash; // 0x08 + char m_Name[32]; // 0x0C + }; + static_assert(sizeof(scriptId) == 0x30); +} \ No newline at end of file diff --git a/src/types/script/scriptIdBase.hpp b/src/types/script/scriptIdBase.hpp new file mode 100644 index 0000000..9ac1e47 --- /dev/null +++ b/src/types/script/scriptIdBase.hpp @@ -0,0 +1,57 @@ +#pragma once +#include + +namespace rage +{ + class datBitBuffer; + class netLoggingInterface; + class scrThread; + + class scriptIdBase + { + public: + virtual ~scriptIdBase() = default; // 0 (0x00) + + // Assumes the script thread's identity. + virtual void Reset(scrThread*) {}; // 1 (0x08) + + // Returns whether the hash of the script id is valid. + virtual bool IsValid() { return false; }; // 2 (0x10) + + // Gets the hash of the script id. + virtual std::uint32_t* GetHash(std::uint32_t* out) { return 0; }; // 3 (0x18) + + // Gets an unknown value from the script id. + virtual std::uint32_t* GetUniqueId(std::uint32_t* out) { return 0; }; // 4 (0x20) + + // Gets the name of the script id. This function is not thread-safe and the resulting name must be copied out of the ptr immediately + virtual const char* GetDebugName() { return nullptr; }; // 5 (0x28) + + // Serializes the script id from the buffer. + virtual void Deserialize(datBitBuffer* buffer) {}; // 6 (0x30) + + // Serializes the script id to the buffer. + virtual void Serialize(datBitBuffer* buffer) {}; // 7 (0x38) + + // Calculates some information with the position hash & instance id. + virtual std::uint32_t GetSize() { return 0; }; // 8 (0x40) + + // Calls _0x40 and returns it's value added to another value. + virtual std::uint32_t GetSizeWithHeader() { return 0; }; // 9 (0x48) + + // Logs some information about the script id. + virtual void LogInfo(netLoggingInterface* logger) {}; // 10 (0x50) + + // Copies the information of other to this object. + virtual void CopyData(scriptIdBase* other) {} // 11 (0x58) + + // Returns whether the other script id is equal. + virtual bool operator==(scriptIdBase*) { return false; }; // 12 (0x60) + + // Populates the script name from the hash + virtual void PopulateScriptName() {}; // 13 (0x68) + + // return this->IsValid() && this->m_Hash == other->m_Hash; + virtual bool IsHandlerForSameScript(scriptIdBase* other) { return false; }; // 14 (0x70) + }; +} \ No newline at end of file