diff --git a/src/game/backend/Tunables.cpp b/src/game/backend/Tunables.cpp index 0c6b01f..20c0eeb 100644 --- a/src/game/backend/Tunables.cpp +++ b/src/game/backend/Tunables.cpp @@ -107,7 +107,7 @@ namespace YimMenu TUNABLES_LAUNCH_DATA args; args.Context = 6; // BASE_GLOBALS args.ContentModifier = 27; // MP_FM_RANDOM - if (!BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS("tuneables_processing"_J, &args, SCR_SIZEOF(args), eStackSizes::DEFAULT)) + if (!BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS("tuneables_processing"_J, &args, SCR_SIZEOF(args), static_cast(eStackSizes::DEFAULT))) { LOG(FATAL) << "Failed to start tuneables_processing. Cannot cache tunables."; return; diff --git a/src/game/features/recovery/ClaimSafeEarnings.cpp b/src/game/features/recovery/ClaimSafeEarnings.cpp new file mode 100644 index 0000000..2092a9c --- /dev/null +++ b/src/game/features/recovery/ClaimSafeEarnings.cpp @@ -0,0 +1,82 @@ +#include "core/commands/ListCommand.hpp" +#include "game/backend/Self.hpp" +#include "game/gta/ScriptGlobal.hpp" +#include "game/pointers/Pointers.hpp" +#include "types/script/globals/GPBD_FM.hpp" + +namespace YimMenu::Features +{ + enum class eAppVinewoodMenuSafe + { + NIGHTCLUB, + ARCADE, + AGENCY, + SALVAGE_YARD, + BAIL_OFFICE, + GARMENT_FACTORY + }; + + static std::vector> businessNames = { + {static_cast(eAppVinewoodMenuSafe::NIGHTCLUB), "Nightclub"}, + {static_cast(eAppVinewoodMenuSafe::ARCADE), "Arcade"}, + {static_cast(eAppVinewoodMenuSafe::AGENCY), "Agency"}, + {static_cast(eAppVinewoodMenuSafe::SALVAGE_YARD), "Salvage Yard"}, + {static_cast(eAppVinewoodMenuSafe::BAIL_OFFICE), "Bail Office"}, + {static_cast(eAppVinewoodMenuSafe::GARMENT_FACTORY), "Garment Factory"} + }; + + static ListCommand _SelectedBusiness{"businesssafe", "Business", "Business to claim earning from.", businessNames, 0}; + + class ClaimSafeEarnings : public Command + { + using Command::Command; + + virtual void OnCall() override + { + if (!*Pointers.IsSessionStarted) + return; + + switch (static_cast(_SelectedBusiness.GetState())) + { + case eAppVinewoodMenuSafe::NIGHTCLUB: + { + if (GPBD_FM::Get()->Entries[Self::GetPlayer().GetId()].PropertyData.NightclubData.SafeCashValue > 0) + *ScriptGlobal(2707980).As() = TRUE; + break; + } + case eAppVinewoodMenuSafe::ARCADE: + { + if (GPBD_FM::Get()->Entries[Self::GetPlayer().GetId()].PropertyData.ArcadeData.SafeCashValue > 0) + *ScriptGlobal(2707989).As() = TRUE; + break; + } + case eAppVinewoodMenuSafe::AGENCY: + { + if (GPBD_FM::Get()->Entries[Self::GetPlayer().GetId()].PropertyData.FixerHQData.SafeCashValue > 0) + *ScriptGlobal(2707998).As() = TRUE; + break; + } + case eAppVinewoodMenuSafe::SALVAGE_YARD: + { + if (GPBD_FM::Get()->Entries[Self::GetPlayer().GetId()].PropertyData.SalvageYardData.TotalEarnings > 0) + *ScriptGlobal(2708007).As() = TRUE; + break; + } + case eAppVinewoodMenuSafe::BAIL_OFFICE: + { + if (GPBD_FM::Get()->Entries[Self::GetPlayer().GetId()].PropertyData.BailShopData.SafeCashValue > 0) + *ScriptGlobal(2708016).As() = TRUE; + break; + } + case eAppVinewoodMenuSafe::GARMENT_FACTORY: + { + if (GPBD_FM::Get()->Entries[Self::GetPlayer().GetId()].PropertyData.HackerDenData.SafeCashValue > 0) + *ScriptGlobal(2708025).As() = TRUE; + break; + } + } + } + }; + + static ClaimSafeEarnings _ClaimSafeEarnings{"claimsafeearnings", "Claim Safe Earnings", "Claims your safe earnings from the selected business."}; +} \ No newline at end of file diff --git a/src/game/features/self/OpenWardrobe.cpp b/src/game/features/self/OpenWardrobe.cpp index 7cbb34c..e5b705c 100644 --- a/src/game/features/self/OpenWardrobe.cpp +++ b/src/game/features/self/OpenWardrobe.cpp @@ -4,7 +4,6 @@ #include "game/backend/Self.hpp" #include "game/backend/ScriptPatches.hpp" #include "game/backend/NativeHooks.hpp" -#include "game/gta/data/StackSizes.hpp" #include "game/gta/Natives.hpp" #include "game/gta/Scripts.hpp" #include "game/gta/ScriptLocal.hpp" @@ -18,6 +17,7 @@ namespace YimMenu::Features SCR_VEC3 Position; SCR_FLOAT Heading; }; + static_assert(sizeof(WARDROBE_LAUNCH_DATA) == 5 * 8); static bool startedByUs{}; static ScriptPatch shouldCleanupWardrobePatch{}; @@ -34,23 +34,17 @@ namespace YimMenu::Features virtual void OnCall() override { - if (!*Pointers.IsSessionStarted || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("wardrobe_mp"_J) > 0) + if (!*Pointers.IsSessionStarted || Scripts::IsScriptActive("wardrobe_mp"_J)) { Notifications::Show("Wardrobe", "Not safe to open the wardrobe at the moment.", NotificationType::Error); return; } - while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED("wardrobe_mp"_J)) - { - SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH("wardrobe_mp"_J); - ScriptMgr::Yield(); - } - WARDROBE_LAUNCH_DATA launchData; launchData.Type = 7; launchData.Position = Self::GetPed().GetPosition(); launchData.Heading = Self::GetPed().GetHeading(); - if (!BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS("wardrobe_mp"_J, &launchData, SCR_SIZEOF(launchData), eStackSizes::SHOP)) + if (!Scripts::StartScript("wardrobe_mp"_J, eStackSizes::SHOP, &launchData, SCR_SIZEOF(launchData))) { Notifications::Show("Wardrobe", "Failed to open the wardrobe.", NotificationType::Error); return; @@ -92,9 +86,10 @@ namespace YimMenu::Features } isItemLockedByStatPatch3->Enable(); - NativeHooks::AddHook("wardrobe_mp"_J, NativeIndex::GET_DISTANCE_BETWEEN_COORDS, &GetDistanceBetweenCoordsHook); - - SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED("wardrobe_mp"_J); + static bool initNativeHook = [] { + NativeHooks::AddHook("wardrobe_mp"_J, NativeIndex::GET_DISTANCE_BETWEEN_COORDS, &GetDistanceBetweenCoordsHook); + return true; + }(); startedByUs = true; } diff --git a/src/game/features/vehicle/CallMechanic.cpp b/src/game/features/vehicle/CallMechanic.cpp index c90c38c..340f065 100644 --- a/src/game/features/vehicle/CallMechanic.cpp +++ b/src/game/features/vehicle/CallMechanic.cpp @@ -2,11 +2,10 @@ #include "core/backend/ScriptMgr.hpp" #include "core/frontend/Notifications.hpp" #include "game/backend/Self.hpp" -#include "game/gta/data/StackSizes.hpp" -#include "game/gta/Natives.hpp" #include "game/gta/Scripts.hpp" #include "game/gta/ScriptLocal.hpp" #include "game/gta/ScriptGlobal.hpp" +#include "game/pointers/Pointers.hpp" #include "types/script/Timer.hpp" namespace YimMenu::Features @@ -17,7 +16,7 @@ namespace YimMenu::Features virtual void OnCall() override { - if (!*Pointers.IsSessionStarted || SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("AM_CONTACT_REQUESTS"_J) > 0) + if (!*Pointers.IsSessionStarted || Scripts::IsScriptActive("AM_CONTACT_REQUESTS"_J)) { Notifications::Show("Mechanic", "Not safe to call the mechanic at the moment.", NotificationType::Error); return; @@ -31,14 +30,8 @@ namespace YimMenu::Features *data.At(3).At(1).As() = 89; *data.At(2).As() = "AM_CONTACT_REQUESTS"_J; - while (!SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED("AM_CONTACT_REQUESTS"_J)) - { - SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH("AM_CONTACT_REQUESTS"_J); - ScriptMgr::Yield(); - } - auto args = data.At(3).As(); - if (auto id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS("AM_CONTACT_REQUESTS"_J, args, 21, eStackSizes::SCRIPT_XML)) + if (auto id = Scripts::StartScript("AM_CONTACT_REQUESTS"_J, eStackSizes::SCRIPT_XML, args, 21)) { if (auto thread = Scripts::FindScriptThreadByID(id)) { @@ -50,8 +43,6 @@ namespace YimMenu::Features { Notifications::Show("Mechanic", "Failed to call the mechanic.", NotificationType::Error); } - - SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED("AM_CONTACT_REQUESTS"_J); } } }; diff --git a/src/game/features/vehicle/SavePersonalVehicle.cpp b/src/game/features/vehicle/SavePersonalVehicle.cpp index a4c5705..4e2fc29 100644 --- a/src/game/features/vehicle/SavePersonalVehicle.cpp +++ b/src/game/features/vehicle/SavePersonalVehicle.cpp @@ -1,14 +1,14 @@ #include "SavePersonalVehicle.hpp" #include "core/commands/Command.hpp" #include "core/backend/ScriptMgr.hpp" -#include "game/backend/Self.hpp" #include "core/frontend/Notifications.hpp" -#include "game/gta/data/StackSizes.hpp" -#include "game/gta/Natives.hpp" +#include "game/backend/Self.hpp" #include "game/gta/Scripts.hpp" #include "game/gta/ScriptFunction.hpp" #include "game/gta/ScriptLocal.hpp" +#include "game/pointers/Pointers.hpp" #include "types/script/locals/VehicleRewardData.hpp" +#include "types/script/globals/FreemodeGeneral.hpp" namespace YimMenu::Features { @@ -28,37 +28,25 @@ namespace YimMenu::Features m_Thread->m_Context.m_State = rage::scrThread::State::KILLED; m_StartedByUs = false; } - m_Thread = nullptr; + m_Thread = nullptr; m_ShouldRunScript = false; continue; } - if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH("AM_MP_VEHICLE_REWARD"_J) == 0) - { - SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH("AM_MP_VEHICLE_REWARD"_J); - if (SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED("AM_MP_VEHICLE_REWARD"_J)) - { - int id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH("AM_MP_VEHICLE_REWARD"_J, eStackSizes::FRIEND); - m_Thread = Scripts::FindScriptThreadByID(id); - if (m_Thread) - m_Thread->m_Context.m_State = rage::scrThread::State::PAUSED; - SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED("AM_MP_VEHICLE_REWARD"_J); - m_StartedByUs = true; - } - else - { - continue; - } - } - else - { - m_Thread = Scripts::FindScriptThread("AM_MP_VEHICLE_REWARD"_J); - } - if (!m_Thread) { - m_ShouldRunScript = false; - continue; + int id = Scripts::StartScript("AM_MP_VEHICLE_REWARD"_J, eStackSizes::FRIEND); + m_Thread = Scripts::FindScriptThreadByID(id); + if (m_Thread) + { + m_Thread->m_Context.m_State = rage::scrThread::State::PAUSED; + m_StartedByUs = true; + } + else + { + m_ShouldRunScript = false; + continue; + } } if (auto VehicleRewardData = VEHICLE_REWARD_DATA::Get(m_Thread)) @@ -111,6 +99,12 @@ namespace YimMenu::Features return; } + if (Self::GetVehicle().GetHandle() == FreemodeGeneral::Get()->PersonalVehicleIndex) + { + Notifications::Show("Save Personal Vehicle", "This vehicle is already a personal vehicle.", NotificationType::Error); + return; + } + SavePersonalVehicle::SetShouldRunScript(true); } }; diff --git a/src/game/frontend/submenus/Debug/Scripts.cpp b/src/game/frontend/submenus/Debug/Scripts.cpp index 58a773d..cce6e85 100644 --- a/src/game/frontend/submenus/Debug/Scripts.cpp +++ b/src/game/frontend/submenus/Debug/Scripts.cpp @@ -15,6 +15,37 @@ namespace YimMenu::Submenus { + static constexpr std::pair stackSizes[] = { + {"MICRO", static_cast(eStackSizes::MICRO)}, + {"MINI", static_cast(eStackSizes::MINI)}, + {"DEFAULT", static_cast(eStackSizes::DEFAULT)}, + {"SPECIAL_ABILITY", static_cast(eStackSizes::SPECIAL_ABILITY)}, + {"FRIEND", static_cast(eStackSizes::FRIEND)}, + {"SHOP", static_cast(eStackSizes::SHOP)}, + {"CELLPHONE", static_cast(eStackSizes::CELLPHONE)}, + {"VEHICLE_SPAWN", static_cast(eStackSizes::VEHICLE_SPAWN)}, + {"CAR_MOD_SHOP", static_cast(eStackSizes::CAR_MOD_SHOP)}, + {"PAUSE_MENU_SCRIPT", static_cast(eStackSizes::PAUSE_MENU_SCRIPT)}, + {"APP_INTERNET", static_cast(eStackSizes::APP_INTERNET)}, + {"MULTIPLAYER_MISSION", static_cast(eStackSizes::MULTIPLAYER_MISSION)}, + {"CONTACTS_APP", static_cast(eStackSizes::CONTACTS_APP)}, + {"INTERACTION_MENU", static_cast(eStackSizes::INTERACTION_MENU)}, + {"SCRIPT_XML", static_cast(eStackSizes::SCRIPT_XML)}, + {"PROPERTY_INT", static_cast(eStackSizes::PROPERTY_INT)}, + {"ACTIVITY_CREATOR_INT", static_cast(eStackSizes::ACTIVITY_CREATOR_INT)}, + {"SMPL_INTERIOR", static_cast(eStackSizes::SMPL_INTERIOR)}, + {"WAREHOUSE", static_cast(eStackSizes::WAREHOUSE)}, + {"IE_DELIVERY", static_cast(eStackSizes::IE_DELIVERY)}, + {"SHOP_CONTROLLER", static_cast(eStackSizes::SHOP_CONTROLLER)}, + {"AM_MP_YACHT", static_cast(eStackSizes::AM_MP_YACHT)}, + {"INGAMEHUD", static_cast(eStackSizes::INGAMEHUD)}, + {"TRANSITION", static_cast(eStackSizes::TRANSITION)}, + {"FMMC_LAUNCHER", static_cast(eStackSizes::FMMC_LAUNCHER)}, + {"MULTIPLAYER_FREEMODE", static_cast(eStackSizes::MULTIPLAYER_FREEMODE)}, + {"MISSION", static_cast(eStackSizes::MISSION)}, + {"MP_LAUNCH_SCRIPT", static_cast(eStackSizes::MP_LAUNCH_SCRIPT)} + }; + std::shared_ptr BuildScriptsMenu() { auto scripts = std::make_unique("Scripts"); diff --git a/src/game/frontend/submenus/Recovery.cpp b/src/game/frontend/submenus/Recovery.cpp index 600ec02..1e9daf8 100644 --- a/src/game/frontend/submenus/Recovery.cpp +++ b/src/game/frontend/submenus/Recovery.cpp @@ -9,24 +9,31 @@ namespace YimMenu::Submenus Recovery::Recovery() : Submenu::Submenu("Recovery") { - auto missions = std::make_shared("Missions"); - auto casino = std::make_shared("Casino"); + auto missions = std::make_shared("Missions"); + auto businesses = std::make_shared("Businesses"); + auto casino = std::make_shared("Casino"); - auto generalGroup = std::make_shared("General"); - auto casinoGroup = std::make_shared("CasinoRigSlotMachines"); + auto generalGroup = std::make_shared("General"); + auto businessGroup = std::make_shared("General"); + auto casinoGroup = std::make_shared("CasinoRigSlotMachines"); generalGroup->AddItem(std::make_shared("playallmissionssolo"_J)); generalGroup->AddItem(std::make_shared("forcelaunchheist"_J)); generalGroup->AddItem(std::make_shared("rpmultiplierinput"_J)); generalGroup->AddItem(std::make_shared("rpmultiplier"_J)); + + businessGroup->AddItem(std::make_shared("businesssafe"_J)); + businessGroup->AddItem(std::make_shared("claimsafeearnings"_J)); casinoGroup->AddItem(std::make_shared("casinomanipulaterigslotmachines"_J)); missions->AddItem(generalGroup); + businesses->AddItem(businessGroup); casino->AddItem(casinoGroup); AddCategory(std::move(missions)); + AddCategory(std::move(businesses)); AddCategory(std::move(casino)); AddCategory(BuildStatEditorMenu()); AddCategory(BuildTransactionsMenu()); diff --git a/src/game/gta/Scripts.cpp b/src/game/gta/Scripts.cpp index 7baaf34..6168352 100644 --- a/src/game/gta/Scripts.cpp +++ b/src/game/gta/Scripts.cpp @@ -1,4 +1,5 @@ #include "Scripts.hpp" +#include "core/backend/ScriptMgr.hpp" #include "game/pointers/Pointers.hpp" #include "types/rage/atArray.hpp" #include "types/rage/tlsContext.hpp" @@ -8,6 +9,7 @@ #include "types/script/CGameScriptHandlerNetComponent.hpp" #include "types/script/CGameScriptId.hpp" #include "types/script/globals/GlobalPlayerBD.hpp" +#include "game/gta/Natives.hpp" #include "game/gta/Packet.hpp" #include "game/backend/Players.hpp" #include "game/backend/Self.hpp" @@ -15,6 +17,45 @@ namespace YimMenu::Scripts { + int StartScript(joaat_t hash, eStackSizes stackSize, void* args, int argCount) + { + if (!SCRIPT::DOES_SCRIPT_WITH_NAME_HASH_EXIST(hash)) + return 0; + + if (SCRIPT::GET_NUMBER_OF_THREADS_RUNNING_THE_SCRIPT_WITH_THIS_HASH(hash) > 0) + return FindScriptThread(hash)->m_Context.m_ThreadId; + + for (int i = 0; !SCRIPT::HAS_SCRIPT_WITH_NAME_HASH_LOADED(hash); i++) + { + SCRIPT::REQUEST_SCRIPT_WITH_NAME_HASH(hash); + ScriptMgr::Yield(); + + if (i > 30) + return 0; + } + + int id = 0; + if (args) + { + id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH_AND_ARGS(hash, args, argCount, static_cast(stackSize)); + } + else + { + id = BUILTIN::START_NEW_SCRIPT_WITH_NAME_HASH(hash, static_cast(stackSize)); + } + + SCRIPT::SET_SCRIPT_WITH_NAME_HASH_AS_NO_LONGER_NEEDED(hash); + return id; + } + + bool IsScriptActive(joaat_t hash) + { + if (auto program = FindScriptProgram(hash)) + return (program->m_RefCount - 1) > 0; + + return false; + } + rage::scrThread* FindScriptThread(joaat_t hash) { for (auto& thread : *Pointers.ScriptThreads) diff --git a/src/game/gta/Scripts.hpp b/src/game/gta/Scripts.hpp index 1bc2499..366c358 100644 --- a/src/game/gta/Scripts.hpp +++ b/src/game/gta/Scripts.hpp @@ -1,5 +1,6 @@ #pragma once #include "core/util/Joaat.hpp" +#include "game/gta/data/StackSizes.hpp" namespace rage { @@ -11,6 +12,8 @@ class SimplePattern; namespace YimMenu::Scripts { + extern int StartScript(joaat_t hash, eStackSizes stackSize = eStackSizes::DEFAULT, void* args = nullptr, int argCount = 0); + extern bool IsScriptActive(joaat_t hash); extern rage::scrThread* FindScriptThread(joaat_t hash); extern rage::scrThread* FindScriptThreadByID(std::uint32_t id); extern rage::scrProgram* FindScriptProgram(joaat_t hash); diff --git a/src/game/gta/Stats.cpp b/src/game/gta/Stats.cpp index f37490f..8d0cd44 100644 --- a/src/game/gta/Stats.cpp +++ b/src/game/gta/Stats.cpp @@ -1,18 +1,15 @@ #include "Stats.hpp" #include "game/gta/Natives.hpp" -namespace +namespace YimMenu::Stats { - void ConvertMPX(std::string& statName) + static void ConvertMPX(std::string& statName) { std::transform(statName.begin(), statName.end(), statName.begin(), ::tolower); if (statName.substr(0, 3) == "mpx") - statName[2] = YimMenu::Stats::GetCharIndex() + '0'; + statName[2] = GetCharIndex() + '0'; } -} -namespace YimMenu::Stats -{ int GetCharIndex() { int index{}; @@ -41,7 +38,7 @@ namespace YimMenu::Stats void SetDate(std::string statName, Date* value) { ConvertMPX(statName); - STATS::STAT_SET_DATE(Joaat(statName), value, sizeof(Date) / 8, TRUE); + STATS::STAT_SET_DATE(Joaat(statName), value, SCR_SIZEOF(Date), TRUE); } void SetString(std::string statName, const char* value) @@ -78,7 +75,7 @@ namespace YimMenu::Stats { Date value{}; ConvertMPX(statName); - STATS::STAT_GET_DATE(Joaat(statName), &value, sizeof(Date) / 8, -1); + STATS::STAT_GET_DATE(Joaat(statName), &value, SCR_SIZEOF(Date), -1); return value; } diff --git a/src/game/gta/Stats.hpp b/src/game/gta/Stats.hpp index 8e5035b..92e493a 100644 --- a/src/game/gta/Stats.hpp +++ b/src/game/gta/Stats.hpp @@ -1,13 +1,9 @@ #pragma once #include "core/util/Joaat.hpp" +#include "types/script/types.hpp" namespace YimMenu::Stats { - struct Date - { - alignas(8) int Year, Month, Day, Hour, Minute, Second, Millisecond; - }; - extern int GetCharIndex(); extern void SetInt(std::string statName, int value); diff --git a/src/game/gta/data/StackSizes.hpp b/src/game/gta/data/StackSizes.hpp index 3272b25..379406f 100644 --- a/src/game/gta/data/StackSizes.hpp +++ b/src/game/gta/data/StackSizes.hpp @@ -2,7 +2,7 @@ namespace YimMenu { - enum eStackSizes + enum class eStackSizes { MICRO = 128, MINI = 512, @@ -33,35 +33,4 @@ namespace YimMenu MISSION = 63500, MP_LAUNCH_SCRIPT = 34750 }; - - static constexpr std::pair stackSizes[] = { - {"MICRO", MICRO}, - {"MINI", MINI}, - {"DEFAULT", DEFAULT}, - {"SPECIAL_ABILITY", SPECIAL_ABILITY}, - {"FRIEND", FRIEND}, - {"SHOP", SHOP}, - {"CELLPHONE", CELLPHONE}, - {"VEHICLE_SPAWN", VEHICLE_SPAWN}, - {"CAR_MOD_SHOP", CAR_MOD_SHOP}, - {"PAUSE_MENU_SCRIPT", PAUSE_MENU_SCRIPT}, - {"APP_INTERNET", APP_INTERNET}, - {"MULTIPLAYER_MISSION", MULTIPLAYER_MISSION}, - {"CONTACTS_APP", CONTACTS_APP}, - {"INTERACTION_MENU", INTERACTION_MENU}, - {"SCRIPT_XML", SCRIPT_XML}, - {"PROPERTY_INT", PROPERTY_INT}, - {"ACTIVITY_CREATOR_INT", ACTIVITY_CREATOR_INT}, - {"SMPL_INTERIOR", SMPL_INTERIOR}, - {"WAREHOUSE", WAREHOUSE}, - {"IE_DELIVERY", IE_DELIVERY}, - {"SHOP_CONTROLLER", SHOP_CONTROLLER}, - {"AM_MP_YACHT", AM_MP_YACHT}, - {"INGAMEHUD", INGAMEHUD}, - {"TRANSITION", TRANSITION}, - {"FMMC_LAUNCHER", FMMC_LAUNCHER}, - {"MULTIPLAYER_FREEMODE", MULTIPLAYER_FREEMODE}, - {"MISSION", MISSION}, - {"MP_LAUNCH_SCRIPT", MP_LAUNCH_SCRIPT} - }; } \ No newline at end of file diff --git a/src/types/script/globals/FreemodeGeneral.hpp b/src/types/script/globals/FreemodeGeneral.hpp new file mode 100644 index 0000000..c6f77a8 --- /dev/null +++ b/src/types/script/globals/FreemodeGeneral.hpp @@ -0,0 +1,69 @@ +#pragma once +#include "types/script/types.hpp" +#include "types/script/Timer.hpp" +#include "types/script/globals/GSBD_BlockB.hpp" + +enum class eDealerPremiumProducts +{ + COKE = 2, + METH = 3, + WEED = 4, + ACID = 7 +}; + +struct STREET_DEALER_DATA +{ + SCR_INT Location; // 0 + alignas(8) eDealerPremiumProducts PremiumProduct; // 1 (https://github.com/ShinyWasabi/GTAO-Bot/blob/8394e090afa584938c8e9a63a55b22e2803a51e0/src/modules/street_dealers.js#L76) + SCR_INT CokePrice; // 2 + SCR_INT MethPrice; // 3 + SCR_INT WeedPrice; // 4 + SCR_INT AcidPrice; // 5 + SCR_INT UNK_0006; // 6 +}; +static_assert(sizeof(STREET_DEALER_DATA) == 7 * 8); + +struct STREET_DEALERS +{ + SCR_ARRAY Dealers; // 0 + SCR_INT ClosestDealerLocation; // 22 + SCR_INT ClosetsDealerIndex; // 23 +}; +static_assert(sizeof(STREET_DEALERS) == 24 * 8); + +struct DAILY_RESET_DATA +{ + TIMER Timer; // 0 + SCR_INT ResetDurationMs; // 1 (86400000ms = 24 hours) + SCR_INT Seed; // 2 +}; +static_assert(sizeof(DAILY_RESET_DATA) == 4 * 8); + +struct FREEMODE_DELIVERY_DATA +{ + SCR_INT Flags; // 0 + SCR_INT TransactionStatus; // 1 + BLIP_INDEX Blip; // 2 + SCR_INT Type; // 3 (this seems to be the same as DeliverableHash, at least for exotic exports) + SCR_INT FMMCType; // 4 + DELIVERABLE_ID Id; // 5 + GAMER_HANDLE GamerHandle; // 7 + TIMER Timer; // 20 + SCR_HASH DeliverableHash; // 22 + SCR_BOOL Refresh; // 23 (needs more testing) +}; +static_assert(sizeof(FREEMODE_DELIVERY_DATA) == 24 * 8); + +struct FreemodeGeneral +{ + uint64_t PAD_0000[301]; + VEHICLE_INDEX PersonalVehicleIndex; // 301 + uint64_t PAD_0302[6551]; + STREET_DEALERS StreetDealers; // 6853 + uint64_t PAD_6877[57]; + DAILY_RESET_DATA DailyReset; // 6934 + FREEMODE_DELIVERY_DATA DeliveryData; // 6938 + + static FreemodeGeneral* Get(); +}; +//static_assert(sizeof(FreemodeGeneral) == 7224 * 8); \ 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 54bc5e1..d2e30f7 100644 --- a/src/types/script/globals/GPBD_FM.hpp +++ b/src/types/script/globals/GPBD_FM.hpp @@ -381,8 +381,8 @@ struct ARCADE_DATA SCR_INT AppearanceBitset; SCR_INT AppearanceBitset2; SCR_INT AppearanceBitset3; + SCR_INT UNK_0004; SCR_INT SafeCashValue; - SCR_INT PAD_0005; // unused }; static_assert(sizeof(ARCADE_DATA) == 6 * 8); @@ -459,7 +459,9 @@ static_assert(sizeof(SALVAGE_YARD_DATA) == 7 * 8); struct BAIL_SHOP_DATA { SCR_INT Index; - uint64_t PAD_0001[11]; // a field was removed in b3407 + SCR_INT StyleFlags; + SCR_INT SafeCashValue; + uint64_t PAD_0001[9]; // a field was removed in b3407 }; static_assert(sizeof(BAIL_SHOP_DATA) == 12 * 8); diff --git a/src/types/script/globals/Globals.cpp b/src/types/script/globals/Globals.cpp index c9c75bb..63f3a4d 100644 --- a/src/types/script/globals/Globals.cpp +++ b/src/types/script/globals/Globals.cpp @@ -13,6 +13,8 @@ #include "GlobalPlayerBD.hpp" #include "g_AMC_playerBD.hpp" #include "MPSV.hpp" +#include "g_SavedMPGlobals.hpp" +#include "FreemodeGeneral.hpp" #include "game/gta/ScriptGlobal.hpp" #define DEFINE_GLOBAL_ACCESSOR(str, global) \ @@ -38,4 +40,6 @@ DEFINE_GLOBAL_ACCESSOR(GSBD_Kicking, 1877529); DEFINE_GLOBAL_ACCESSOR(GSBD_PropertyInstances, 1937699); DEFINE_GLOBAL_ACCESSOR(g_AMC_playerBD, 2699624); DEFINE_GLOBAL_ACCESSOR(GSBD_RandomEvents, 1882524); -DEFINE_GLOBAL_ACCESSOR(MPSV, 1586543); // purposely +1 \ No newline at end of file +DEFINE_GLOBAL_ACCESSOR(MPSV, 1586543); +DEFINE_GLOBAL_ACCESSOR(g_SavedMPGlobals, 2359296); +DEFINE_GLOBAL_ACCESSOR(FreemodeGeneral, 2739945); \ No newline at end of file diff --git a/src/types/script/globals/g_SavedMPGlobals.hpp b/src/types/script/globals/g_SavedMPGlobals.hpp new file mode 100644 index 0000000..edba637 --- /dev/null +++ b/src/types/script/globals/g_SavedMPGlobals.hpp @@ -0,0 +1,256 @@ +#pragma once +#include "types/script/types.hpp" + +// All the names can be found in the startup script + +struct MP_PROPERTY_SAVED +{ + SCR_BOOL TVOn; // 0 + SCR_INT TVChannelId; // 1 + SCR_BOOL PenthouseTVOn; // 2 + SCR_INT PenthouseTVChannelId; // 3 + SCR_BOOL MediaRoomTVOn; // 4 + SCR_INT MediaRoomTVChannelId; // 5 + SCR_ARRAY RadioOnId; // 6 + SCR_ARRAY RadioStationId; // 7 + SCR_BOOL GarageTVOn; // 12 + SCR_INT GarageTVChannelId; // 13 + SCR_BOOL GarageRadioOn; // 14 + SCR_INT GarageRadioStationId; // 15 + SCR_INT NumberTimesSmoked; // 16 + SCR_INT NumberTimesDrank; // 17 + SCR_INT NumberTimesStrippers; // 18 + SCR_INT NumberTimesSmokedSecond; // 19 + SCR_INT NumberTimesDrankSecond; // 20 + SCR_INT NumberTimesStrippersSecond; // 21 + SCR_INT NumberTimesSmoked3; // 22 + SCR_INT NumberTimesDrank3; // 23 + SCR_INT NumberTimesStrippers3; // 24 + SCR_INT NumberTimesSmoked4; // 25 + SCR_INT NumberTimesDrank4; // 26 + SCR_INT NumberTimesStrippers4; // 27 + SCR_INT NumberTimesSmoked5; // 28 + SCR_INT NumberTimesDrank5; // 29 + SCR_INT NumberTimesStrippers5; // 30 + SCR_INT NumberTimesSmokedYatch; // 31 + SCR_INT NumberTimesDrankYatch; // 32 + SCR_INT NumberTimesStrippersYatch; // 33 + SCR_INT DateLastCleanedApartment; // 34 + SCR_INT ShowersTaken; // 35 + SCR_ARRAY PropDrinks; // 36 + SCR_ARRAY PropSmokes; // 59 + SCR_ARRAY PropStrippers; // 82 + SCR_ARRAY PropNamedVehs; // 105 +}; +static_assert(sizeof(MP_PROPERTY_SAVED) == 586 * 8); + +struct CAR_APP_ORDER +{ + // field 0 to 40 actually seems to be a struct (MISC::START_SAVE_STRUCT_WITH_SIZE(panParam0, 41, sParam1)) + SCR_INT Model; // 0 + SCR_INT ColourId1; // 1 + SCR_INT ColourId2; // 2 + SCR_INT Colour1Group; // 3 + SCR_INT Colour2Group; // 4 + SCR_INT WindowTint; // 5 + SCR_INT TyreSmokeR; // 6 + SCR_INT TyreSmokeG; // 7 + SCR_INT TyreSmokeB; // 8 + SCR_INT Engine; // 9 + SCR_INT Brakes; // 10 + SCR_INT Wheels; // 11 + SCR_INT WheelType; // 12 + SCR_INT Exhaust; // 13 + SCR_INT Suspension; // 14 + SCR_INT Armour; // 15 + SCR_INT Horn; // 16 + SCR_INT Lights; // 17 + SCR_BOOL BulletProofTyres; // 18 + SCR_INT Turbo; // 19 + SCR_INT TyreSmoke; // 20 + TEXT_LABEL_15 PlateText; // 21 + SCR_INT PlateBack; // 25 + SCR_INT UId; // 26 + SCR_INT Cost; // 27 + TEXT_LABEL_15 PlateTextPending; // 28 + SCR_INT PlateBackPending; // 32 + SCR_BOOL ProcessOrder; // 33 + SCR_BOOL OrderForPlayerVehicle; // 34 + SCR_BOOL OrderReceivedOnBoot; // 35 + SCR_BOOL OrderPending; // 36 + SCR_BOOL CheckPlateProfanity; // 37 + SCR_BOOL SCProfanityFailed; // 38 + SCR_BOOL SOrderFailedFunds; // 39 + SCR_BOOL OrderPaidFor; // 40 + SCR_ARRAY CarHidden; // 41 + SCR_BOOL UpdateMods; // 52 + SCR_BOOL MultiplayerDataWiped; // 53 + SCR_BOOL DeleteCarData; // 54 + SCR_BOOL CarAppPlateSet; // 55 + TEXT_LABEL_15 CarAppPlateText; // 56 + SCR_INT CarAppPlateBack; // 60 + SCR_INT OrderCount; // 61 + SCR_INT OrderVehicle; // 62 + SCR_ARRAY SavedVehSlot; // 63 + SCR_ARRAY SavedVehPrio; // 74 + SCR_INT LastUsed; // 85 + SCR_INT NewUsed; // 86 + SCR_BOOL SetupInit; // 87 +}; +static_assert(sizeof(CAR_APP_ORDER) == 88 * 8); + +struct DAILY_OBJECTIVES +{ + SCR_INT Objective; // 0 + SCR_BOOL Completed; // 1 + SCR_INT Initial; // 2 +}; +static_assert(sizeof(DAILY_OBJECTIVES) == 3 * 8); + +struct MP_GENERAL_SAVED +{ + SCR_INT CashGivenTotal; // 0 + SCR_INT CashGivenTime; // 1 + SCR_INT LastSavedCar; // 2 + SCR_INT CurrentPropValue; // 3 + SCR_INT WheelieTimer; // 4 + SCR_INT WheelieUpdates; // 5 + SCR_INT WheelieTime; // 6 + SCR_BOOL GrabTime; // 7 + SCR_INT LastSoldVehicleTime; // 8 + SCR_INT LastTimePlayed; // 9 + SCR_INT SaveCoupons; // 10 + SCR_INT NewVehPurchased; // 11 + SCR_INT LastBruciePillReminder; // 12 + SCR_INT LastSecVanReminder; // 13 + SCR_INT LastBountyReminder; // 14 + SCR_INT LastParaReminder; // 15 + SCR_INT LastCrateDropReminder; // 16 + SCR_INT LastGangAttackReminder; // 17 + SCR_INT LastImpExpReminder; // 18 + SCR_INT LastInsuranceReminder; // 19 + SCR_INT LastSurvivalReminder; // 20 + SCR_INT LastBikerBackupReminder; // 21 + SCR_INT LastVagosBackupReminder; // 22 + SCR_INT LastLesterVehReminder; // 23 + SCR_INT LastPersonalVehDeliveryReminder; // 24 + SCR_INT LastPegasusVehicleReminder; // 25 + SCR_INT LastMerryweatherReminder; // 26 + SCR_INT LastLesterHelpReminder; // 27 + SCR_INT LastLesterReqJobReminder; // 28 + SCR_INT LastGeraldReqJobReminder; // 29 + SCR_INT LastSimeonReqJobReminder; // 30 + SCR_INT LastMartinReqJobReminder; // 31 + SCR_INT LastRonReqJobReminder; // 32 + SCR_INT RecentlyPassedMissionBitset; // 33 + SCR_INT RecentlyPassedMissionTime; // 34 + SCR_INT LastImportExportDelTime; // 35 + SCR_INT LastImportExportListTime; // 36 + SCR_INT MyLastImportExportListDay; // 37 + SCR_INT VehicleWebsiteReminderTime; // 38 + SCR_BOOL DefaultClothesSet; // 39 + SCR_ARRAY Clothes; // 40 + SCR_ARRAY Carmods; // 47 + SCR_INT LastCrewCharWasIn; // 1272 + SCR_INT StripperUnlockedBS; // 1273 + SCR_INT GeneralBS; // 1274 + SCR_INT CarsModifiedTimeStamp; // 1275 + SCR_ARRAY GolfLongestDriveHole; // 1276 + SCR_ARRAY GolfLongestPuttHole; // 1286 + SCR_INT GolfBestRound; // 1296 + SCR_FLOAT GolfLongestDrive; // 1297 + SCR_FLOAT GolfLongestPutt; // 1298 + SCR_INT ShareLJCashTotal; // 1299 + SCR_INT ShareLJCashTime; // 1300 + SCR_INT ReceiveLJCashTotal; // 1301 + SCR_INT ReceiveLJCashTime; // 1302 + SCR_INT LastAccProp; // 1303 + SCR_INT Multi1PropVal; // 1304 + SCR_ARRAY PropAryVal; // 1305 + SCR_INT LastAccSmplInt; // 1337 + SCR_INT KrPatchUpdate; // 1338 + SCR_ARRAY OutfitCompDraw; // 1339 + SCR_ARRAY OutfitCompTex; // 1613 + SCR_ARRAY OutfitPropID; // 1887 + SCR_ARRAY OutfitPropTex; // 2098 + SCR_ARRAY OutfitStored; // 2309 + SCR_ARRAY OutfitTatCrewA; // 2331 + SCR_ARRAY OutfitTatCrewB; // 2353 + SCR_ARRAY OutfitTatCrewC; // 2375 + SCR_ARRAY OutfitTatCrewD; // 2397 + SCR_ARRAY OutfitTatCrewE; // 2419 + SCR_ARRAY OutfitTatCrewF; // 2441 + SCR_ARRAY OutfitName; // 2463 + SCR_ARRAY OutfitShirt; // 2632 + SCR_ARRAY LastJobGamer; // 2654 + SCR_ARRAY DLCMods; // 2694 + SCR_ARRAY DLCSuperMods; // 3613 + SCR_BOOL DOCompletedObjectives; // 4240 + SCR_BOOL DOLoggedInToday; // 4241 + SCR_INT DOXValue; // 4242 + SCR_INT DOLastHistoryLength; // 4243 + SCR_INT DOLastResetTime; // 4244 + SCR_ARRAY DOObjectives; // 4245 + SCR_ARRAY DOHistory; // 4255 + SCR_ARRAY LastJobGamerName; // 4280 + SCR_ARRAY BGSaveInt; // 4329 + SCR_ARRAY PropLib; // 4340 + SCR_ARRAY LastGOGGamer; // 4343 + SCR_ARRAY LastGOJobGamer; // 4383 + SCR_ARRAY LastGOJobGamerName; // 4423 +}; +static_assert(sizeof(MP_GENERAL_SAVED) == 4472 * 8); + +struct MP_BOUNTY_SAVED +{ + GAMER_HANDLE BountyGamer; // 0 + SCR_INT BountyTime; // 13 + SCR_INT BountyValue; // 14 + SCR_ARRAY BountyGamerHandles; // 15 + SCR_ARRAY BountyTim; // 224 +}; +static_assert(sizeof(MP_BOUNTY_SAVED) == 241 * 8); + +struct MP_ATM_SAVED +{ + SCR_INT MPATMCaret; // 0 + SCR_ARRAY MPATMLogVal; // 1 + SCR_ARRAY MPATMLogScrs; // 18 + SCR_ARRAY MPATMLogAct; // 115 + SCR_ARRAY MPATMLogDat; // 132 + SCR_BOOL MPAnyVehBought; // 149 +}; +static_assert(sizeof(MP_ATM_SAVED) == 150 * 8); + +struct MP_SCRIPT_SAVES_DATA +{ + SCR_ARRAY SaveDataIntScriptSaves; // 0 + SCR_ARRAY SaveDataFloatScriptSaves; // 2 + SCR_ARRAY SaveDataBoolScriptSaves; // 4 + SCR_ARRAY SaveDataStringScriptSaves; // 6 + SCR_ARRAY SaveDataVectorScriptSaves; // 15 + SCR_ARRAY SaveDataDateScriptSaves; // 19 +}; +static_assert(sizeof(MP_SCRIPT_SAVES_DATA) == 27 * 8); + +struct g_SavedMPGlobalsEntry +{ + // Are these two a struct? TEXT_LABEL_ASSIGN_STRING(&unk, "MP_BIG_ASS_VEHICLES", 24) -> MISC::START_SAVE_STRUCT_WITH_SIZE(panParam0, 7, sParam1) + SCR_INT BAVTimestamp; // 0 + SCR_ARRAY BAVFlags; // 1 + MP_PROPERTY_SAVED PropertySaved; // 7 + CAR_APP_ORDER CarAppOrder; // 593 + MP_GENERAL_SAVED GeneralSaved; // 681 + MP_BOUNTY_SAVED BountySaved; // 5153 + MP_ATM_SAVED ATMSaved; // 5394 + MP_SCRIPT_SAVES_DATA ScriptSavesData; // 5544 +}; +static_assert(sizeof(g_SavedMPGlobalsEntry) == 5571 * 8); + +struct g_SavedMPGlobals +{ + SCR_ARRAY Entries; + + static g_SavedMPGlobals* Get(); +}; +static_assert(sizeof(g_SavedMPGlobals) == 5572 * 8); \ No newline at end of file diff --git a/src/types/script/types.hpp b/src/types/script/types.hpp index 7aecc38..eb9f333 100644 --- a/src/types/script/types.hpp +++ b/src/types/script/types.hpp @@ -29,6 +29,7 @@ using Vector3 = rage::scrVector; #define PED_INDEX alignas(8) Ped #define VEHICLE_INDEX alignas(8) Vehicle #define INTERIOR_INDEX alignas(8) Interior +#define BLIP_INDEX alignas(8) Blip #define NETWORK_INDEX alignas(8) int #define SCR_SIZEOF(x) (sizeof(x) / 8) @@ -99,6 +100,12 @@ struct Color3 }; static_assert(sizeof(Color3) == 3 * 8); +struct Date +{ + SCR_INT Year, Month, Day, Hour, Minute, Second, Millisecond; +}; +static_assert(sizeof(Date) == 7 * 8); + // serialized bitbuffer data of rage::rlGamerHandle + some padding for last gen compatibility // TODO: is the above statement true in Enhanced? // seemingly yes