From a016b36e5ee1cb32d186eaea490acf290476f6ee Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:24:59 +0100 Subject: [PATCH 01/49] 164 search for clothes by (#166) * Revert "Release v2.1.1" * Add Input option for ped components * Undo mistaken revert after failed release. --- Solution/source/Scripting/enums.h | 1 - .../source/Submenus/PedComponentChanger.cpp | 32 +++++++++++++++---- .../Release/menyooStuff/PedDecalOverlays.xml | 6 ++-- Solution/source/macros.h | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Solution/source/Scripting/enums.h b/Solution/source/Scripting/enums.h index 38abd394..ad9ef33f 100644 --- a/Solution/source/Scripting/enums.h +++ b/Solution/source/Scripting/enums.h @@ -1859,7 +1859,6 @@ enum ePedVarComp PV_COMP_JBIB, PV_COMP_MAX }; - //Source: https://natives.altv.mp/0x1913FE4CBF41C463 namespace ePedConfigFlags { diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index bfd3539a..dc6ac7f0 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -251,7 +251,8 @@ namespace sub void ComponentChanger2_() { bool compon_plus = 0, - compon_minus = 0; + compon_minus = 0, + compon_input = 0; int compon_drawable_current = GET_PED_DRAWABLE_VARIATION(Static_241, Static_12), compon_texture_current = GET_PED_TEXTURE_VARIATION(Static_241, Static_12), @@ -263,14 +264,31 @@ namespace sub AddTitle("Set Variation"); - AddNumber("Type", compon_drawable_current, 0, null, compon_plus, compon_minus); + AddNumber("Type", compon_drawable_current, 0, compon_input, compon_plus, compon_minus); AddNumber("Texture", compon_texture_current, 0, null, compon_plus, compon_minus); //AddNumber("Palette", compon_palette_current, 0, null, compon_plus, compon_minus); switch (*Menu::currentopATM) { case 1: - if (compon_plus) + if (compon_input) + { + std::string inputStr = Game::InputBox("", 5U, "", std::to_string(compon_drawable_old)); + if (inputStr.length() > 0) + { + try + { + compon_drawable_current = stoi(inputStr); + if (compon_drawable_current > GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(Static_241, Static_12) - 1) + { + compon_drawable_current = compon_drawable_old; + Game::Print::PrintError_InvalidInput(); + } + } + catch (...) { Game::Print::PrintError_InvalidInput(); } + } + } + else if (compon_plus) { if (compon_drawable_current < GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(Static_241, Static_12) - 1) { @@ -337,10 +355,10 @@ namespace sub || compon_texture_old != compon_texture_current || compon_palette_old != compon_palette_current) { - if (Static_12 == PV_COMP_ACCS && !GET_PED_CONFIG_FLAG(Static_241, ePedConfigFlags::DisableTakeOffScubaGear, true)) //checks if accessory category & DisableTakeOffScubaGear is false - { - SET_PED_CONFIG_FLAG(Static_241, ePedConfigFlags::DisableTakeOffScubaGear, true); - } + if (Static_12 == PV_COMP_ACCS && !GET_PED_CONFIG_FLAG(Static_241, ePedConfigFlags::DisableTakeOffScubaGear, true)) //checks if accessory category & DisableTakeOffScubaGear is false + { + SET_PED_CONFIG_FLAG(Static_241, ePedConfigFlags::DisableTakeOffScubaGear, true); + } SET_PED_COMPONENT_VARIATION(Static_241, Static_12, compon_drawable_current, compon_texture_current, compon_palette_current); while (!HasPedSpecificDrawable(compon_drawable_current)) { diff --git a/Solution/source/_Build/bin/Release/menyooStuff/PedDecalOverlays.xml b/Solution/source/_Build/bin/Release/menyooStuff/PedDecalOverlays.xml index eaadb278..29facd9c 100644 --- a/Solution/source/_Build/bin/Release/menyooStuff/PedDecalOverlays.xml +++ b/Solution/source/_Build/bin/Release/menyooStuff/PedDecalOverlays.xml @@ -1696,7 +1696,8 @@ - + + @@ -3274,7 +3275,8 @@ - + + diff --git a/Solution/source/macros.h b/Solution/source/macros.h index bb3f0772..75d056d2 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS // version -#define MENYOO_CURRENT_VER_ "2.1.1" +#define MENYOO_CURRENT_VER_ "2.1.2a1dev" #define GAME_PLAYERCOUNT 30 From 4e55bb3be4910fb6229d0cc3c58749a8c00cd04c Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:29:32 +0100 Subject: [PATCH 02/49] Add new Halloween Weathers (#167) - fix 155 - refactor sWeatherNames as a std::pair to allow for different hash and display name - add minor debug code --- Solution/source/Scripting/World.cpp | 43 +++++++++++++------ Solution/source/Scripting/World.h | 2 +- Solution/source/Scripting/enums.h | 6 ++- Solution/source/Submenus/Spooner/Submenus.cpp | 4 +- Solution/source/Submenus/WeatherOptions.cpp | 7 ++- 5 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Solution/source/Scripting/World.cpp b/Solution/source/Scripting/World.cpp index f1fe3535..5b388003 100644 --- a/Solution/source/Scripting/World.cpp +++ b/Solution/source/Scripting/World.cpp @@ -50,7 +50,26 @@ std::vector _nearbyPeds, _nearbyVehicles, _worldPeds, _worldVehicles, _w namespace World { - const std::vector World::sWeatherNames{ "ExtraSunny", "Clear", "Clouds", "Smog", "Foggy", "Overcast", "Rain", "Thunder", "Clearing", "Neutral", "Snow", "Blizzard", "SnowLight", "Halloween" }; + //const std::vector World::sWeatherNames{ "ExtraSunny", "Clear", "Clouds", "Smog", "Foggy", "Overcast", "Rain", "Thunder", "Clearing", "Neutral", "Snow", "Blizzard", "SnowLight", "Christmas", "Halloween", "Halloween Snow", "Halloween Rain"}; + const std::vector> World::sWeatherNames{ + {"ExtraSunny", "ExtraSunny"}, + {"Clear", "Clear"}, + {"Clouds", "Clouds"}, + {"Smog", "Smog"}, + {"Foggy", "Foggy"}, + {"Overcast", "Overcast"}, + {"Rain", "Rain"}, + {"Thunder", "Thunder"}, + {"Clearing", "Clearing"}, + {"Neutral", "Neutral"}, + {"Snow", "Snow"}, + {"Blizzard", "Blizzard"}, + {"SnowLight", "SnowLight"}, + //{"Christmas", "XMAS"}, // Still not working for some reason + {"Halloween", "Halloween"}, + {"Halloween Snow", "SNOW_HALLOWEEN"}, // Different internal name + {"Halloween Rain", "RAIN_HALLOWEEN"} // Different internal name + }; void GravityLevel_set(int value) { @@ -78,7 +97,7 @@ namespace World void Weather_set(WeatherType weather) { CLEAR_OVERRIDE_WEATHER(); - SET_WEATHER_TYPE_NOW((PCHAR)sWeatherNames[static_cast(weather)].c_str()); + SET_WEATHER_TYPE_NOW((PCHAR)sWeatherNames[static_cast(weather)].second.c_str()); } void Weather_set(const std::string& weatherName) { @@ -87,7 +106,7 @@ namespace World } void SetWeatherOverTime(WeatherType weather, DWORD ms) { - SET_WEATHER_TYPE_OVERTIME_PERSIST((PCHAR)sWeatherNames[static_cast(weather)].c_str(), float(ms) / 1000.0f); + SET_WEATHER_TYPE_OVERTIME_PERSIST((PCHAR)sWeatherNames[static_cast(weather)].second.c_str(), float(ms) / 1000.0f); } void SetWeatherOverTime(const std::string& weatherName, DWORD ms) { @@ -95,7 +114,7 @@ namespace World } void SetWeatherOverride(WeatherType weather) { - SET_OVERRIDE_WEATHER(sWeatherNames[static_cast(weather)].c_str()); + SET_OVERRIDE_WEATHER(sWeatherNames[static_cast(weather)].second.c_str()); //SET_WEATHER_TYPE_NOW(sWeatherNames[static_cast(weather)].c_str()); } void SetWeatherOverride(const std::string& weatherName) @@ -109,7 +128,7 @@ namespace World } void SetWeatherTransition(WeatherType from, WeatherType to, DWORD ms) { - SET_CURR_WEATHER_STATE(GET_HASH_KEY(sWeatherNames[static_cast(from)]), GET_HASH_KEY(sWeatherNames[static_cast(to)]), float(ms) / 1000.0f); + SET_CURR_WEATHER_STATE(GET_HASH_KEY(sWeatherNames[static_cast(from)].second), GET_HASH_KEY(sWeatherNames[static_cast(to)].second), float(ms) / 1000.0f); } void GetWeatherTransition(WeatherType& from, WeatherType& to, DWORD& time) { @@ -121,11 +140,11 @@ namespace World for (UINT8 i = 0; i < sWeatherNames.size(); i++) { - if (fr == GET_HASH_KEY(sWeatherNames[i])) + if (fr == GET_HASH_KEY(sWeatherNames[i].second)) { from = (WeatherType)i; } - if (t == GET_HASH_KEY(sWeatherNames[i])) + if (t == GET_HASH_KEY(sWeatherNames[i].second)) { to = (WeatherType)i; } @@ -136,7 +155,7 @@ namespace World Hash currentWeatherHash = GET_PREV_WEATHER_TYPE_HASH_NAME(); for (int i = 0; i < sWeatherNames.size(); i++) { - if (currentWeatherHash == GET_HASH_KEY(sWeatherNames[i])) + if (currentWeatherHash == GET_HASH_KEY(sWeatherNames[i].second)) { return static_cast(i); } @@ -147,7 +166,7 @@ namespace World { for (int i = 0; i < sWeatherNames.size(); i++) { - if (weatherName.compare(sWeatherNames[i]) == 0) + if (weatherName.compare(sWeatherNames[i].second) == 0) { return static_cast(i); } @@ -159,9 +178,9 @@ namespace World Hash currentWeatherHash = GET_PREV_WEATHER_TYPE_HASH_NAME(); for (auto& weatherName : sWeatherNames) { - if (currentWeatherHash == GET_HASH_KEY(weatherName)) + if (currentWeatherHash == GET_HASH_KEY(weatherName.second)) { - return weatherName; + return weatherName.first; } } return std::string(); @@ -170,7 +189,7 @@ namespace World { auto weatherTypeInt = static_cast(weatherType); if (weatherTypeInt >= 0 && weatherTypeInt < sWeatherNames.size()) - return sWeatherNames[weatherTypeInt]; + return sWeatherNames[weatherTypeInt].first; else return std::string(); } diff --git a/Solution/source/Scripting/World.h b/Solution/source/Scripting/World.h index dac91946..8e06840d 100644 --- a/Solution/source/Scripting/World.h +++ b/Solution/source/Scripting/World.h @@ -58,7 +58,7 @@ extern std::vector _nearbyPeds, _nearbyVehicles, _worldPeds, _worldVehic namespace World { - extern const std::vector sWeatherNames; + extern const std::vector> sWeatherNames; void GravityLevel_set(int value); diff --git a/Solution/source/Scripting/enums.h b/Solution/source/Scripting/enums.h index ad9ef33f..188eb00c 100644 --- a/Solution/source/Scripting/enums.h +++ b/Solution/source/Scripting/enums.h @@ -4802,8 +4802,10 @@ enum class WeatherType : int Snow, Blizzard, SnowLight, - //Xmas, - Halloween + //XMAS, + Halloween, + SNOW_HALLOWEEN, + RAIN_HALLOWEEN }; namespace EXPLOSION { diff --git a/Solution/source/Submenus/Spooner/Submenus.cpp b/Solution/source/Submenus/Spooner/Submenus.cpp index 8dce4eaa..02958c97 100644 --- a/Solution/source/Submenus/Spooner/Submenus.cpp +++ b/Solution/source/Submenus/Spooner/Submenus.cpp @@ -805,9 +805,9 @@ namespace sub for (auto& ws : World::sWeatherNames) { bool bWeatherNamePressed = false; - AddTickol(ws, weatherToSetStr == ws, bWeatherNamePressed, bWeatherNamePressed); if (bWeatherNamePressed) + AddTickol(ws.first, weatherToSetStr == ws.second, bWeatherNamePressed, bWeatherNamePressed); if (bWeatherNamePressed) { - nodeWeatherToSet.text() = ws.c_str(); + nodeWeatherToSet.text() = ws.second.c_str(); doc.save_file((const char*)filePath.c_str()); } } diff --git a/Solution/source/Submenus/WeatherOptions.cpp b/Solution/source/Submenus/WeatherOptions.cpp index cdba5bbf..1f224eeb 100644 --- a/Solution/source/Submenus/WeatherOptions.cpp +++ b/Solution/source/Submenus/WeatherOptions.cpp @@ -17,6 +17,7 @@ #include "..\Natives\natives2.h" #include "..\Memory\GTAmemory.h" #include "..\Scripting\World.h" +#include "..\Util\FileLogger.h" #include #include @@ -61,11 +62,13 @@ namespace sub for (auto& weatherName : World::sWeatherNames) { bool bWeatherPressed = false; - AddTickol(weatherName, GET_PREV_WEATHER_TYPE_HASH_NAME() == GET_HASH_KEY(weatherName), bWeatherPressed, bWeatherPressed); if (bWeatherPressed) + AddTickol(weatherName.first, GET_PREV_WEATHER_TYPE_HASH_NAME() == GET_HASH_KEY(weatherName.second), bWeatherPressed, bWeatherPressed); if (bWeatherPressed) { - World::SetWeatherOverride(weatherName); + addlog(ige::LogType::LOG_DEBUG, "Setting weather to " + weatherName.first, __FILENAME__); + World::SetWeatherOverride(weatherName.second); } } + //AddweatherOption_("Clear"); //AddweatherOption_("ExtraSunny"); //AddweatherOption_("Clouds"); From d0e9badaebef640802c1a5b8fa4616f765b6e9b2 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 30 Jul 2024 20:11:14 +0100 Subject: [PATCH 03/49] UpVersion for Pre-release --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 75d056d2..49998612 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS // version -#define MENYOO_CURRENT_VER_ "2.1.2a1dev" +#define MENYOO_CURRENT_VER_ "2.1.2a1" #define GAME_PLAYERCOUNT 30 From 7e60fa0b5bf98794aac903e974f29d9902cba387 Mon Sep 17 00:00:00 2001 From: Andy <41640713+katsutosh@users.noreply.github.com> Date: Tue, 30 Jul 2024 23:52:45 +0200 Subject: [PATCH 04/49] refactor implement ePedConfigFlags in *_PED_CONFIG_FLAG natives (#168) --- Solution/source/Menu/Routine.cpp | 24 +++++++++---------- Solution/source/Scripting/GTAped.cpp | 4 ++-- .../source/Submenus/PedComponentChanger.cpp | 2 +- Solution/source/Submenus/PlayerOptions.cpp | 16 ++++++------- .../Submenus/Spooner/EntityManagement.cpp | 2 +- .../Submenus/Spooner/FileManagement.cpp | 4 ++-- Solution/source/Submenus/Spooner/Submenus.cpp | 4 ++-- 7 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index 63a77d9a..328173fe 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -993,8 +993,8 @@ void set_self_resurrectionGun() targPed.MaxHealth_set(400); targPed.Health_set(200); SET_PED_GENERATES_DEAD_BODY_EVENTS(targPed.Handle(), false); - SET_PED_CONFIG_FLAG(targPed.Handle(), 166, 0); - SET_PED_CONFIG_FLAG(targPed.Handle(), 187, 0); + SET_PED_CONFIG_FLAG(targPed.Handle(), ePedConfigFlags::IsInjured, 0); + SET_PED_CONFIG_FLAG(targPed.Handle(), ePedConfigFlags::HasHurtStarted, 0); targPed.Task().ClearAllImmediately(); TaskSequence seq; @@ -1476,12 +1476,12 @@ void set_ped_seatbelt_on(Ped ped) { SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(ped, 1); // state cantFollOff //SET_PED_CONFIG_FLAG(ped, 32, true); - SET_PED_CONFIG_FLAG(ped, 32, false); + SET_PED_CONFIG_FLAG(ped, ePedConfigFlags::WillFlyThruWindscreen, false); } void set_ped_seatbelt_off(Ped ped) { SET_PED_CAN_BE_KNOCKED_OFF_VEHICLE(ped, 0); // state canFallOff - SET_PED_CONFIG_FLAG(ped, 32, true); + SET_PED_CONFIG_FLAG(ped, ePedConfigFlags::WillFlyThruWindscreen, true); } // Misc - FreeCam @@ -2706,9 +2706,9 @@ void Set_Walkunderwater(Entity PlayerPed) { if (IS_ENTITY_IN_WATER(PlayerPed)) { - SET_PED_CONFIG_FLAG(PlayerPed, 65, false); - SET_PED_CONFIG_FLAG(PlayerPed, 66, false); - SET_PED_CONFIG_FLAG(PlayerPed, 168, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::IsSwimming, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::WasSwimming, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::_0xD8072639, false); Vector3 PlayerPos = GET_ENTITY_COORDS(PlayerPed, 0); DRAW_LIGHT_WITH_RANGEEX(PlayerPos.x, PlayerPos.y, (PlayerPos.z + 1.5f), 255, 255, 251, 100.0f, 1.5f, 0.0f); @@ -2721,11 +2721,11 @@ void Set_Walkunderwater(Entity PlayerPed) if (GET_ENTITY_HEIGHT_ABOVE_GROUND(PlayerPed) > 1) //Do falling down { - SET_PED_CONFIG_FLAG(PlayerPed, 60, false); - SET_PED_CONFIG_FLAG(PlayerPed, 61, false); - SET_PED_CONFIG_FLAG(PlayerPed, 104, false); - SET_PED_CONFIG_FLAG(PlayerPed, 276, false); - SET_PED_CONFIG_FLAG(PlayerPed, 76, true); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::IsStanding, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::WasStanding, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::OpenDoorArmIK, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::EdgeDetected, false); + SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::IsInTheAir, true); APPLY_FORCE_TO_ENTITY(PlayerPed, true, 0, 0, -0.7f, 0, 0, 0, true, true, true, true, false, true); } diff --git a/Solution/source/Scripting/GTAped.cpp b/Solution/source/Scripting/GTAped.cpp index 243e4b7a..9fcfd342 100644 --- a/Solution/source/Scripting/GTAped.cpp +++ b/Solution/source/Scripting/GTAped.cpp @@ -453,11 +453,11 @@ void GTAped::CanSufferCriticalHits_set(bool value) bool GTAped::CanFlyThroughWindscreen_get() const { - return GET_PED_CONFIG_FLAG(this->mHandle, 32, true) != 0; + return GET_PED_CONFIG_FLAG(this->mHandle, ePedConfigFlags::WillFlyThruWindscreen, true) != 0; } void GTAped::CanFlyThroughWindscreen_set(bool value) { - SET_PED_CONFIG_FLAG(this->mHandle, 32, value); + SET_PED_CONFIG_FLAG(this->mHandle, ePedConfigFlags::WillFlyThruWindscreen, value); } void GTAped::CanBeKnockedOffBike_set(int state) diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index dc6ac7f0..bae5d967 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -1371,7 +1371,7 @@ namespace sub if (bWas241) Static_241 = ep.Handle(); } - if (nodePedStuff.child("HasShortHeight").text().as_bool()) SET_PED_CONFIG_FLAG(ep.Handle(), 223, 1); + if (nodePedStuff.child("HasShortHeight").text().as_bool()) SET_PED_CONFIG_FLAG(ep.Handle(), ePedConfigFlags::_Shrink, 1); auto nodePedHeadFeatures = nodePedStuff.child("HeadFeatures"); if (sub::PedHeadFeatures_catind::DoesPedModelSupportHeadFeatures(eModel) && nodePedHeadFeatures) diff --git a/Solution/source/Submenus/PlayerOptions.cpp b/Solution/source/Submenus/PlayerOptions.cpp index d5474628..73ad3656 100644 --- a/Solution/source/Submenus/PlayerOptions.cpp +++ b/Solution/source/Submenus/PlayerOptions.cpp @@ -300,14 +300,14 @@ namespace sub std::vector vPedFlags { //{ 227, "Play Dead" }, - { 32, "Can Fall Out Through Windscreen" }, - { 62, "Is (Nearby) Car (MAY CRASH)" }, - { 78, "Is Aiming Check" }, - { 101, "Is Aiming" }, - { 125, "Has Overflowing Diaper (MAY CRASH)" }, - { 166, "Is Injured" }, - { 187, "Is Injured In Combat" }, - { 223, "Is Short Heighted (Small)" }, + { ePedConfigFlags::WillFlyThruWindscreen, "Can Fall Out Through Windscreen" }, + { ePedConfigFlags::InVehicle, "Is (Nearby) Car (MAY CRASH)" }, + { ePedConfigFlags::IsAimingGun, "Is Aiming Check" }, + { ePedConfigFlags::ForcedAim, "Is Aiming" }, + { ePedConfigFlags::_0x5FED6BFD, "Has Overflowing Diaper (MAY CRASH)" }, + { ePedConfigFlags::IsInjured, "Is Injured" }, + { ePedConfigFlags::HasHurtStarted, "Is Injured In Combat" }, + { ePedConfigFlags::_Shrink, "Is Short Heighted (Small)" }, //{ 000000, "" }, }; diff --git a/Solution/source/Submenus/Spooner/EntityManagement.cpp b/Solution/source/Submenus/Spooner/EntityManagement.cpp index a18982a6..c6ea445a 100644 --- a/Solution/source/Submenus/Spooner/EntityManagement.cpp +++ b/Solution/source/Submenus/Spooner/EntityManagement.cpp @@ -666,7 +666,7 @@ namespace sub::Spooner //GTAped(newEntity.Handle).GiveWeaponsFromArray(weaponsBackup); SET_NETWORK_ID_CAN_MIGRATE(ep.NetID(), true); ep.BlockPermanentEvents_set(orig.IsStill); - SET_PED_CONFIG_FLAG(ep.Handle(), 223, GET_PED_CONFIG_FLAG(origPed.Handle(), 223, false)); + SET_PED_CONFIG_FLAG(ep.Handle(), ePedConfigFlags::_Shrink, GET_PED_CONFIG_FLAG(origPed.Handle(), ePedConfigFlags::_Shrink, false)); SET_PED_CAN_PLAY_AMBIENT_ANIMS(ep.Handle(), true); SET_PED_CAN_PLAY_AMBIENT_BASE_ANIMS(ep.Handle(), true); diff --git a/Solution/source/Submenus/Spooner/FileManagement.cpp b/Solution/source/Submenus/Spooner/FileManagement.cpp index 7325ec31..9db801ad 100644 --- a/Solution/source/Submenus/Spooner/FileManagement.cpp +++ b/Solution/source/Submenus/Spooner/FileManagement.cpp @@ -131,7 +131,7 @@ namespace sub::Spooner nodePedStuff.append_child("CanRagdoll").text() = ep.CanRagdoll_get(); - nodePedStuff.append_child("HasShortHeight").text() = GET_PED_CONFIG_FLAG(ep.Handle(), 223, false) != 0; + nodePedStuff.append_child("HasShortHeight").text() = GET_PED_CONFIG_FLAG(ep.Handle(), ePedConfigFlags::_Shrink, false) != 0; nodePedStuff.append_child("Armour").text() = ep.Armour_get(); @@ -518,7 +518,7 @@ namespace sub::Spooner ep.CanRagdoll_set(nodePedStuff.child("CanRagdoll").text().as_bool(true)); SET_PED_RAGDOLL_ON_COLLISION(ep.Handle(), nodePedStuff.child("CanRagdoll").text().as_bool(false)); - if (nodePedStuff.child("HasShortHeight").text().as_bool()) SET_PED_CONFIG_FLAG(ep.Handle(), 223, 1); + if (nodePedStuff.child("HasShortHeight").text().as_bool()) SET_PED_CONFIG_FLAG(ep.Handle(), ePedConfigFlags::_Shrink, 1); ep.Armour_set(nodePedStuff.child("Armour").text().as_int()); ep.Weapon_set(nodePedStuff.child("CurrentWeapon").text().as_uint()); diff --git a/Solution/source/Submenus/Spooner/Submenus.cpp b/Solution/source/Submenus/Spooner/Submenus.cpp index 02958c97..104cf36b 100644 --- a/Solution/source/Submenus/Spooner/Submenus.cpp +++ b/Solution/source/Submenus/Spooner/Submenus.cpp @@ -2255,7 +2255,7 @@ namespace sub GTAped thisPed = SelectedEntity.Handle; bool butAmIOnline = NETWORK_IS_IN_SESSION() != 0; bool isPedMyPed = thisPed.Handle() == myPed.Handle(); - bool bIsPedShortHeighted = GET_PED_CONFIG_FLAG(thisPed.Handle(), 223, false) != 0; + bool bIsPedShortHeighted = GET_PED_CONFIG_FLAG(thisPed.Handle(), ePedConfigFlags::_Shrink, false) != 0; PedGroup myPedGroup = myPed.CurrentPedGroup_get(); bool pedops_isStill_toggle = false, @@ -2275,7 +2275,7 @@ namespace sub MenuOptions::AddOption_RelationshipTextScroller(); AddToggle("Is Still (Block Fleeing)", SelectedEntity.IsStill, pedops_isStill_toggle, pedops_isStill_toggle); if (pedops_isStill_toggle) { thisPed.BlockPermanentEvents_set(SelectedEntity.IsStill); } AddLocal("Can Ragdoll", thisPed.CanRagdoll_get(), pedops_canRagdoll_toggle, pedops_canRagdoll_toggle); if (pedops_canRagdoll_toggle) { bool ns = !thisPed.CanRagdoll_get(); thisPed.CanRagdoll_set(ns); SET_PED_RAGDOLL_ON_COLLISION(thisPed.Handle(), ns); } - AddLocal("Is Short Heighted (Small)", bIsPedShortHeighted, pedops_shortHeighted_toggle, pedops_shortHeighted_toggle); if (pedops_shortHeighted_toggle) { SET_PED_CONFIG_FLAG(SelectedEntity.Handle.Handle(), 223, bIsPedShortHeighted ? 0 : 1); } + AddLocal("Is Short Heighted (Small)", bIsPedShortHeighted, pedops_shortHeighted_toggle, pedops_shortHeighted_toggle); if (pedops_shortHeighted_toggle) { SET_PED_CONFIG_FLAG(SelectedEntity.Handle.Handle(), ePedConfigFlags::_Shrink, bIsPedShortHeighted ? 0 : 1); } int thisArmour = thisPed.Armour_get(); bool bArmour_plus = false, bArmour_minus = false, bArmour_input = false; From 9142a7ee98b7d4d20ec45a7d1be566b5d8868e87 Mon Sep 17 00:00:00 2001 From: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> Date: Mon, 12 Aug 2024 13:37:31 +0100 Subject: [PATCH 05/49] Update WeaponIndivs.cpp (#171) This is for a test I want to make. I want to see if animals will work properly if manually given the animal "weapons". If it doesn't work I will undo this change myself. --- Solution/source/Scripting/WeaponIndivs.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Solution/source/Scripting/WeaponIndivs.cpp b/Solution/source/Scripting/WeaponIndivs.cpp index e31281f9..6dbbd209 100644 --- a/Solution/source/Scripting/WeaponIndivs.cpp +++ b/Solution/source/Scripting/WeaponIndivs.cpp @@ -53,6 +53,8 @@ std::map WeaponIndivs::vWeaponLabels { WEAPON_METALDETECTOR, "Metal Detector" }, //2699 { WEAPON_CANDYCANE, "Candy Cane" }, //2802 { WEAPON_STUNROD, "Stun Rod"}, + { WEAPON_ANIMAL, "ANIMAL"}, + { WEAPON_COUGAR, "COUGAR"}, //slot pistol (22) { WEAPON_PISTOL, "Pistol" }, { WEAPON_PISTOL_MK2, "Pistol Mk2" }, From dc94c4dfa100819ada28fbc030424dd12f3d71a8 Mon Sep 17 00:00:00 2001 From: LuisYeah1234-hub <64372171+LuisYeah1234-hub@users.noreply.github.com> Date: Sat, 15 Mar 2025 10:58:12 +0100 Subject: [PATCH 06/49] Fix freeze & crash while Loading Benchmark From loading screens (#269) * #218 (#226) * #218 - Corrected and enchanced/refactored teleport to waypoint * #218 - Removed duplicate declaration of ____gtaGroundCheckHeight array * Update macros.h * Improve Gen 9 Warning (#227) * Improve Gen 9 Warning - Update on-screen warning text with clearer instructions - Add explicit list of gen9 dlcs to menyoolog - Add two new g9 dlcs to check list - Add check for mp2024 bugged dlc (temp until r* fix) * UpVersion for Pre-release * Missing game build (#228) * Fix Missing Game Build Add 3407 to Main.h * Fix Missing Game Build Add 3407 to Menyoo.rc * UpVersion for Pre-release * Fix #232 (#233) * Remove playsound on doors Comment out play sound line * UpVersion for Pre-release * Blip fix (#236) * Update GTAblip.h (#234) Fixed Deluxo duplicate mishap. Duplicate reassigned to Toreador. * Update GTAblip.cpp (#235) Duplicate Deluxo reassigned to Toreador. * UpVersion for Prerelease --------- Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> * Blip fix patch (#240) * Update GTAblip.h (#237) Renamed duplicate Deluxo to 'Toreador'. * Update GTAblip.cpp (#238) Renamed duplicate Deluxo to 'Toreador'. --------- Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> * Achievement unlocks (#245) * UpVersion for Pre-release * Add more achievement options (#242) - Update the number achievements to 77 - Add menu options to unlock individual achievements --------- Co-authored-by: frankie2d * Update Readme.txt * Actions Improvements (#254) * Update msbuild.yml - Migrate build artefact from v3 to v4 * Update master_build.yml - Remove exit 1 for successful cancellations - Add CANCELJOB to skip unnecessary steps and jobs * Aos blips (#251) * Agents of Sabotage blips (#247) * Update GTAblip.h Added Agents of Sabotage blips! * Update GTAblip.cpp Added Agents of Sabotage blips. * UpVersion for Pre-release --------- Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> * Update master_build.yml * Aos blips fix (#255) * Update GTAblip.cpp * Update GTAblip.h Add missing comma to std::map for blips. * 3442 build (#258) * Update Menyoo.rc Add 3442 FX ASI Build * Update main.h Add 3442 Version * UpVersion for Pre-release * Update macros.h * Fix freeze & crash on Loading Benchmark Fixes a freeze and then a crash while loading Benchmark from anything except the Pause Menu --------- Co-authored-by: ShawnPR1 <31240808+ShawnPR1@users.noreply.github.com> Co-authored-by: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> Co-authored-by: frankie2d --- Solution/source/Menu/Routine.cpp | 2 +- Solution/source/macros.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index 5ba2e6a9..7a0e0451 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -171,7 +171,7 @@ inline void MenyooMain() g_MenyooConfigTick = GetTickCount(); g_FaderTick = GetTickCount(); - if (!NETWORK_IS_SESSION_STARTED()) + if (!NETWORK_IS_SESSION_STARTED() && !IS_COMMANDLINE_END_USER_BENCHMARK() && !LANDING_SCREEN_STARTED_END_USER_BENCHMARK()) { if (GTAmemory::FindShopController()) GeneralGlobalHax::EnableBlockedMpVehiclesInSp(); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 13d7ef3d..ed5448de 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -15,8 +15,8 @@ #define _CRT_SECURE_NO_WARNINGS -// version -#define MENYOO_CURRENT_VER_ "2.1.3" + +#define MENYOO_CURRENT_VER_ "2.1.4a1" #define GAME_PLAYERCOUNT 30 From 1d8acaf721550f749eb87f19233814831fad1fe0 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Mon, 31 Mar 2025 14:12:41 +0400 Subject: [PATCH 07/49] Language log fix (#290) * Fix log file continuously duplicating error messages(#288) Change it to record only once. If your native language is English, you may not find this problem. I used an external translation file json to translate the menu into my language. When I open the menu, an error message will be written to the menyooLog file for each frame. As long as you stay on the current menu page, it will repeatedly write the same message for each menu line, like this: * moving from filelogger.cpp to language.cpp instead Restore filelogger.cpp * UpVersion for Pre-release --------- Co-authored-by: lucienlmy <101241027+lucienlmy@users.noreply.github.com> --- Solution/source/Menu/Language.cpp | 19 +++++++++++++------ Solution/source/macros.h | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Solution/source/Menu/Language.cpp b/Solution/source/Menu/Language.cpp index c9fed5e5..0e92198e 100644 --- a/Solution/source/Menu/Language.cpp +++ b/Solution/source/Menu/Language.cpp @@ -1,4 +1,4 @@ -/* +/* * Menyoo PC - Grand Theft Auto V single-player trainer mod * Copyright (C) 2019 MAFINS * @@ -15,6 +15,7 @@ #include #include +#include using Json = nlohmann::json; namespace Language @@ -33,14 +34,20 @@ namespace Language std::string Lang::Translate(std::string text) { - try - { + static std::set reported_missing; + + try { auto& ret = this->pairs.at(text); return ret; } - catch (std::out_of_range) - { - addlog(ige::LogType::LOG_ERROR, "Translate string out of range: " + text, __FILENAME__); + catch (std::out_of_range) { + if(reported_missing.insert(text).second) { + addlog(ige::LogType::LOG_ERROR, + "Missing translation for: " + text, + __FILENAME__); + } + this->pairs[text] = text; + return text; } } diff --git a/Solution/source/macros.h b/Solution/source/macros.h index ed5448de..4ded1a3a 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.1.4a1" +#define MENYOO_CURRENT_VER_ "2.1.4a2" #define GAME_PLAYERCOUNT 30 From d3afa65186437cd8f2f34bd559b5ecef1590702f Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sun, 6 Apr 2025 13:09:02 +0400 Subject: [PATCH 08/49] Enhanced freecam (#296) * Enhanced Free Camera Mode functionality (#274) 1. Use the mouse wheel to adjust the flight speed 2. Press and hold the right mouse button for fine flight 3. Press and hold the spacebar to use the wheel to adjust the FOV 4. Use the Tab key to switch and lock the flight altitude, QE can still adjust the altitude * Fixed the display problem of adjusting various camera values 1: Change the camera display text to a custom method; 2: Change the name of the configuration file node [free-camera]right_click_slow_speed automatically generated by the camera to default_slow_speed; 3: Except for the default value, which will change in real time according to the adjustment in the game, the rest can be adjusted before entering the game [free-camera] default_speed = 8.100000 default_fov = 58.000000 default_slow_speed = 0.800000 speed_adjust_step = 1.000000 fov_adjust_step = 1.000000 min_speed = 0.100000 max_speed = 20.000000 min_fov = 30.000000 max_fov = 120.000000 --------- Co-authored-by: lucienlmy <101241027+lucienlmy@users.noreply.github.com> --- Solution/source/Menu/MenuConfig.cpp | 40 ++++++- Solution/source/Menu/MenuConfig.h | 15 ++- Solution/source/Menu/Routine.cpp | 164 ++++++++++++++++++++++++++-- Solution/source/Menyoo.vcxproj | 2 +- Solution/source/macros.h | 2 +- 5 files changed, 212 insertions(+), 11 deletions(-) diff --git a/Solution/source/Menu/MenuConfig.cpp b/Solution/source/Menu/MenuConfig.cpp index a8796eeb..7b2ac926 100644 --- a/Solution/source/Menu/MenuConfig.cpp +++ b/Solution/source/Menu/MenuConfig.cpp @@ -1,4 +1,4 @@ -/* +/* * Menyoo PC - Grand Theft Auto V single-player trainer mod * Copyright (C) 2019 MAFINS * @@ -43,6 +43,21 @@ CSimpleIniA MenuConfig::iniFile; bool MenuConfig::bSaveAtIntervals = true; +// Initialize the default camera parameters +namespace MenuConfig { + namespace FreeCam { + float defaultSpeed = 0.5f; + float defaultFov = 50.0f; + float defaultSlowSpeed = 0.2f; + float speedAdjustStep = 0.1f; + float fovAdjustStep = 1.0f; + float minSpeed = 0.1f; + float maxSpeed = 10.0f; + float minFov = 30.0f; + float maxFov = 120.0f; + } +} + void MenuConfig::ConfigInit() { MenuConfig::iniFile.SetUnicode(true); @@ -307,6 +322,17 @@ void MenuConfig::ConfigRead() sub::Speedo_catind::_currentSpeedoBg.fileName = ini.GetValue(section_haxValues.c_str(), "speedo_bg_name", sub::Speedo_catind::_currentSpeedoBg.fileName.c_str()); sub::Speedo_catind::SetCurrentBgIdFromBgNameForConfig(); + // Read camera configuration + std::string section_freecam = "free-camera"; + FreeCam::defaultSpeed = (float)ini.GetDoubleValue(section_freecam.c_str(), "default_speed", FreeCam::defaultSpeed); + FreeCam::defaultFov = (float)ini.GetDoubleValue(section_freecam.c_str(), "default_fov", FreeCam::defaultFov); + FreeCam::defaultSlowSpeed = (float)ini.GetDoubleValue(section_freecam.c_str(), "default_slow_speed", FreeCam::defaultSlowSpeed); + FreeCam::speedAdjustStep = (float)ini.GetDoubleValue(section_freecam.c_str(), "speed_adjust_step", FreeCam::speedAdjustStep); + FreeCam::fovAdjustStep = (float)ini.GetDoubleValue(section_freecam.c_str(), "fov_adjust_step", FreeCam::fovAdjustStep); + FreeCam::minSpeed = (float)ini.GetDoubleValue(section_freecam.c_str(), "min_speed", FreeCam::minSpeed); + FreeCam::maxSpeed = (float)ini.GetDoubleValue(section_freecam.c_str(), "max_speed", FreeCam::maxSpeed); + FreeCam::minFov = (float)ini.GetDoubleValue(section_freecam.c_str(), "min_fov", FreeCam::minFov); + FreeCam::maxFov = (float)ini.GetDoubleValue(section_freecam.c_str(), "max_fov", FreeCam::maxFov); } void MenuConfig::ConfigSave() @@ -556,6 +582,18 @@ void MenuConfig::ConfigSave() ini.SetDoubleValue(section_haxValues.c_str(), "speedo_screen_pos_y", sub::Speedo_catind::_speedoPosition.y); ini.SetValue(section_haxValues.c_str(), "speedo_bg_name", sub::Speedo_catind::_currentSpeedoBg.fileName.c_str()); + // Save camera configuration + std::string section_freecam = "free-camera"; + ini.SetDoubleValue(section_freecam.c_str(), "default_speed", FreeCam::defaultSpeed); + ini.SetDoubleValue(section_freecam.c_str(), "default_fov", FreeCam::defaultFov); + ini.SetDoubleValue(section_freecam.c_str(), "right_click_slow_speed", FreeCam::defaultSlowSpeed); + ini.SetDoubleValue(section_freecam.c_str(), "speed_adjust_step", FreeCam::speedAdjustStep); + ini.SetDoubleValue(section_freecam.c_str(), "fov_adjust_step", FreeCam::fovAdjustStep); + ini.SetDoubleValue(section_freecam.c_str(), "min_speed", FreeCam::minSpeed); + ini.SetDoubleValue(section_freecam.c_str(), "max_speed", FreeCam::maxSpeed); + ini.SetDoubleValue(section_freecam.c_str(), "min_fov", FreeCam::minFov); + ini.SetDoubleValue(section_freecam.c_str(), "max_fov", FreeCam::maxFov); + ini.SaveFile((GetPathffA(Pathff::Main, true) + "menyooConfig.ini").c_str()); } diff --git a/Solution/source/Menu/MenuConfig.h b/Solution/source/Menu/MenuConfig.h index ce4aac92..667fc45c 100644 --- a/Solution/source/Menu/MenuConfig.h +++ b/Solution/source/Menu/MenuConfig.h @@ -1,4 +1,4 @@ -/* +/* * Menyoo PC - Grand Theft Auto V single-player trainer mod * Copyright (C) 2019 MAFINS * @@ -16,6 +16,19 @@ namespace MenuConfig extern CSimpleIniA iniFile; extern bool bSaveAtIntervals; +// Camera configuration parameters +namespace FreeCam { + extern float defaultSpeed; // Default movement speed + extern float defaultFov; // Default FOV value + extern float defaultSlowSpeed; // Speed ​​multiplier when right mouse button is held + extern float speedAdjustStep; // Speed ​​adjustment step + extern float fovAdjustStep; // FOV adjustment step + extern float minSpeed; // Minimum speed + extern float maxSpeed; // Maximum speed + extern float minFov; // Minimum FOV + extern float maxFov; // Maximum FOV + } + void ConfigInit(); void ConfigRead(); void ConfigSave(); diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index 7a0e0451..faf9f707 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -1,4 +1,4 @@ -/* +/* * Menyoo PC - Grand Theft Auto V single-player trainer mod * Copyright (C) 2019 MAFINS * @@ -321,6 +321,14 @@ bool bit_grav_gun_disabled = 0; float forge_dist = 6.0f, _globalForgeGun_prec = 0.2f, _globalForgeGun_shootForce = 300.0f; bool ObjSpawn_forge_assistance = 0; +DWORD g_lastSpeedDisplayTime = 0; +DWORD g_lastFOVDisplayTime = 0; +float g_lastSpeedValue = 0.0f; +float g_lastFOVValue = 0.0f; + +DWORD g_lastHeightLockMessageTime = 0; +const char* g_lastHeightLockMessage = nullptr; + #pragma endregion #pragma region methods used define // p.s. this ain't it chief @@ -1514,6 +1522,9 @@ void set_ped_seatbelt_off(Ped ped) // Misc - FreeCam bool bit_noclip_already_invis, bit_noclip_already_collis, bit_noclip_show_help = true; Camera g_cam_noClip; +bool g_freecam_heightLocked = false; +float g_freecam_lockedHeight = 0.0f; +float g_freecam_speed = MenuConfig::FreeCam::defaultSpeed; // Modify the default value void set_no_clip_off1() { GTAentity myPed = PLAYER_PED_ID(); @@ -1599,7 +1610,7 @@ void set_no_clip() cam.Position_set(GameplayCamera::Position_get()); cam.Rotation_set(GameplayCamera::Rotation_get()); cam.AttachTo(ent, camOffset); - cam.FieldOfView_set(GameplayCamera::FieldOfView_get()); + cam.FieldOfView_set(MenuConfig::FreeCam::defaultFov); // Use configured FOV cam.DepthOfFieldStrength_set(0.0f); World::RenderingCamera_set(cam); } @@ -1648,14 +1659,145 @@ void set_no_clip() //} } else - { - float noclip_prec_level = IS_DISABLED_CONTROL_PRESSED(0, INPUT_SPRINT) ? 1.77f : 0.35f; + { + // Handle mouse wheel to adjust movement speed - only adjust speed when right button is not pressed + if(!IsKeyDown(VK_SPACE)) + { + // Add TAB key to lock height function + if(IsKeyJustUp(VK_TAB)) { + g_freecam_heightLocked = !g_freecam_heightLocked; + if(g_freecam_heightLocked) { + // Store the current height when locked + g_freecam_lockedHeight = ent.Position_get().z; + g_lastHeightLockMessage = "Height Locked"; + } else { + g_lastHeightLockMessage = "Height Unlocked"; + } + g_lastHeightLockMessageTime = GetTickCount(); + } + // Handle mouse wheel to adjust speed + if(IS_DISABLED_CONTROL_PRESSED(2, INPUT_CURSOR_SCROLL_UP)) + { + g_freecam_speed += MenuConfig::FreeCam::speedAdjustStep; + if(g_freecam_speed > MenuConfig::FreeCam::maxSpeed) + g_freecam_speed = MenuConfig::FreeCam::maxSpeed; + + // Save the current speed as the default value + MenuConfig::FreeCam::defaultSpeed = g_freecam_speed; + MenuConfig::ConfigSave(); + + // Display the current speed + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(oss_ << "FreeCam Speed: " << g_freecam_speed, 0.5f, 0.95f); + + g_lastSpeedValue = g_freecam_speed; + g_lastSpeedDisplayTime = GetTickCount(); + } + if(IS_DISABLED_CONTROL_PRESSED(2, INPUT_CURSOR_SCROLL_DOWN)) + { + g_freecam_speed -= MenuConfig::FreeCam::speedAdjustStep; + if(g_freecam_speed < MenuConfig::FreeCam::minSpeed) + g_freecam_speed = MenuConfig::FreeCam::minSpeed; + + // Save the current speed as the default value + MenuConfig::FreeCam::defaultSpeed = g_freecam_speed; + MenuConfig::ConfigSave(); + + // Display the current speed + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(oss_ << "FreeCam Speed: " << g_freecam_speed, 0.5f, 0.95f); + + g_lastSpeedValue = g_freecam_speed; + g_lastSpeedDisplayTime = GetTickCount(); + } + + // Check if speed text needs to be displayed + if(GetTickCount() - g_lastSpeedDisplayTime < 1000) // 1秒延迟 + { + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(oss_ << "FreeCam Speed: " << g_lastSpeedValue, 0.5f, 0.95f); + } + } + + // When pressing the space bar, the speed is fixed at 0.2 + //float current_speed = IsKeyDown(VK_CONTROL) ? 0.2f : g_freecam_speed; + float current_speed = IS_DISABLED_CONTROL_PRESSED(2, INPUT_VEH_ATTACK2) ? MenuConfig::FreeCam::defaultSlowSpeed : g_freecam_speed; + + // Make sprint increase based on current speed + float noclip_prec_level = IS_DISABLED_CONTROL_PRESSED(0, INPUT_SPRINT) ? current_speed * 2.0f : current_speed; + Vector3 offset; offset.x = GET_CONTROL_NORMAL(0, INPUT_MOVE_LR) * noclip_prec_level; offset.y = -GET_CONTROL_NORMAL(0, INPUT_MOVE_UD) * noclip_prec_level; - offset.z = IS_DISABLED_CONTROL_PRESSED(2, INPUT_PARACHUTE_BRAKE_RIGHT) ? noclip_prec_level : IS_DISABLED_CONTROL_PRESSED(2, INPUT_PARACHUTE_BRAKE_LEFT) ? -noclip_prec_level : 0.0f; - if (!offset.IsZero()) + + if(g_freecam_heightLocked) { + // When the height is locked, only the up/down keys are allowed to adjust the height + float zOffset = IS_DISABLED_CONTROL_PRESSED(2, INPUT_PARACHUTE_BRAKE_RIGHT) ? noclip_prec_level : + IS_DISABLED_CONTROL_PRESSED(2, INPUT_PARACHUTE_BRAKE_LEFT) ? -noclip_prec_level : 0.0f; + if(zOffset != 0.0f) { + g_freecam_lockedHeight += zOffset; + } + // Use locked height + Vector3 newPos = cam.GetOffsetInWorldCoords(offset - camOffset); + newPos.z = g_freecam_lockedHeight; + ent.Position_set(newPos); + } + else { + // Original code in unlocked state + offset.z = IS_DISABLED_CONTROL_PRESSED(2, INPUT_PARACHUTE_BRAKE_RIGHT) ? noclip_prec_level : + IS_DISABLED_CONTROL_PRESSED(2, INPUT_PARACHUTE_BRAKE_LEFT) ? -noclip_prec_level : 0.0f; + if(!offset.IsZero()) ent.Position_set(cam.GetOffsetInWorldCoords(offset - camOffset)); +} + + // Add right mouse button + scroll wheel to control camera FOV + if(IsKeyDown(VK_SPACE)) // Press and hold the right mouse button + { + float currentFov = cam.FieldOfView_get(); + if(IS_DISABLED_CONTROL_PRESSED(2, INPUT_CURSOR_SCROLL_UP)) // Scroll up to increase FOV + { + currentFov += MenuConfig::FreeCam::fovAdjustStep; + if(currentFov > MenuConfig::FreeCam::maxFov) + currentFov = MenuConfig::FreeCam::maxFov; + cam.FieldOfView_set(currentFov); + + // Save the current FOV as the default value + MenuConfig::FreeCam::defaultFov = currentFov; + MenuConfig::ConfigSave(); + + // Display the current FOV value + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(oss_ << "Camera FOV: " << currentFov, 0.5f, 0.95f); + + g_lastFOVValue = currentFov; + g_lastFOVDisplayTime = GetTickCount(); + } + if(IS_DISABLED_CONTROL_PRESSED(2, INPUT_CURSOR_SCROLL_DOWN)) // Scroll down to reduce FOV + { + currentFov -= MenuConfig::FreeCam::fovAdjustStep; + if(currentFov < MenuConfig::FreeCam::minFov) + currentFov = MenuConfig::FreeCam::minFov; + cam.FieldOfView_set(currentFov); + + // Save the current FOV as the default value + MenuConfig::FreeCam::defaultFov = currentFov; + MenuConfig::ConfigSave(); + + // Display the current FOV value + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(oss_ << "Camera FOV: " << currentFov, 0.5f, 0.95f); + + g_lastFOVValue = currentFov; + g_lastFOVDisplayTime = GetTickCount(); + } + + // Check if FOV text needs to be displayed + if(GetTickCount() - g_lastFOVDisplayTime < 1000) // 1秒延迟 + { + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(oss_ << "Camera FOV: " << g_lastFOVValue, 0.5f, 0.95f); + } + } //if (Menu::currentsub == SUB::CLOSED) //{ @@ -1672,6 +1814,12 @@ void set_no_clip() } } + // Check whether the lock status text needs to be displayed + if(g_lastHeightLockMessage != nullptr && GetTickCount() - g_lastHeightLockMessageTime < 1000) + { + Game::Print::setupdraw(GTAfont::Impact, Vector2(0.4f, 0.4f), true, false, false); + Game::Print::drawstring(g_lastHeightLockMessage, 0.5f, 0.95f); + } } // Playerped - ability @@ -2245,7 +2393,7 @@ inline void set_Handling_Mult69_7() if (IS_DISABLED_CONTROL_PRESSED(2, INPUT_SCRIPT_PAD_RIGHT) || IsKeyDown('D')) APPLY_FORCE_TO_ENTITY(g_myVeh, 1, mult69_7 / 220, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1, 1, 1, 0, 1); if (IS_DISABLED_CONTROL_PRESSED(2, INPUT_SCRIPT_PAD_LEFT) || IsKeyDown('A')) - APPLY_FORCE_TO_ENTITY(g_myVeh, 1, (0 - mult69_7) / 220, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1, 1, 1, 0, 1); + APPLY_FORCE_TO_ENTITY(g_myVeh, 1, (0 - mult69_7) / 220, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 1, 1, 1, 0,1); } else { @@ -2704,6 +2852,8 @@ void set_vehicle_wheels_invisible(GTAvehicle vehicle, bool enable) // Ped - ability (multiplier lists) std::map g_pedList_movGrp; std::map g_pedList_wmovGrp; +std::map g_pedList_facial_mood; + // Spooner/ped - facial mood - getter/setter std::map g_pedList_facialMood; std::string get_ped_facial_mood(GTAentity ped) diff --git a/Solution/source/Menyoo.vcxproj b/Solution/source/Menyoo.vcxproj index 71617a9c..67c8e2ff 100644 --- a/Solution/source/Menyoo.vcxproj +++ b/Solution/source/Menyoo.vcxproj @@ -328,4 +328,4 @@ - \ No newline at end of file + diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 4ded1a3a..07c896cc 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.1.4a2" +#define MENYOO_CURRENT_VER_ "2.2.0a1" #define GAME_PLAYERCOUNT 30 From fe7c3499d4887d6c9bf70763b338f7345ef278a8 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 26 Jun 2025 14:49:48 +0400 Subject: [PATCH 09/49] Delete Solution/source/_Build/bin/Release/menyooStuff/menyooLog.txt Remove Menyoolog.txt from Menyoostuff to avoid confusion --- .../bin/Release/menyooStuff/menyooLog.txt | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 Solution/source/_Build/bin/Release/menyooStuff/menyooLog.txt diff --git a/Solution/source/_Build/bin/Release/menyooStuff/menyooLog.txt b/Solution/source/_Build/bin/Release/menyooStuff/menyooLog.txt deleted file mode 100644 index d2b320b2..00000000 --- a/Solution/source/_Build/bin/Release/menyooStuff/menyooLog.txt +++ /dev/null @@ -1,27 +0,0 @@ -___ ___ _____ _ ___ _______ _____ -| \/ || ___| \ | \ \ / / _ || _ | -| . . || |__ | \| |\ V /| | | || | | | -| |\/| || __|| . ` | \ / | | | || | | | -| | | || |___| |\ | | | \ \_/ /\ \_/ / -\_| |_/\____/\_| \_/ \_/ \___/ \___/ - - -If you are reading this then Menyoo has been unable to initialise. - -Please ensure you have ScripthookV and an ASI Loader installed (available through the OpenIV app. - -If you have both of these installed, check the following logs: - -asiloader.log - Should have the below entry - ASI: Loading "[install path]\Grand Theft Auto V\Menyoo.asi" - "Menyoo.asi" => [HEX Value] - -ScriptHookV.log - Should have the below entries - [Time Stamp] INIT: Registering script 'Menyoo.asi' ([Hex Value]) - [Time Stamp] INIT: Registering additional script thread 'Menyoo.asi' ([Hex Value]) - [Time Stamp] CORE: Started thread 'Menyoo.asi' ([Hex Value]), id [int] active 1 - [Time Stamp] CORE: Started thread 'Menyoo.asi' ([Hex Value]), id [int] active 1 - [Time Stamp] CORE: Launching main() for 'Menyoo.asi' ([Hex Value]), id [int] - - -If either of these files are missing and/or not showing information about menyoo, please check the installation of all three. \ No newline at end of file From 8f3af58b6e72d6e87c8f4aa19c95b1eda639e0b6 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sun, 17 Aug 2025 18:01:25 +0400 Subject: [PATCH 10/49] Five m install instructions (#333) * Update Readme.txt * Added support for FiveM Game Build 3570 (#331) * chore(MenyooSP): add support for Game Build 3570 * build(scripthookv): updated ScriptHookV to v3586.0 * Update missing Game Builds * Add missing 3521 build (fix #309) --------- Co-authored-by: Daniel <85079899+ArnieNOR@users.noreply.github.com> --- .../ScriptHookV/SDK/lib/ScriptHookV.lib | Bin 7284 -> 7888 bytes Solution/source/Menyoo.rc | 21 +++++++++++++++--- Solution/source/_Build/bin/Release/Readme.txt | 11 ++++++++- Solution/source/main.h | 6 +++++ 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/Solution/external/ScriptHookV/SDK/lib/ScriptHookV.lib b/Solution/external/ScriptHookV/SDK/lib/ScriptHookV.lib index f0900e06f10e7ce4177665c3e9aee04b0821d45a..2e04022dd8f85a49f7495f8badb36007e0597e2d 100644 GIT binary patch delta 1620 zcma)+!A}%d9LK-246y9N&g{iseCLX+bkst>zq^bM^z0^c6X8paH#ocLRWXXp&yT9-E z_ul*c-n^IDjiD9WpBX$jICvmCKtP|EpC2LSW}N*@ru3`Fh%hV0V54hRw( zF6~AB&LqcN%zJ>qx?QD{M<#ZsipnFSFIC~ZI%AI7{Esn~UE-$!hfN+Cd#y@0k4$3H zC3*{R@bT!QN6N&-+@E3qS<#9wYa2x3UE0L z+>HRT0j#$J8wsGu<5&{7X9Blb*vZ_90V=bkvzDabS~K<5G1qlkC401$+#* z3<^T9U_wTC3@Ta>L;!7QMHD(B&|shm&1i%l5`6XY52zcc5{c8x=1b{aRhKGyADxs{ zS_yWn{^`Fj?Ud@FG(gt_&p+8!mTHfFj`q@nU^Cs6mDQD?<=e@%C1vPQTYs(U(}qdG zkRnT8uTM}iwB~ELPK8Jpy$T%>j|Y{1Yg#_@bWBxU?HP4>N81u^6^~~4gjc&1RvSg$ zZ91!V&~PYDPs884ru|~L7WuN?(Bme49XVF}Rkckzr)fcv<`6eaf=p8lY5GO$^osu0 zv{oU?vdG81q)Omp>elO2MZG$~lJ1@0XvTesQz`KpS1Lg1Cz0wfr;_<^H|L$UZHemZYegl#aXM0~`)hK0fLV|5go)Yav39 r<43(=cJCAI6mCr%jQ`zm&TU!X>#|Vb6Os1XyAtl?18mnRm&m*Y26c9M delta 1237 zcmZvbOGs2<7=~YuGtR}ioHOS(bH*E5M3yr zWM7LGL9`4~CftSD&P^b#LI+wzZQICTo1nh`{MyVh2Oj>zyzl#6{xkErztr>833lc( z-PyCb9x4Rvhvza~P3~th4B#XXEdr_mXnDXXNz&7R%Pyacxh1jI0hb{@8GB=&EvnNSz11`gSGS0lj=;i>UuL?-h#%LkdvDTn0`VXy>{kM+A z`xK*`Q-Qn&lpJ6>4eT;oCa}(iA!fq{x|miSC?tRZ)(QqNlLGdb?IbYF%yYh*zh7k^ z-xH#Uz=DZ5VhA9FAZpPUhK>YOXfWV|A2q0ga-{V?CoKmb(^u>C+U-!WislrXW^2E! z-H+T<=y&X5<(d{v#MRKm*yatr3JB6WElo9gnpWbo%7a;YskhLG+AALKBpiCJ?s&s5 zG}R}<^j2Fs@Q)`V(tp|GH9KVCnA7^s~!HJJxlt zJYws$qR0i7{cKqFWhi8~lud2fS z3$e!!$MB0~^EBmHboVIBqqLl(o$EyDRr*qS4pE_U%osJ+Rg5X*r8=2D#_2e{smpoN z&+6q1%do177q$> Date: Sun, 17 Aug 2025 19:30:14 +0400 Subject: [PATCH 11/49] Update master_build.yml (#336) * Five m install instructions (#332) * Fix freeze & crash while Loading Benchmark From loading screens (#269) * #218 (#226) * #218 - Corrected and enchanced/refactored teleport to waypoint * #218 - Removed duplicate declaration of ____gtaGroundCheckHeight array * Update macros.h * Improve Gen 9 Warning (#227) * Improve Gen 9 Warning - Update on-screen warning text with clearer instructions - Add explicit list of gen9 dlcs to menyoolog - Add two new g9 dlcs to check list - Add check for mp2024 bugged dlc (temp until r* fix) * UpVersion for Pre-release * Missing game build (#228) * Fix Missing Game Build Add 3407 to Main.h * Fix Missing Game Build Add 3407 to Menyoo.rc * UpVersion for Pre-release * Fix #232 (#233) * Remove playsound on doors Comment out play sound line * UpVersion for Pre-release * Blip fix (#236) * Update GTAblip.h (#234) Fixed Deluxo duplicate mishap. Duplicate reassigned to Toreador. * Update GTAblip.cpp (#235) Duplicate Deluxo reassigned to Toreador. * UpVersion for Prerelease --------- Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> * Blip fix patch (#240) * Update GTAblip.h (#237) Renamed duplicate Deluxo to 'Toreador'. * Update GTAblip.cpp (#238) Renamed duplicate Deluxo to 'Toreador'. --------- Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> * Achievement unlocks (#245) * UpVersion for Pre-release * Add more achievement options (#242) - Update the number achievements to 77 - Add menu options to unlock individual achievements --------- Co-authored-by: frankie2d * Update Readme.txt * Actions Improvements (#254) * Update msbuild.yml - Migrate build artefact from v3 to v4 * Update master_build.yml - Remove exit 1 for successful cancellations - Add CANCELJOB to skip unnecessary steps and jobs * Aos blips (#251) * Agents of Sabotage blips (#247) * Update GTAblip.h Added Agents of Sabotage blips! * Update GTAblip.cpp Added Agents of Sabotage blips. * UpVersion for Pre-release --------- Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> * Update master_build.yml * Aos blips fix (#255) * Update GTAblip.cpp * Update GTAblip.h Add missing comma to std::map for blips. * 3442 build (#258) * Update Menyoo.rc Add 3442 FX ASI Build * Update main.h Add 3442 Version * UpVersion for Pre-release * Update macros.h * Fix freeze & crash on Loading Benchmark Fixes a freeze and then a crash while loading Benchmark from anything except the Pause Menu --------- Co-authored-by: ShawnPR1 <31240808+ShawnPR1@users.noreply.github.com> Co-authored-by: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> Co-authored-by: frankie2d * Update Readme.txt * Added support for FiveM Game Build 3570 (#331) * chore(MenyooSP): add support for Game Build 3570 * build(scripthookv): updated ScriptHookV to v3586.0 * Update missing Game Builds --------- Co-authored-by: LuisYeah1234-hub <64372171+LuisYeah1234-hub@users.noreply.github.com> Co-authored-by: ShawnPR1 <31240808+ShawnPR1@users.noreply.github.com> Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> Co-authored-by: frankie2d Co-authored-by: Daniel <85079899+ArnieNOR@users.noreply.github.com> * Update master_build.yml --------- Co-authored-by: LuisYeah1234-hub <64372171+LuisYeah1234-hub@users.noreply.github.com> Co-authored-by: ShawnPR1 <31240808+ShawnPR1@users.noreply.github.com> Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> Co-authored-by: frankie2d Co-authored-by: Daniel <85079899+ArnieNOR@users.noreply.github.com> --- .github/workflows/master_build.yml | 1 - Solution/source/macros.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 207a24a9..6ab93c16 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -108,7 +108,6 @@ jobs: - name: Set output id: set_output - if: env.CANCELJOB != 'true' run: echo "CANCELJOB=${{ env.CANCELJOB }}" >> $GITHUB_OUTPUT build: diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 07c896cc..f34e5da5 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,6 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS + #define MENYOO_CURRENT_VER_ "2.2.0a1" #define GAME_PLAYERCOUNT 30 From 94801e343a13f6f72069654c7ac76d23afd6a9db Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Mon, 27 Oct 2025 23:30:40 +0400 Subject: [PATCH 12/49] Enhanced (#354) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial code edits: added log points and bypassed initial memory checks * Fixed vehicle memory address issue * Reverted logging issues * Added FiveM install instructions (#332) * Fixed freeze/crash while loading Benchmark from loading screens (#269) * Teleport & Ground Check Updates (#218, #226) * Refactored “Teleport to Waypoint” * Removed duplicate declaration of ____gtaGroundCheckHeight array * Improved Gen 9 Warning (#227) * Clarified on-screen text and added explicit DLC list * Included new DLC checks and temporary mp2024 workaround * Game Build Support Updates * Added builds 3407, 3442, and 3570 * Updated Main.h, Menyoo.rc, and macros.h accordingly * Blip Fixes & Additions * Fixed duplicate Deluxo → reassigned to Toreador (#234–240) * Added Agents of Sabotage blips (#247, #251, #255) * Achievements Improvements (#242, #245) * Increased achievements to 77 * Added menu options to unlock individual achievements * CI & Actions Improvements (#254) * Migrated build artifacts (v3 → v4) * Improved job cancellation handling and reduced redundant steps * Freeze/Crash Fix * Fixed freeze/crash when loading Benchmark from non-pause-menu screens * FiveM Enhancements & Compatibility (#331, #352) * Added enhanced FiveM and game build support * Updated ScriptHookV to v3586.0 * Merged enhanced feature branches and updated version numbers Co-authored-by: LuisYeah1234-hub <64372171+LuisYeah1234-hub@users.noreply.github.com> Co-authored-by: ShawnPR1 <31240808+ShawnPR1@users.noreply.github.com> Co-authored-by: ThatRealSpicyDragon <158034338+ThatRealSpicyDragon@users.noreply.github.com> Co-authored-by: frankie2d Co-authored-by: Daniel <85079899+ArnieNOR@users.noreply.github.com> Co-authored-by: Chiheb Bacha --- .github/workflows/master_build.yml | 1 + Solution/source/Memory/GTAmemory.cpp | 1971 +++++++++++++----- Solution/source/Memory/GTAmemory.h | 426 ++-- Solution/source/Menu/Menu.cpp | 29 +- Solution/source/Menu/MenuConfig.cpp | 1 + Solution/source/Menu/Routine.cpp | 184 +- Solution/source/Menyoo.rc | 5 + Solution/source/Menyoo.vcxproj | 2 +- Solution/source/Menyoo.vcxproj.filters | 2 + Solution/source/Scripting/ModelNames.cpp | 5 +- Solution/source/Scripting/World.cpp | 12 +- Solution/source/Submenus/MainMenu.cpp | 7 + Solution/source/Submenus/PedModelChanger.cpp | 25 +- Solution/source/Submenus/PlayerOptions.cpp | 10 +- Solution/source/Submenus/WeatherOptions.cpp | 12 +- Solution/source/Util/FileLogger.cpp | 112 +- Solution/source/Util/FileLogger.h | 2 + Solution/source/macros.h | 3 +- Solution/source/main.cpp | 30 +- Solution/source/main.h | 14 + 20 files changed, 2078 insertions(+), 775 deletions(-) diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 6ab93c16..207a24a9 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -108,6 +108,7 @@ jobs: - name: Set output id: set_output + if: env.CANCELJOB != 'true' run: echo "CANCELJOB=${{ env.CANCELJOB }}" >> $GITHUB_OUTPUT build: diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index 132fa7d7..1c9afab1 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -46,31 +46,56 @@ MODULEINFO g_MainModuleInfo = { 0 }; ScriptTable* scriptTable; ScriptHeader* shopController; -typedef CVehicleModelInfo*(*GetModelInfo_t)(unsigned int modelHash, int* index); -typedef CVehicleModelInfo*(*InitVehicleArchetype_t)(const char*, bool, unsigned int); +typedef CVehicleModelInfo* (*GetModelInfo_t)(unsigned int modelHash, int* index); +typedef CVehicleModelInfo* (*InitVehicleArchetype_t)(const char*, bool, unsigned int); +typedef CVehicleModelInfo* (*InitVehicleArchetypeEnhanced_t)(uint32_t, const char*); GetModelInfo_t GetModelInfo; std::unordered_map g_vehicleHashes; -CallHook * g_InitVehicleArchetype = nullptr; +CallHook* g_InitVehicleArchetypeLegacy = nullptr; CVehicleModelInfo* initVehicleArchetype_stub(const char* name, bool a2, unsigned int a3) { g_vehicleHashes.insert({ GET_HASH_KEY(name), boost::to_lower_copy(name) }); - return g_InitVehicleArchetype->fn(name, a2, a3); + return g_InitVehicleArchetypeLegacy->fn(name, a2, a3); } + +// InitVehicleArchetype has been inlined in Enhanced, instead we hook one of functions which are called after it and take its first parameter. +CallHook* g_InitVehicleArchetypeEnhanced = nullptr; +CVehicleModelInfo* initVehicleArchetypeEnhanced_stub(uint32_t a1, const char* name) { + g_vehicleHashes.insert({ GET_HASH_KEY(name), name }); + return g_InitVehicleArchetypeEnhanced->fn(a1, name); +} + void setupHooks() { - auto addr = GTAmemory::FindPattern("\xE8\x00\x00\x00\x00\x48\x8B\x4D\xE0\x48\x8B\x11", "x????xxxxxxx"); - if (!addr) { - addlog(ige::LogType::LOG_ERROR, "Couldn't find InitVehicleArchetype", __FILENAME__); - return; + + if (g_isEnhanced) { + auto addr = MemryScan::PatternScanner::FindPattern("e8 ? ? ? ? 43 89 44 2c"); + if (!addr) { + addlog(ige::LogType::LOG_ERROR, "Couldn't find InitVehicleArchetypeEnahnced", __FILENAME__); + return; + } + addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at " + std::to_string(addr), __FILENAME__); + g_InitVehicleArchetypeEnhanced = HookManager::SetCall(addr, initVehicleArchetypeEnhanced_stub); + } + else { + auto addr = GTAmemory::FindPattern("\xE8\x00\x00\x00\x00\x48\x8B\x4D\xE0\x48\x8B\x11", "x????xxxxxxx"); + if (!addr) { + addlog(ige::LogType::LOG_ERROR, "Couldn't find InitVehicleArchetype", __FILENAME__); + return; + } + addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at " + std::to_string(addr), __FILENAME__); + g_InitVehicleArchetypeLegacy = HookManager::SetCall(addr, initVehicleArchetype_stub); } - addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at "+std::to_string(addr), __FILENAME__); - g_InitVehicleArchetype = HookManager::SetCall(addr, initVehicleArchetype_stub); } void removeHooks() { - if (g_InitVehicleArchetype) { - delete g_InitVehicleArchetype; - g_InitVehicleArchetype = nullptr; + if (g_InitVehicleArchetypeLegacy) { + delete g_InitVehicleArchetypeLegacy; + g_InitVehicleArchetypeLegacy = nullptr; + } + if (g_InitVehicleArchetypeEnhanced) { + delete g_InitVehicleArchetypeEnhanced; + g_InitVehicleArchetypeEnhanced = nullptr; } } template R GetMultilayerPointer(void* base, const std::vector& offsets) @@ -159,6 +184,8 @@ namespace MemryScan } } + addlog(ige::LogType::LOG_ERROR, "Pattern " + s + " not found", __FILENAME__); + return NULL; } DWORD64 Pattern::Scan(MODULEINFO mi, const std::string& s) @@ -166,7 +193,7 @@ namespace MemryScan return Scan((DWORD64)mi.lpBaseOfDll, (DWORD64)mi.SizeOfImage, s); } - bool PatternScanner::CompareMemory(const BYTE *data, const BYTE *pattern, const char *mask) + bool PatternScanner::CompareMemory(const BYTE* data, const BYTE* pattern, const char* mask) { for (; *mask; ++mask, ++data, ++pattern) { @@ -206,7 +233,7 @@ namespace MemryScan for (i = 0; i < size; ++i) { - if (CompareMemory((BYTE *)(address + i), (BYTE *)search.data(), mask.data())) + if (CompareMemory((BYTE*)(address + i), (BYTE*)search.data(), mask.data())) { return (DWORD64)(address + i); } @@ -289,25 +316,25 @@ UINT64(*GTAmemory::_entityAddressFunc)(int handle); UINT64(*GTAmemory::_playerAddressFunc)(int handle); UINT64(*GTAmemory::_ptfxAddressFunc)(int handle); int(*GTAmemory::_addEntityToPoolFunc)(UINT64 address); -UINT64(*GTAmemory::_entityPositionFunc)(UINT64 address, float *position); +UINT64(*GTAmemory::_entityPositionFunc)(UINT64 address, float* position); UINT64(*GTAmemory::_entityModel1Func)(UINT64 address), (*GTAmemory::_entityModel2Func)(UINT64 address); -UINT64 *GTAmemory::_entityPoolAddress, *GTAmemory::_vehiclePoolAddress, *GTAmemory::_pedPoolAddress, *GTAmemory::_objectPoolAddress, *GTAmemory::_cameraPoolAddress, *GTAmemory::_pickupObjectPoolAddress; unsigned char(*GTAmemory::SetNmBoolAddress)(__int64, __int64, unsigned char); unsigned char(*GTAmemory::SetNmIntAddress)(__int64, __int64, int); unsigned char(*GTAmemory::SetNmFloatAddress)(__int64, __int64, float); unsigned char(*GTAmemory::SetNmVec3Address)(__int64, __int64, float, float, float); unsigned char(*GTAmemory::SetNmStringAddress)(__int64, __int64, __int64); -UINT64 GTAmemory::CreateNmMessageFunc, GTAmemory::GiveNmMessageFunc; +UINT64(*GTAmemory::CreateNmMessageFunc)(uint64_t, uint64_t, int); +void(*GTAmemory::GiveNmMessageFunc)(uint64_t, void*, uint64_t); UINT64(*GTAmemory::CheckpointBaseAddr)(); UINT64(*GTAmemory::CheckpointHandleAddr)(UINT64 baseAddr, int Handle); -UINT64 *GTAmemory::checkpointPoolAddress; -float *GTAmemory::_readWorldGravityAddress, *GTAmemory::_writeWorldGravityAddress; -UINT64 *GTAmemory::_gamePlayCameraAddr; -int*GTAmemory:: _cursorSpriteAddr; +UINT64* GTAmemory::checkpointPoolAddress; +float* GTAmemory::_readWorldGravityAddress, * GTAmemory::_writeWorldGravityAddress; +UINT64* GTAmemory::_gamePlayCameraAddr; +int* GTAmemory::_cursorSpriteAddr; INT32* GTAmemory::_transitionStatus = nullptr; UINT64 GTAmemory::_gxtLabelFromHashAddr1; -char*(__fastcall *GTAmemory::_gxtLabelFromHashFuncAddr)(UINT64 address, unsigned int hash); +char* (__fastcall* GTAmemory::_gxtLabelFromHashFuncAddr)(UINT64 address, unsigned int hash); /*struct EntityPoolTask { @@ -499,11 +526,49 @@ class EntityPool return num1 - (num2 & 0x3FFFFFFF) <= 256; } }; + +class EntityPoolEnhanced +{ +public: + char _padding0[24]; + UINT32 num1; + char _padding1[12]; + UINT32 num2; + + inline bool Full() + { + return num1 - (num2 & 0x3FFFFFFF) <= 256; + } +}; + class VehiclePool { public: //char _padding0[0]; - UINT64 *poolAddress; + UINT64* poolAddress; + //char _padding1[0]; + UINT32 size; + char _padding2[36]; + UINT32* bitArray; + char _padding3[40]; + UINT32 itemCount; + + inline bool isValid(UINT32 i) + { + return (bitArray[i >> 5] >> (i & 0x1F)) & 1; + } + + inline UINT64 getAddress(UINT32 i) + { + return poolAddress[i]; + } +}; +class VehiclePoolEnhanced +{ +public: + void* vptr; + //char _padding0[0]; + UINT64* poolAddress; //char _padding1[0]; UINT32 size; char _padding2[36]; @@ -529,7 +594,37 @@ class GenericPool { BYTE* byteArray; //char _padding2[0]; UINT32 size; + //char _padding3[0]; + UINT32 itemSize; + + + inline bool isValid(UINT32 i) + { + return mask(i) != 0; + } + + inline UINT64 getAddress(UINT32 i) + { + return mask(i) & (poolStartAddress + i * itemSize); + } +private: + inline long long mask(UINT32 i) + { + long long num1 = byteArray[i] & 0x80; + return ~((num1 | -num1) >> 63); + } +}; +// TODO +class GenericPoolEnhanced { +public: + void* vptr; + //char _padding0[0]; + UINT64 poolStartAddress; + //char _padding1[0]; + BYTE* byteArray; //char _padding2[0]; + UINT32 size; + //char _padding3[0]; UINT32 itemSize; @@ -567,12 +662,48 @@ struct EntityPoolTask { } + static uintptr_t GetModelInfo(uintptr_t entityAddress) + { + if (entityAddress) + { + return entityAddress + 0x20; + } + + return (uintptr_t)(0); + } + // Unchanged in Enhanced. + static int GetModelHashFromFwArcheType(uintptr_t fwArcheTypeAddress) + { + if (fwArcheTypeAddress) + { + return *reinterpret_cast(fwArcheTypeAddress + 0x18); + } + + return 0; + } + static int GetModelHashFromEntity(uintptr_t entityAddress) + { + if (!entityAddress) + { + return 0; + } + + auto modelInfoAddress = GetModelInfo(entityAddress); + if (modelInfoAddress) + { + return GetModelHashFromFwArcheType(modelInfoAddress); + } + + return 0; + } + + inline bool CheckEntity(uintptr_t address) { if (_posCheck) { float position[3]; - GTAmemory::_entityPositionFunc(address, position); + GTAmemory::GetEntityPos(address, position); // replaced _getEntityPos with a call to GetEntityPos which implements the same function for enhanced (because it was inlined), and calls the old function for legacy. if (Vector3::Subtract(_position, Vector3(position[0], position[1], position[2])).LengthSquared() > _radiusSquared) { @@ -582,25 +713,38 @@ struct EntityPoolTask if (_modelCheck) { - UINT32 v0 = *reinterpret_cast(GTAmemory::_entityModel1Func(*reinterpret_cast(address + 32))); - UINT32 v1 = v0 & 0xFFFF; - UINT32 v2 = ((v1 ^ v0) & 0x0FFF0000 ^ v1) & 0xDFFFFFFF; - UINT32 v3 = ((v2 ^ v0) & 0x10000000 ^ v2) & 0x3FFFFFFF; - const uintptr_t v5 = GTAmemory::_entityModel2Func(reinterpret_cast(&v3)); - - - if (!v5) - { + if (g_isEnhanced) { + // This should be equivalent to what we have in legacy. + int modelHash = GetModelHashFromEntity(address); + for (int hash : _modelHashes) { + if (modelHash == hash) + { + return true; + } + } return false; } - for (int hash : _modelHashes) - { - if (*reinterpret_cast(v5 + 24) == hash) + else { + UINT32 v0 = *reinterpret_cast(GTAmemory::_entityModel1Func(*reinterpret_cast(address + 32))); + UINT32 v1 = v0 & 0xFFFF; + UINT32 v2 = ((v1 ^ v0) & 0x0FFF0000 ^ v1) & 0xDFFFFFFF; + UINT32 v3 = ((v2 ^ v0) & 0x10000000 ^ v2) & 0x3FFFFFFF; + const uintptr_t v5 = GTAmemory::_entityModel2Func(reinterpret_cast(&v3)); + + + if (!v5) { - return true; + return false; } + for (int hash : _modelHashes) + { + if (*reinterpret_cast(v5 + 24) == hash) + { + return true; + } + } + return false; } - return false; } return true; @@ -608,27 +752,64 @@ struct EntityPoolTask void Run(std::vector& _handles) { - if (*GTAmemory::_entityPoolAddress == 0) - { - return; + if (g_isEnhanced) { + if (GTAmemory::_entityPoolAddress == 0) + { + return; + } + } + else { + if (*GTAmemory::_entityPoolAddress == 0) + { + return; + } + } + + EntityPool* entityPool; + EntityPoolEnhanced* entityPoolEnhanced; + + if (g_isEnhanced) { + entityPoolEnhanced = reinterpret_cast(*GTAmemory::_entityPoolAddress); + } + else { + entityPool = reinterpret_cast(*GTAmemory::_entityPoolAddress); } - EntityPool* entityPool = reinterpret_cast(*GTAmemory::_entityPoolAddress); if (TypeHasFlag(Type::Vehicle)) { if (*GTAmemory::_vehiclePoolAddress) { - VehiclePool* vehiclePool = *reinterpret_cast(*GTAmemory::_vehiclePoolAddress); + // could definitely be refactored to avoid the duplicate code + if (g_isEnhanced) { - for (UINT32 i = 0; i < vehiclePool->size; i++) - { - //if (entityPool->Full()) break; - if (vehiclePool->isValid(i)) + VehiclePoolEnhanced* vehiclePool = *reinterpret_cast(*GTAmemory::_vehiclePoolAddress); + + for (UINT32 i = 0; i < vehiclePool->size; i++) + { + //if (entityPoolEnhanced->Full()) break; + if (vehiclePool->isValid(i)) + { + UINT64 address = vehiclePool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } + } + } + } + else { + VehiclePool* vehiclePool = *reinterpret_cast(*GTAmemory::_vehiclePoolAddress); + + for (UINT32 i = 0; i < vehiclePool->size; i++) { - UINT64 address = vehiclePool->getAddress(i); - if (address && CheckEntity(address)) + //if (entityPool->Full()) break; + if (vehiclePool->isValid(i)) { - _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + UINT64 address = vehiclePool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } } } } @@ -636,39 +817,82 @@ struct EntityPoolTask } if (TypeHasFlag(Type::Ped)) { - if (*GTAmemory::_pedPoolAddress) - { - GenericPool* pedPool = reinterpret_cast(*GTAmemory::_pedPoolAddress); + if (g_isEnhanced) { + if (GTAmemory::_pedPoolAddress) + { + GenericPoolEnhanced* pedPool = reinterpret_cast(GTAmemory::_pedPoolAddress); - for (UINT32 i = 0; i < pedPool->size; i++) + for (UINT32 i = 0; i < pedPool->size; i++) + { + //if (entityPool->Full()) break; + if (pedPool->isValid(i)) + { + UINT64 address = pedPool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } + } + } + } + } + else { + if (*GTAmemory::_pedPoolAddress) { - //if (entityPool->Full()) break; - if (pedPool->isValid(i)) + GenericPool* pedPool = reinterpret_cast(*GTAmemory::_pedPoolAddress); + + for (UINT32 i = 0; i < pedPool->size; i++) { - UINT64 address = pedPool->getAddress(i); - if (address && CheckEntity(address)) + //if (entityPool->Full()) break; + if (pedPool->isValid(i)) { - _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + UINT64 address = pedPool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } } } } } + } if (TypeHasFlag(Type::Prop)) { - if (*GTAmemory::_objectPoolAddress) - { - GenericPool* propPool = reinterpret_cast(*GTAmemory::_objectPoolAddress); + if (g_isEnhanced) { + if (GTAmemory::_objectPoolAddress) + { + GenericPoolEnhanced* propPool = reinterpret_cast(GTAmemory::_objectPoolAddress); - for (UINT32 i = 0; i < propPool->size; i++) + for (UINT32 i = 0; i < propPool->size; i++) + { + //if (entityPool->Full()) break; + if (propPool->isValid(i)) + { + UINT64 address = propPool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } + } + } + } + } + else { + if (*GTAmemory::_objectPoolAddress) { - //if (entityPool->Full()) break; - if (propPool->isValid(i)) + GenericPool* propPool = reinterpret_cast(*GTAmemory::_objectPoolAddress); + + for (UINT32 i = 0; i < propPool->size; i++) { - UINT64 address = propPool->getAddress(i); - if (address && CheckEntity(address)) + //if (entityPool->Full()) break; + if (propPool->isValid(i)) { - _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + UINT64 address = propPool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } } } } @@ -676,27 +900,56 @@ struct EntityPoolTask } if (TypeHasFlag(Type::PickupObject)) { - if (*GTAmemory::_pickupObjectPoolAddress) - { - GenericPool* pickupPool = reinterpret_cast(*GTAmemory::_pickupObjectPoolAddress); + if (g_isEnhanced) { + if (GTAmemory::_pickupObjectPoolAddress) + { + GenericPoolEnhanced* pickupPool = reinterpret_cast(GTAmemory::_pickupObjectPoolAddress); - for (UINT32 i = 0; i < pickupPool->size; i++) + for (UINT32 i = 0; i < pickupPool->size; i++) + { + //if (entityPool->Full()) break; + if (pickupPool->isValid(i)) + { + UINT64 address = pickupPool->getAddress(i); + if (address) + { + if (_posCheck) + { + float* position = (float*)(address + 0x90); + if (Vector3::Subtract(_position, Vector3(position[0], position[1], position[2])).LengthSquared() > _radiusSquared) + { + continue; + } + } + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } + } + } + } + } + else { + if (*GTAmemory::_pickupObjectPoolAddress) { - //if (entityPool->Full()) break; - if (pickupPool->isValid(i)) + GenericPool* pickupPool = reinterpret_cast(*GTAmemory::_pickupObjectPoolAddress); + + for (UINT32 i = 0; i < pickupPool->size; i++) { - UINT64 address = pickupPool->getAddress(i); - if (address) + //if (entityPool->Full()) break; + if (pickupPool->isValid(i)) { - if (_posCheck) + UINT64 address = pickupPool->getAddress(i); + if (address) { - float* position = (float*)(address + 0x90); - if (Vector3::Subtract(_position, Vector3(position[0], position[1], position[2])).LengthSquared() > _radiusSquared) + if (_posCheck) { - continue; + float* position = (float*)(address + 0x90); + if (Vector3::Subtract(_position, Vector3(position[0], position[1], position[2])).LengthSquared() > _radiusSquared) + { + continue; + } } + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); } - _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); } } } @@ -719,160 +972,767 @@ struct GenericTask GenericTask(func pFunc, UINT64 Arg) : _toRun(pFunc), _arg(Arg) { } - virtual void Run() - { - _res = _toRun(_arg); + virtual void Run() + { + _res = _toRun(_arg); + } + + UINT64 GetResult() + { + return _res; + } + +private: + func _toRun; + UINT64 _arg; + UINT64 _res; +}; + +#pragma region -- Helpers needed for Enhanced -- + +uint64_t(*s_getScriptEntity)(int handle); +uint64_t s_ptfxEntityVPtr; +uint8_t(*s_isPtfxEntityUsableVFunc)(uint64_t entity, uint64_t arg2, uint64_t vptr); + +uint64_t s_PtfxVfuncSecondArgumentFuncAddr; +uint64_t* s_PtfxHashTableCount; +uint64_t* s_PtfxHashTableBuckets; + +static void* GetPtfxAddressFunc(int handle); +static bool IsPtfxEntityUsable(uint64_t entity); + +static bool IsPtfxEntityUsable(uint64_t entity) +{ + if (entity == 0) + return false; + + // Cache vptr and the vfunc at 0x28 + if (!s_isPtfxEntityUsableVFunc || s_ptfxEntityVPtr == 0) + { + s_ptfxEntityVPtr = *reinterpret_cast(entity); + if (s_ptfxEntityVPtr == 0) + return false; + + uintptr_t funcPtr = *reinterpret_cast(s_ptfxEntityVPtr + 0x28); + if (funcPtr == 0) + return false; + + s_isPtfxEntityUsableVFunc = reinterpret_cast< + uint8_t(*)(uint64_t, uint64_t, uint64_t) + >(funcPtr); + } + + int result = s_isPtfxEntityUsableVFunc( + entity, + s_PtfxVfuncSecondArgumentFuncAddr, + s_ptfxEntityVPtr + ); + + return result != 0; +} + +static void* GetPtfxAddressFunc(int handle) +{ + uint64_t entity = s_getScriptEntity(handle); + if (entity == 0 || !IsPtfxEntityUsable(entity)) + return nullptr; + + if (!s_PtfxHashTableCount || !s_PtfxHashTableBuckets) + return nullptr; + if (*s_PtfxHashTableCount == 0 || *s_PtfxHashTableBuckets == 0) + return nullptr; + + uint32_t keyed = static_cast(handle + 0x10000000); + uint32_t count = static_cast(*s_PtfxHashTableCount); + uint32_t index = keyed % count; + + auto** bucketsBase = reinterpret_cast(*s_PtfxHashTableBuckets); + uint64_t* node = reinterpret_cast(bucketsBase[index]); + + while (node != nullptr) + { + uint64_t key = *node; + if (key == keyed) + { + uint64_t A = *(node + 1); + if (A == 0) + return nullptr; + return reinterpret_cast(A); + } + node = *reinterpret_cast(node + 2); + } + + return nullptr; +} + +uint64_t s_entityVPtr; +uint8_t(*s_isEntityUsableVFunc)(uint64_t entity, uint64_t arg2); +uint64_t s_entityPosVFuncSecondArgument; + +uintptr_t s_pedEntityPosSecondCheckOffset; +uintptr_t s_entityPosFloatsOffset; +uintptr_t s_entityInternalTypeOffset; +uintptr_t s_pedEntityInVehicleCheckOffset; + +enum EntityTypeInternal +{ + TypeInvalid = 0, + TypeBuilding = 1, + TypeAnimatedBuilding = 2, + TypeVehicle = 3, + TypePed = 4, + TypeObject = 5, + TypeParticleEffect = 48 +}; + +static bool IsEntityUsable(uint64_t entity); +static EntityTypeInternal GetEntityTypeInternal(uint64_t address); +static uint64_t GetVehiclePedIsIn(uint64_t address); +static void GetEntityPos(uint64_t address, float* position); + +static bool IsEntityUsable(uint64_t entity) +{ + if (entity == 0) + return false; + + if (!s_isEntityUsableVFunc || s_entityVPtr == 0) + { + s_entityVPtr = *reinterpret_cast(entity); + if (s_entityVPtr == 0) + return false; + + uintptr_t funcPtr = *reinterpret_cast(s_entityVPtr + 0x28); + if (funcPtr == 0) + return false; + + s_isEntityUsableVFunc = reinterpret_cast(funcPtr); + } + + int result = s_isEntityUsableVFunc(entity, s_entityPosVFuncSecondArgument); + return result != 0; +} + +void GTAmemory::GetEntityPos(uint64_t address, float* position) +{ + if (address == 0) + { + position[0] = position[1] = position[2] = 0.0f; + return; + } + + if (g_isEnhanced) + { + if (IsEntityUsable(address)) + { + if (GetEntityTypeInternal(address) == EntityTypeInternal::TypePed) + { + if (*(uint8_t*)(address + s_pedEntityPosSecondCheckOffset) != 0x40) + { + uint64_t vehicleAddress = GetVehiclePedIsIn(address); + if (vehicleAddress != 0) + address = vehicleAddress; + } + } + + position[0] = *(float*)(address + s_entityPosFloatsOffset); + position[1] = *(float*)(address + s_entityPosFloatsOffset + 4); + position[2] = *(float*)(address + s_entityPosFloatsOffset + 8); + } + else + { + position[0] = position[1] = position[2] = 0.0f; + } + } + else + { + GTAmemory::_entityPositionFunc(address, position); + } +} + +static EntityTypeInternal GetEntityTypeInternal(uint64_t address) +{ + uint8_t type = *(uint8_t*)(address + s_entityInternalTypeOffset); + return static_cast(type); +} + +static uint64_t GetVehiclePedIsIn(uint64_t address) +{ + return *(uint64_t*)(address + s_pedEntityInVehicleCheckOffset); +} + +static uint64_t Rol(uint64_t value, int count) +{ + count &= 63; + return (value << count) | (value >> (64 - count)); +} + +#pragma endregion + +void GTAmemory::Init() +{ + UINT64 address; + + // Get relative address and add it to the instruction address. + // 3 bytes equal the size of the opcode and its first argument. 7 bytes are the length of opcode and all its parameters. + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("48 8d 3d ? ? ? ? 48 8b 04 f7"); + } + else { + address = FindPattern("\x4C\x8D\x05\x00\x00\x00\x00\x0F\xB7\xC1", "xxx????xxx"); + } + if (address) _blipList = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("41 57 41 56 56 57 53 48 83 ec ? 89 d7 49 89 ce"); + } + else { + address = FindPattern("\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x18\x89\x54\x24\x10\x56\x57\x41\x56\x48\x83\xEC\x20\x48\x8B\xD9", "xxxxxxxxxxxxxxxxxxxxxxxxx"); + } + if (address) _gxtLabelFromHashFuncAddr = reinterpret_cast(address); + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("85 c0 74 ? 48 8d 0d ? ? ? ? 48 89 da e8"); + } + else { + address = FindPattern("\x84\xC0\x74\x34\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\xD3", "xxxxxxx????xxx"); + } + if (address) _gxtLabelFromHashAddr1 = *reinterpret_cast(address + 7) + address + 11; + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("41 8b 4c 1c ? e8"); + // This function is not 100% the same as in legacy. The one from legacy was inlined in Enhanced, + // so that we can only call the function that returns an entitys address from its guid, but need to implement the vfunc call that comes after it on our own. + // That vfunc doesn't always take the same parameters, and it seems to not be necessary for the correct functioning of this function, + // so we will leave it out in general, and implement it for some specific functions (see GetPtfxAddress). + _entityAddressFunc = reinterpret_cast(*reinterpret_cast(address + 6) + address + 10); + + address = MemryScan::PatternScanner::FindPattern("89 f1 b2 ? e8 ? ? ? ? 31 c9 48"); + _playerAddressFunc = reinterpret_cast(*reinterpret_cast(address + 5) + address + 9); + + // entityPositionFunc was inlined in Enhanced. We reimplement it ourselves. + address = MemryScan::PatternScanner::FindPattern("0f 84 ? ? ? ? f3 0f 10 bc 24 30 01 00 00"); + s_entityPosVFuncSecondArgument = (uint64_t)(*(int*)(address - 12) + address - 8); + + address = MemryScan::PatternScanner::FindPattern("31 c0 80 7f ? ? 48 0f 45 f8 0f 85 ? ? ? ? e9"); + address = *(int*)(address + 17) + address + 21; + s_pedEntityPosSecondCheckOffset = *(int*)(address + 2); + address = *(int*)(address + 14) + address + 18; + s_pedEntityInVehicleCheckOffset = *(int*)(address + 3); + + address = MemryScan::PatternScanner::FindPattern("0f 28 8f ? ? ? ? f3 0f 10 b7 ? ? ? ? f3 0f 16 c1 e9"); + s_entityPosFloatsOffset = *(int*)(address + 3); + + address = MemryScan::PatternScanner::FindPattern("48 89 d6 0f b6 42 ? 04 ? 3c ? 0f 87 ? ? ? ? e9"); + address = *(int*)(address + 13) + address + 17; + address = *(int*)(address + 1) + address + 5; + s_entityInternalTypeOffset = *(byte*)(address + 2); + + + address = MemryScan::PatternScanner::FindPattern("0c ? 88 46 ? 48 8b 4e ? e8"); + _entityModel1Func = reinterpret_cast(*reinterpret_cast(address + 10) + address + 14); + + } + else { + if (GTAmemory::GetGameVersion() >= eGameVersion::VER_1_0_1290_1_STEAM) + { + address = FindPattern("\xE8\x00\x00\x00\x00\x48\x8B\xD8\x48\x85\xC0\x74\x2E\x48\x83\x3D", "x????xxxxxxxxxxx"); + _entityAddressFunc = reinterpret_cast(*reinterpret_cast(address + 1) + address + 5); + address = FindPattern("\xB2\x01\xE8\x00\x00\x00\x00\x48\x85\xC0\x74\x1C\x8A\x88", "xxx????xxxxxxx"); + _playerAddressFunc = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + address = FindPattern("\x48\x8B\xDA\xE8\x00\x00\x00\x00\xF3\x0F\x10\x44\x24", "xxxx????xxxxx"); + _entityPositionFunc = reinterpret_cast(address - 6); + address = FindPattern("\x0F\x85\x00\x00\x00\x00\x48\x8B\x4B\x20\xE8\x00\x00\x00\x00\x48\x8B\xC8", "xx????xxxxx????xxx"); + _entityModel1Func = reinterpret_cast(*reinterpret_cast(address + 11) + address + 15); + address = FindPattern("\x45\x33\xC9\x3B\x05", "xxxxx"); + _entityModel2Func = reinterpret_cast(address - 0x46); + + address = FindPattern("\x4C\x8B\x05\x00\x00\x00\x00\x40\x8A\xF2\x8B\xE9", "xxx????xxxxx"); + _pickupObjectPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + } + else + { + address = FindPattern("\x33\xFF\xE8\x00\x00\x00\x00\x48\x85\xC0\x74\x58", "xxx????xxxxx"); + _entityAddressFunc = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + address = FindPattern("\xB2\x01\xE8\x00\x00\x00\x00\x33\xC9\x48\x85\xC0\x74\x3B", "xxx????xxxxxxx"); + _playerAddressFunc = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + address = FindPattern("\x48\x8B\xC8\xE8\x00\x00\x00\x00\xF3\x0F\x10\x54\x24\x00\xF3\x0F\x10\x4C\x24\x00\xF3\x0F\x10", "xxxx????xxxxx?xxxxx?xxx"); + _entityPositionFunc = reinterpret_cast(*reinterpret_cast(address + 4) + address + 8); + address = FindPattern("\x25\xFF\xFF\xFF\x3F\x89\x44\x24\x38\xE8\x00\x00\x00\x00\x48\x85\xC0\x74\x03", "xxxxxxxxxx????xxxxx"); + _entityModel1Func = reinterpret_cast(*reinterpret_cast(address - 61) + address - 57); + _entityModel2Func = reinterpret_cast(*reinterpret_cast(address + 10) + address + 14); + + address = FindPattern("\x8B\xF0\x48\x8B\x05\x00\x00\x00\x00\xF3\x0F\x59\xF6", "xxxxx????xxxx"); + _pickupObjectPoolAddress = reinterpret_cast(*reinterpret_cast(address + 5) + address + 9); + } + } + + // This function was inlined in Enhanced, so we reimplement it ourselves. + if (!g_isEnhanced) { + address = FindPattern("\x74\x21\x48\x8B\x48\x20\x48\x85\xC9\x74\x18\x48\x8B\xD6\xE8", "xxxxxxxxxxxxxxx") - 10; + _ptfxAddressFunc = reinterpret_cast(*reinterpret_cast(address) + address + 4); + } + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("56 57 48 83 ec ? 48 89 cf 48 8d 71 ? 8b 15"); + } + else { + address = FindPattern("\x48\xF7\xF9\x49\x8B\x48\x08\x48\x63\xD0\xC1\xE0\x08\x0F\xB6\x1C\x11\x03\xD8", "xxxxxxxxxxxxxxxxxxx"); + } + if (address) { + _addEntityToPoolFunc = reinterpret_cast(address - (g_isEnhanced ? 0 : 0x68)); + } + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("48 8b 05 ? ? ? ? 48 85 c0 74 ? 4c 8b 00"); + } + else { + address = FindPattern("\x48\x8B\x05\x00\x00\x00\x00\xF3\x0F\x59\xF6\x48\x8B\x08", "xxx????xxxxxxx"); + } + _vehiclePoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + if (!g_isEnhanced) { + address = FindPattern("\x4C\x8B\x0D\x00\x00\x00\x00\x44\x8B\xC1\x49\x8B\x41\x08", "xxx????xxxxxxx"); + _entityPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + address = FindPattern("\x48\x8B\x05\x00\x00\x00\x00\x41\x0F\xBF\xC8\x0F\xBF\x40\x10", "xxx????xxxxxxxx"); + _pedPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + address = FindPattern("\x48\x8B\x05\x00\x00\x00\x00\x8B\x78\x10\x85\xFF", "xxx????xxxxx"); + _objectPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + + address = FindPattern("\x48\x8B\xC8\xEB\x02\x33\xC9\x48\x85\xC9\x74\x26", "xxxxxxxxxxxx") - 9; + _cameraPoolAddress = reinterpret_cast(*reinterpret_cast(address) + address + 4); + } + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("56 48 83 ec ? 48 89 ce 48 89 11 44 89 41"); + } + else + { + address = MemryScan::PatternScanner::FindPattern("\x40\x53\x48\x83\xEC\x20\x83\x61\x0C\x00\x44\x89\x41\x08\x49\x63\xC0", "xxxxxxxxxxxxxxxxx"); + } + if (address != null) + { + CreateNmMessageFunc = reinterpret_cast(address); + } + + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("44 8b 89 ? ? ? ? b9"); + if (address != null) + { + GiveNmMessageFunc = reinterpret_cast(address); + } + } + else + { + address = MemryScan::PatternScanner::FindPattern("\x0F\x84\x8B\x00\x00\x00\x48\x8B\x47\x30\x48\x8B\x48\x10\x48\x8B\x51\x20\x80\x7A\x10\x0A", "xxxxxxxxxxxxxxxxxxxxxx"); + if (address != null) + { + GiveNmMessageFunc = reinterpret_cast((UINT64*)(*(int*)(address - 0x1E) + address - 0x1A)); + } + } + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("7d ? 45 89 c6 48 89 d7"); + if (address != null) + { + SetNmIntAddress = reinterpret_cast(address - 20); + } + } + else { + address = MemryScan::PatternScanner::FindPattern("\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x63\x49\x0C\x41\x8B\xF8", "xxxx?xxxxxxxxxxxxxxx"); + if (address != null) + { + SetNmIntAddress = reinterpret_cast(address); + } + } + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("7d ? 45 89 c6 48 89 d3"); + if (address != null) + { + SetNmBoolAddress = reinterpret_cast(address - 20); + } + } + else + { + address = MemryScan::PatternScanner::FindPattern("\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x63\x49\x0C\x41\x8A\xF8", "xxxx?xxxxxxxxxxxxxxx"); + if (address != null) + { + SetNmBoolAddress = reinterpret_cast(address); + } + } + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("41 56 56 57 53 48 83 ec ? 0f 29 74 24 20 48 89 ce 48 63 79"); + } + else { + address = MemryScan::PatternScanner::FindPattern("\x40\x53\x48\x83\xEC\x30\x48\x8B\xD9\x48\x63\x49\x0C", "xxxxxxxxxxxxx"); + } + if (address != null) + { + SetNmFloatAddress = reinterpret_cast(address); + } + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("41 56 56 57 53 48 83 ec ? 48 89 ce 48 63 79"); + if (address != null) + { + SetNmStringAddress = reinterpret_cast(address); + } + } + else { + address = MemryScan::PatternScanner::FindPattern("\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x63\x49\x0C\x49\x8B\xE8", "xxxxxxxxxxxxxxx"); + if (address != null) + { + SetNmStringAddress = reinterpret_cast(address - 15); + } + } + + if (g_isEnhanced) + { + address = MemryScan::PatternScanner::FindPattern("0f 29 7c 24 30 0f 29 74 24 20 48 89 ce 48 63 79"); + if (address != null) + { + SetNmVec3Address = reinterpret_cast(address - 15); + } + } + else + { + address = MemryScan::PatternScanner::FindPattern("\x40\x53\x48\x83\xEC\x40\x48\x8B\xD9\x48\x63\x49\x0C", "xxxxxxxxxxxxx"); + if (address != null) + { + SetNmVec3Address = reinterpret_cast(address); + } + } + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("83 fe ? 75 ? b8 ? ? ? ? 48 8d 0d"); + if (address) + { + checkpointPoolAddress = reinterpret_cast(*reinterpret_cast(address + 13) + address + 17); + } + address = MemryScan::PatternScanner::FindPattern("48 83 ec ? e8 ? ? ? ? 48 85 c0 74 ? e8 ? ? ? ? 48 8b 80"); + if (address) + { + CheckpointBaseAddr = reinterpret_cast(address); + } + address = MemryScan::PatternScanner::FindPattern("74 ? 66 83 78 ? ? 75 ? 48 63 78"); + if (address) + { + CheckpointHandleAddr = reinterpret_cast(*reinterpret_cast(address - 7) + address - 3); + } + } + else { + address = FindPattern("\x8A\x4C\x24\x60\x8B\x50\x10\x44\x8A\xCE", "xxxxxxxxxx"); + CheckpointBaseAddr = reinterpret_cast(*reinterpret_cast(address - 19) + address - 15); + CheckpointHandleAddr = reinterpret_cast(*reinterpret_cast(address - 9) + address - 5); + checkpointPoolAddress = reinterpret_cast(*reinterpret_cast(address + 17) + address + 21); + } + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("e8 ? ? ? ? 41 80 bd ? ? ? ? ? 45 0f b7 85"); + _getHashKey = reinterpret_cast(*reinterpret_cast(address + 1) + address + 5); + } + else { + address = FindPattern("\x48\x8B\x0B\x33\xD2\xE8\x00\x00\x00\x00\x89\x03", "xxxxxx????xx"); + _getHashKey = reinterpret_cast(*reinterpret_cast(address + 6) + address + 10); + } + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("89 c8 48 8d 0d ? ? ? ? f3 0f 10 04 81 f3 0f 11 05"); + if (address) + { + _readWorldGravityAddress = reinterpret_cast(*reinterpret_cast(address + 18) + address + 22); + _writeWorldGravityAddress = reinterpret_cast(*reinterpret_cast(address + 5) + address + 9); + } + } + else { + address = FindPattern("\x48\x63\xC1\x48\x8D\x0D\x00\x00\x00\x00\xF3\x0F\x10\x04\x81\xF3\x0F\x11\x05\x00\x00\x00\x00", "xxxxxx????xxxxxxxxx????"); + if (address) { + _writeWorldGravityAddress = reinterpret_cast(*reinterpret_cast(address + 6) + address + 10); + _readWorldGravityAddress = reinterpret_cast(*reinterpret_cast(address + 19) + address + 23); + } + } + + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("89 0d ? ? ? ? 48 8d 0d ? ? ? ? e8 ? ? ? ? 84 c0"); + if (address) + { + _cursorSpriteAddr = reinterpret_cast(*reinterpret_cast(address + 2) + address + 6); + } + } + else { + address = FindPattern("\x74\x11\x8B\xD1\x48\x8D\x0D\x00\x00\x00\x00\x45\x33\xC0", "xxxxxxx????xxx"); + _cursorSpriteAddr = reinterpret_cast(*reinterpret_cast(address - 4) + address); } - UINT64 GetResult() - { - return _res; + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("88 05 ? ? ? ? e8 ? ? ? ? 88 05 ? ? ? ? e8"); + if (address) + { + address = (*reinterpret_cast(address + 18) + address + 22); + _gamePlayCameraAddr = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + } + } + else { + address = FindPattern("\x48\x8B\xC7\xF3\x0F\x10\x0D", "xxxxxxx") - 0x1D; + address = address + *reinterpret_cast(address) + 4; + _gamePlayCameraAddr = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); } -private: - func _toRun; - UINT64 _arg; - UINT64 _res; -}; -void GTAmemory::Init() -{ - UINT64 address; - // Get relative address and add it to the instruction address. - // 3 bytes equal the size of the opcode and its first argument. 7 bytes are the length of opcode and all its parameters. + // Bypass model requests block + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("44 0f b6 b4 24 ? ? ? ? 41 20 f6"); + if (address) memset(reinterpret_cast(address - 20), 0x90, 20); + } + else { + // new pattern that lands outside of the patched bytes, to ensure compatibility with other mods that patch them. + address = MemryScan::PatternScanner::FindPattern("45 84 e4 74 ? e8 ? ? ? ? 48 85 c0"); + if (address) memset(reinterpret_cast(address - 24), 0x90, 24); + } - address = FindPattern("\x4C\x8D\x05\x00\x00\x00\x00\x0F\xB7\xC1", "xxx????xxx"); - if (address) _blipList = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + // Bypass is player model allowed to spawn checks + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("74 ? e8 ? ? ? ? 48 8b b0"); + if (address) memset(reinterpret_cast(address + 28), 0x90, 6); + } + else { + // new pattern that lands outside of the patched bytes, to ensure compatibility with other mods that patch them. + address = MemryScan::PatternScanner::FindPattern("40 53 48 83 ec ? e8 ? ? ? ? 48 8b d8 48 85 c0 74 ? 48 8b 10 48 8b c8 ff 52"); + if (address) memset(reinterpret_cast(address + 28), 0x90, 4); + } - address = FindPattern("\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x18\x89\x54\x24\x10\x56\x57\x41\x56\x48\x83\xEC\x20", "xxxxxxxxxxxxxxxxxxxxxx"); - _gxtLabelFromHashFuncAddr = reinterpret_cast(address); - address = FindPattern("\x84\xC0\x74\x34\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\xD3", "xxxxxxx????xxx"); - _gxtLabelFromHashAddr1 = *reinterpret_cast(address + 7) + address + 11; + //GetModelInfo - if (GTAmemory::GetGameVersion() >= eGameVersion::VER_1_0_1290_1_STEAM) - { - address = FindPattern("\xE8\x00\x00\x00\x00\x48\x8B\xD8\x48\x85\xC0\x74\x2E\x48\x83\x3D", "x????xxxxxxxxxxx"); - _entityAddressFunc = reinterpret_cast(*reinterpret_cast(address + 1) + address + 5); - address = FindPattern("\xB2\x01\xE8\x00\x00\x00\x00\x48\x85\xC0\x74\x1C\x8A\x88", "xxx????xxxxxxx"); - _playerAddressFunc = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("45 85 d2 74 ? 49 89 d0 4c 8b 1d"); - address = FindPattern("\x48\x8B\xDA\xE8\x00\x00\x00\x00\xF3\x0F\x10\x44\x24", "xxxx????xxxxx"); - _entityPositionFunc = reinterpret_cast(address - 6); - address = FindPattern("\x0F\x85\x00\x00\x00\x00\x48\x8B\x4B\x20\xE8\x00\x00\x00\x00\x48\x8B\xC8", "xx????xxxxx????xxx"); - _entityModel1Func = reinterpret_cast(*reinterpret_cast(address + 11) + address + 15); - address = FindPattern("\x45\x33\xC9\x3B\x05", "xxxxx"); - _entityModel2Func = reinterpret_cast(address - 0x46); + if (address) { + address = address - 8; + } + else { + addlog(ige::LogType::LOG_ERROR, "Couldn't find GetModelInfo (Enhanced)", __FILENAME__); + } + } + else { + if (getGameVersion() <= 57) { + address = FindPattern( + "\x0F\xB7\x05\x00\x00\x00\x00" + "\x45\x33\xC9\x4C\x8B\xDA\x66\x85\xC0" + "\x0F\x84\x00\x00\x00\x00" + "\x44\x0F\xB7\xC0\x33\xD2\x8B\xC1\x41\xF7\xF0\x48" + "\x8B\x05\x00\x00\x00\x00" + "\x4C\x8B\x14\xD0\xEB\x09\x41\x3B\x0A\x74\x54", + "xxx????" + "xxxxxxxxx" + "xx????" + "xxxxxxxxxxxx" + "xx????" + "xxxxxxxxxxx"); + + if (!address) { + addlog(ige::LogType::LOG_ERROR, "Couldn't find GetModelInfo", __FILENAME__); + } + } + else { + address = FindPattern("\xEB\x09\x41\x3B\x0A\x74\x54", "xxxxxxx"); - address = FindPattern("\x4C\x8B\x05\x00\x00\x00\x00\x40\x8A\xF2\x8B\xE9", "xxx????xxxxx"); - _pickupObjectPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); + if (address) { + address = address - 0x2C; + } + else { + addlog(ige::LogType::LOG_ERROR, "Couldn't find GetModelInfo (v58+)", __FILENAME__); + } + } + } + if (address) { + GetModelInfo = (GetModelInfo_t)(address); } - else - { - address = FindPattern("\x33\xFF\xE8\x00\x00\x00\x00\x48\x85\xC0\x74\x58", "xxx????xxxxx"); - _entityAddressFunc = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - address = FindPattern("\xB2\x01\xE8\x00\x00\x00\x00\x33\xC9\x48\x85\xC0\x74\x3B", "xxx????xxxxxxx"); - _playerAddressFunc = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - - address = FindPattern("\x48\x8B\xC8\xE8\x00\x00\x00\x00\xF3\x0F\x10\x54\x24\x00\xF3\x0F\x10\x4C\x24\x00\xF3\x0F\x10", "xxxx????xxxxx?xxxxx?xxx"); - _entityPositionFunc = reinterpret_cast(*reinterpret_cast(address + 4) + address + 8); - address = FindPattern("\x25\xFF\xFF\xFF\x3F\x89\x44\x24\x38\xE8\x00\x00\x00\x00\x48\x85\xC0\x74\x03", "xxxxxxxxxx????xxxxx"); - _entityModel1Func = reinterpret_cast(*reinterpret_cast(address - 61) + address - 57); - _entityModel2Func = reinterpret_cast(*reinterpret_cast(address + 10) + address + 14); - - address = FindPattern("\x8B\xF0\x48\x8B\x05\x00\x00\x00\x00\xF3\x0F\x59\xF6", "xxxxx????xxxx"); - _pickupObjectPoolAddress = reinterpret_cast(*reinterpret_cast(address + 5) + address + 9); - } - - address = FindPattern("\x74\x21\x48\x8B\x48\x20\x48\x85\xC9\x74\x18\x48\x8B\xD6\xE8", "xxxxxxxxxxxxxxx") - 10; - _ptfxAddressFunc = reinterpret_cast(*reinterpret_cast(address) + address + 4); - - address = FindPattern("\x48\xF7\xF9\x49\x8B\x48\x08\x48\x63\xD0\xC1\xE0\x08\x0F\xB6\x1C\x11\x03\xD8", "xxxxxxxxxxxxxxxxxxx"); - _addEntityToPoolFunc = reinterpret_cast(address - 0x68); - - address = FindPattern("\x4C\x8B\x0D\x00\x00\x00\x00\x44\x8B\xC1\x49\x8B\x41\x08", "xxx????xxxxxxx"); - _entityPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - address = FindPattern("\x48\x8B\x05\x00\x00\x00\x00\xF3\x0F\x59\xF6\x48\x8B\x08", "xxx????xxxxxxx"); - _vehiclePoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - address = FindPattern("\x48\x8B\x05\x00\x00\x00\x00\x41\x0F\xBF\xC8\x0F\xBF\x40\x10", "xxx????xxxxxxxx"); - _pedPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - address = FindPattern("\x48\x8B\x05\x00\x00\x00\x00\x8B\x78\x10\x85\xFF", "xxx????xxxxx"); - _objectPoolAddress = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - - CreateNmMessageFunc = FindPattern("\x33\xDB\x48\x89\x1D\x00\x00\x00\x00\x85\xFF", "xxxxx????xx") - 0x42; - GiveNmMessageFunc = FindPattern("\x0F\x84\x00\x00\x00\x00\x48\x8B\x01\xFF\x90\x00\x00\x00\x00\x41\x3B\xC5", "xx????xxxxx????xxx") - 0x78; - address = FindPattern("\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x63\x49\x0C\x41\x8A\xF8", "xxxx?xxxxxxxxxxxxxxx"); - SetNmBoolAddress = reinterpret_cast(address); - address = FindPattern("\x40\x53\x48\x83\xEC\x30\x48\x8B\xD9\x48\x63\x49\x0C", "xxxxxxxxxxxxx"); - SetNmFloatAddress = reinterpret_cast(address); - address = FindPattern("\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x63\x49\x0C\x41\x8B\xF8", "xxxx?xxxxxxxxxxxxxxx"); - SetNmIntAddress = reinterpret_cast(address); - address = FindPattern("\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x63\x49\x0C\x49\x8B\xE8", "xxxxxxxxxxxxxxx") - 15; - SetNmStringAddress = reinterpret_cast(address); - address = FindPattern("\x40\x53\x48\x83\xEC\x40\x48\x8B\xD9\x48\x63\x49\x0C", "xxxxxxxxxxxxx"); - SetNmVec3Address = reinterpret_cast(address); - - address = FindPattern("\x8A\x4C\x24\x60\x8B\x50\x10\x44\x8A\xCE", "xxxxxxxxxx"); - CheckpointBaseAddr = reinterpret_cast(*reinterpret_cast(address - 19) + address - 15); - CheckpointHandleAddr = reinterpret_cast(*reinterpret_cast(address - 9) + address - 5); - checkpointPoolAddress = reinterpret_cast(*reinterpret_cast(address + 17) + address + 21); - - address = FindPattern("\x48\x8B\x0B\x33\xD2\xE8\x00\x00\x00\x00\x89\x03", "xxxxxx????xx"); - _getHashKey = reinterpret_cast(*reinterpret_cast(address + 6) + address + 10); - - address = FindPattern("\x48\x63\xC1\x48\x8D\x0D\x00\x00\x00\x00\xF3\x0F\x10\x04\x81\xF3\x0F\x11\x05\x00\x00\x00\x00", "xxxxxx????xxxxxxxxx????"); - _writeWorldGravityAddress = reinterpret_cast(*reinterpret_cast(address + 6) + address + 10); - _readWorldGravityAddress = reinterpret_cast(*reinterpret_cast(address + 19) + address + 23); - - address = FindPattern("\x74\x11\x8B\xD1\x48\x8D\x0D\x00\x00\x00\x00\x45\x33\xC0", "xxxxxxx????xxx"); - _cursorSpriteAddr = reinterpret_cast(*reinterpret_cast(address - 4) + address); - - address = FindPattern("\x48\x8B\xC7\xF3\x0F\x10\x0D", "xxxxxxx") - 0x1D; - address = address + *reinterpret_cast(address) + 4; - _gamePlayCameraAddr = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); - address = FindPattern("\x48\x8B\xC8\xEB\x02\x33\xC9\x48\x85\xC9\x74\x26", "xxxxxxxxxxxx") - 9; - _cameraPoolAddress = reinterpret_cast(*reinterpret_cast(address) + address + 4); - // Bypass model requests block - address = MemryScan::PatternScanner::FindPattern("48 85 C0 0F 84 ? ? ? ? 8B 48 50"); - if (address) memset(reinterpret_cast(address), 0x90, 24); + _SpSnow = SpSnow(); + addlog(ige::LogType::LOG_INIT, "GTAMemory Init Done", __FILENAME__); +} - // Bypass is player model allowed to spawn checks - address = MemryScan::PatternScanner::FindPattern("48 8B C8 FF 52 30 84 C0 74 05 48"); - if (address) memset(reinterpret_cast(address + 0x8), 0x90, 2); +void GTAmemory::InitEnhancedPools() { + if (g_isEnhanced) { + + // In Enhanced, the pools are encrypted/obfuscated. Instead of having their pointer stored somewhere, it is constructed at init from different values, + // using bit operations. The problem is that menyoo is loaded a bit too early for the initialization to have happened, and so we can't retrieve those values + // during GTAmemory init. For that reason, we leave that to the very end, and we keep waiting until the game has started (GameState == 0 (PLAYING)). + // This was not a problem with SHVDNE, since NativeMemroy init is only done after the game has started. + + UINT64 address = MemryScan::PatternScanner::FindPattern("83 f9 ? 74 ? 41 89 c8"); + if (address) + { + bool isInitialized = (*(byte*)(*(int*)(address + 11) + address + 15) & 1) != 0; + UINT64 firstValue = *(UINT64*)(*(int*)(address + 29) + address + 33); + UINT64 secondValue = *(UINT64*)(*(int*)(address + 18) + address + 22); + auto firstRol = *(byte*)(address + 25); // 0x1E + auto secondRol = *(byte*)(address + 39); // 0x20 + auto andValue = *(byte*)(address + 42); // 0x1F + auto addValue = *(byte*)(address + 45); // 2 + GTAmemory::_entityPoolAddress = (UINT64*)0; + if (isInitialized) + { + auto rcx = secondValue; + rcx = Rol(rcx, firstRol); + auto rdx = firstValue; + rdx = rdx ^ rcx; + rdx = Rol(rdx, secondRol); + auto cl = (byte)(rcx & 0xFF); + cl = (byte)(cl & andValue); + cl = (byte)(cl + addValue); + rdx = Rol(rdx, cl); + rdx = ~rdx; + GTAmemory::_entityPoolAddress = (UINT64*)rdx; + } - //GetModelInfo - if (getGameVersion() <= 57) { - address = FindPattern( - "\x0F\xB7\x05\x00\x00\x00\x00" - "\x45\x33\xC9\x4C\x8B\xDA\x66\x85\xC0" - "\x0F\x84\x00\x00\x00\x00" - "\x44\x0F\xB7\xC0\x33\xD2\x8B\xC1\x41\xF7\xF0\x48" - "\x8B\x05\x00\x00\x00\x00" - "\x4C\x8B\x14\xD0\xEB\x09\x41\x3B\x0A\x74\x54", - "xxx????" - "xxxxxxxxx" - "xx????" - "xxxxxxxxxxxx" - "xx????" - "xxxxxxxxxxx"); - - if (!address) { - addlog(ige::LogType::LOG_ERROR, "Couldn't find GetModelInfo", __FILENAME__); } - } - else { - address = FindPattern("\xEB\x09\x41\x3B\x0A\x74\x54", "xxxxxxx"); - if (!address) { - addlog(ige::LogType::LOG_ERROR, "Couldn't find GetModelInfo (v58+)", __FILENAME__); + + address = MemryScan::PatternScanner::FindPattern("48 83 ec ? 89 ce 0f b6 05"); + if (address) + { + bool isInitialized = (*(byte*)(*(int*)(address + 9) + address + 13) & 1) != 0; + uint64_t firstValue = *(uint64_t*)(*(int*)(address + 27) + address + 31); + uint64_t secondValue = *(uint64_t*)(*(int*)(address + 16) + address + 20); + auto firstRol = *(byte*)(address + 23); // 0x1F + auto secondRol = *(byte*)(address + 49); // 0x20 + auto andValue = *(byte*)(address + 36); // 0x1F + auto addValue = *(byte*)(address + 39); // 5 + GTAmemory::_pickupObjectPoolAddress = (uint64_t*)0UL; + if (isInitialized) + { + auto rcx = secondValue; + rcx = Rol(rcx, firstRol); + auto rax = firstValue; + rax = rax ^ rcx; + auto cl = (byte)(rcx & 0xFF); + cl = (byte)(cl & andValue); + cl = (byte)(cl + addValue); + rax = Rol(rax, cl); + rax = Rol(rax, secondRol); + rax = ~rax; + GTAmemory::_pickupObjectPoolAddress = (uint64_t*)rax; + } + } + + address = MemryScan::PatternScanner::FindPattern("48 83 ec ? 83 3d ? ? ? ? ? 0f 84 ? ? ? ? 0f b6 05"); + if (address) { + bool isInitialized = (*(byte*)(*(int*)(address + 20) + address + 24) & 1) != 0; + UINT64 firstValue = *(UINT64*)(*(int*)(address + 38) + address + 42); + UINT64 secondValue = *(UINT64*)(*(int*)(address + 27) + address + 31); + auto firstRol = *(byte*)(address + 34); // 0x1E + auto secondRol = *(byte*)(address + 48); // 0x20 + auto andValue = *(byte*)(address + 51); // 0x1F + auto addValue = *(byte*)(address + 54); // 2 + GTAmemory::_pedPoolAddress = (UINT64*)0UL; + if (isInitialized) + { + auto rcx = secondValue; + rcx = Rol(rcx, firstRol); + auto rax = firstValue; + rax = rax ^ rcx; + rax = Rol(rax, secondRol); + auto cl = (byte)(rcx & 0xFF); + cl = (byte)(cl & andValue); + cl = (byte)(cl + addValue); + rax = Rol(rax, cl); + rax = ~rax; + GTAmemory::_pedPoolAddress = (UINT64*)rax; + } + } + + address = MemryScan::PatternScanner::FindPattern("53 48 81 ec ? ? ? ? 0f 29 b4 ? ? ? ? ? 48 89 ce 0f b6 05"); + if (address) + { + bool isInitialized = (*(byte*)(*(int*)(address + 22) + address + 26) & 1) != 0; + UINT64 firstValue = *(UINT64*)(*(int*)(address + 40) + address + 44); + UINT64 secondValue = *(UINT64*)(*(int*)(address + 29) + address + 33); + auto firstRol = *(byte*)(address + 36); // 0x1E + auto secondRol = *(byte*)(address + 59); // 0x20 + auto andValue = *(byte*)(address + 49); // 0x1F + auto addValue = *(byte*)(address + 52); // 3 + GTAmemory::_objectPoolAddress = (UINT64*)0UL; + if (isInitialized) + { + auto rcx = secondValue; + rcx = Rol(rcx, firstRol); + auto rdx = firstValue; + rdx = rdx ^ rcx; + auto cl = (byte)(rcx & 0xFF); + cl = (byte)(cl & andValue); + cl = (byte)(cl + addValue); + rdx = Rol(rdx, cl); + rdx = Rol(rdx, secondRol); + rdx = ~rdx; + GTAmemory::_objectPoolAddress = (UINT64*)rdx; + } + } + + address = MemryScan::PatternScanner::FindPattern("48 89 cb 48 8b 41 ? 8b 10 f2 0f 10 3d"); + if (address) + { + // The pattern is inside a function, which calls a function, which accesses the pool. + address = (*reinterpret_cast(address + 34) + address + 38); + if (address) + { + bool isInitialized = (*reinterpret_cast(*reinterpret_cast(address + 3) + address + 7) & 1) != 0; + UINT64 firstValue = *reinterpret_cast(*reinterpret_cast(address + 21) + address + 25); + UINT64 secondValue = *reinterpret_cast(*reinterpret_cast(address + 10) + address + 14); + auto firstRol = *reinterpret_cast(address + 17); // 0x1b + auto secondRol = *reinterpret_cast(address + 31); // 0x20 + auto andValue = *reinterpret_cast(address + 33); // 0x1f + auto addValue = *reinterpret_cast(address + 36); // 0x1 + auto xorValue = *reinterpret_cast(address + 44); // 0x3f + GTAmemory::_cameraPoolAddress = (UINT64*)0UL; + if (isInitialized) + { + auto rax = secondValue; + rax = Rol(rax, firstRol); + auto rsi = firstValue; + rsi = rsi ^ rax; + rsi = Rol(rsi, secondRol); + auto al = (byte)(rax & 0xFF); + al = (byte)(al & andValue); + rax = (rax & 0xFFFFFFFFFFFFFF00UL) | (UINT64)al; + auto ecx = (int)((rax + (UINT64)addValue) & 0xFFFFFFFF); + auto rdi = rsi; + auto cl = (byte)(ecx & 0xFF); + rdi = rdi << cl; + al = (byte)(al ^ xorValue); + rax = (rax & 0xFFFFFFFFFFFFFF00UL) | (UINT64)al; + auto eax = (int)(rax & 0xFFFFFFFF); + ecx = eax; + cl = (byte)(ecx & 0xFF); + rsi = rsi >> cl; + rsi = rsi | rdi; + rsi = ~rsi; + GTAmemory::_cameraPoolAddress = (UINT64*)rsi; + } + } } address = address - 0x2C; - } + addlog(ige::LogType::LOG_TRACE, "Found Pattern: " + std::to_string(address), __FILENAME__); + GetModelInfo = (GetModelInfo_t)(address); _SpSnow = SpSnow(); - } +} + Vector3 GTAmemory::ReadVector3(UINT64 address) { @@ -896,23 +1756,53 @@ struct HashNode }; void GTAmemory::GenerateVehicleModelList() { + + int classOffset; + uintptr_t address; + HashNode** HashMap; + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("0f b6 88 ? ? ? ? 83 e1 ? e9"); + if (address) + { + classOffset = *(uint*)(address + 3); + + address = MemryScan::PatternScanner::FindPattern("74 ? 49 89 d0 4c 8b 1d"); + if (address) + { + modelHashTable = *reinterpret_cast(*(int*)(address + 8) + address + 12); + modelHashEntries = *reinterpret_cast(address + *(int*)(address - 7) - 3); + // Pattern scan to avoid having offsets accross labels. + address = MemryScan::PatternScanner::FindPattern("\x3B\x05\x00\x00\x00\x00\x7D\x00\x48\x8B\x0D", "xx????x?xxx", address, 200); // TODO: use the findpattern with legacy patterns, because it supports a start address. + modelNum1 = *reinterpret_cast(*(int*)(address + 2) + address + 6); + modelNum2 = *reinterpret_cast(*(int*)(address + 11) + address + 15); + modelNum3 = *reinterpret_cast(*(int*)(address + 48) + address + 52); + modelNum4 = *reinterpret_cast(*(int*)(address + 33) + address + 37); + } + } + } + else { + address = FindPattern("\x66\x81\xF9\x00\x00\x74\x10\x4D\x85\xC0", "xxx??xxxxx"); + if (address) { + address = address - 0x21; + //UINT64 baseFuncAddr = *reinterpret_cast(address - 0x21) + address - 0x1D; + UINT64 baseFuncAddr = address + *reinterpret_cast(address) + 0x4; + //int classOffset = *reinterpret_cast(address + 0x10); + int classOffset = *reinterpret_cast(address + 0x31); + modelHashEntries = *reinterpret_cast(baseFuncAddr + *reinterpret_cast(baseFuncAddr + 3) + 7); + modelNum1 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x52) + baseFuncAddr + 0x56); //cmp + modelNum2 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x63) + baseFuncAddr + 0x67); //mov + modelNum3 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x7A) + baseFuncAddr + 0x7E); //mul + modelNum4 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x81) + baseFuncAddr + 0x85); //add + + modelHashTable = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x24) + baseFuncAddr + 0x28); + } + } + //Zorg - uintptr_t address = FindPattern("\x66\x81\xF9\x00\x00\x74\x10\x4D\x85\xC0", "xxx??xxxxx"); + if (address) { - address = address - 0x21; - //UINT64 baseFuncAddr = *reinterpret_cast(address - 0x21) + address - 0x1D; - UINT64 baseFuncAddr = address + *reinterpret_cast(address) + 0x4; - //int classOffset = *reinterpret_cast(address + 0x10); - int classOffset = *reinterpret_cast(address + 0x31); - modelHashEntries = *reinterpret_cast(baseFuncAddr + *reinterpret_cast(baseFuncAddr + 3) + 7); - modelNum1 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x52) + baseFuncAddr + 0x56); //cmp - modelNum2 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x63) + baseFuncAddr + 0x67); //mov - modelNum3 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x7A) + baseFuncAddr + 0x7E); //mul - modelNum4 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x81) + baseFuncAddr + 0x85); //add - - modelHashTable = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x24) + baseFuncAddr + 0x28); - HashNode** HashMap = reinterpret_cast(modelHashTable); + HashMap = reinterpret_cast(modelHashTable); //I know 0x20 items are defined but there are only 0x16 vehicle classes. //But keeping it at 0x20 is just being safe as the & 0x1F in theory supports up to 0x20 auto& vehicleHashes = GTAmemory::vehicleModels; @@ -942,6 +1832,7 @@ void GTAmemory::GenerateVehicleModelList() } } } + bool GTAmemory::IsModelAPed(unsigned int modelHash) { HashNode** HashMap = reinterpret_cast(modelHashTable); @@ -989,20 +1880,31 @@ UINT64 GTAmemory::_globalTextBlockAddr; std::vector GTAmemory::_vecGXT2Entries; void GTAmemory::LoadGlobalGXTEntries() { - UINT64 address = FindPattern("\x84\xC0\x74\x34\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\xD3", "xxxxxxx????xxx"); + UINT64 address; + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("48 8d 0d ? ? ? ? 4c 89 f2 e8 ? ? ? ? 8b 17"); + } + else { + address = FindPattern("\x84\xC0\x74\x34\x48\x8D\x0D\x00\x00\x00\x00\x48\x8B\xD3", "xxxxxxx????xxx"); + } if (address) { - address = *reinterpret_cast(address + 7) + address + 11; - DWORD offset = 0xA0; // for text block "GLOBAL" - _globalTextBlockAddr = *(UINT64 *)(address + offset); + if (g_isEnhanced) { + address = *reinterpret_cast(address + 3) + address + 7; + } + else { + address = *reinterpret_cast(address + 7) + address + 11; + } + DWORD offset = 0xA0; // for text block "GLOBAL" // seems to be the same in Enhanced + _globalTextBlockAddr = *(UINT64*)(address + offset); - UINT32 numEntries = *(UINT32 *)(_globalTextBlockAddr + 4); + UINT32 numEntries = *(UINT32*)(_globalTextBlockAddr + 4); for (UINT32 entry = 0; entry < numEntries; entry++) { - DWORD labelHash = *(DWORD *)(_globalTextBlockAddr + 8 + entry * 8); + DWORD labelHash = *(DWORD*)(_globalTextBlockAddr + 8 + entry * 8); - DWORD strOffset = *(DWORD *)(_globalTextBlockAddr + 12 + entry * 8); + DWORD strOffset = *(DWORD*)(_globalTextBlockAddr + 12 + entry * 8); _vecGXT2Entries.push_back({ labelHash, strOffset }); } @@ -1021,7 +1923,7 @@ void GTAmemory::EditGXTLabel(DWORD labelHash, LPCSTR string) { if (entry.labelHash == labelHash) { - strcpy_s((char *)(_globalTextBlockAddr + entry.strOffset), strlen(string), string); + strcpy_s((char*)(_globalTextBlockAddr + entry.strOffset), strlen(string), string); //strcpy((char *)(_globalTextBlockAddr + entry.strOffset), string); } } @@ -1040,19 +1942,23 @@ UINT64 GTAmemory::GetCheckpointAddress(int handle) UINT64 addr = GTAmemory::CheckpointHandleAddr(GTAmemory::CheckpointBaseAddr(), handle); if (addr) { - return (UINT64)((UINT64)(GTAmemory::checkpointPoolAddress) + 96 * *reinterpret_cast(addr + 16)); + return (UINT64)((UINT64)(GTAmemory::checkpointPoolAddress)+96 * *reinterpret_cast(addr + 16)); } return 0; } UINT64 GTAmemory::GetPtfxAddress(int handle) { + if (g_isEnhanced) + { + return (UINT64)GetPtfxAddressFunc(handle); + } return (GTAmemory::_ptfxAddressFunc(handle)); } int GTAmemory::GetEntityBoneCount(int handle) { UINT64 MemAddress = _entityAddressFunc(handle); - UINT64 Addr2 = (*(UINT64(__fastcall **)(__int64))(*(UINT64 *)MemAddress + 88i64))(MemAddress); + UINT64 Addr2 = (*(UINT64(__fastcall**)(__int64))(*(UINT64*)MemAddress + 88i64))(MemAddress); UINT64 Addr3; if (!Addr2) { @@ -1086,11 +1992,11 @@ int GTAmemory::GetEntityBoneCount(int handle) } UINT64 GTAmemory::GetEntityBoneMatrixAddress(int handle, int boneIndex) { - if ((boneIndex & 0x80000000) != 0)//boneIndex cant be negative + if ((boneIndex & 0x80000000) != 0) // boneIndex cant be negative return 0; UINT64 MemAddress = _entityAddressFunc(handle); - UINT64 Addr2 = (*(UINT64(__fastcall **)(__int64))(*(UINT64 *)MemAddress + 88i64))(MemAddress); + UINT64 Addr2 = (*(UINT64(__fastcall**)(__int64))(*(UINT64*)MemAddress + 88i64))(MemAddress); UINT64 Addr3; if (!Addr2) { @@ -1141,9 +2047,9 @@ UINT64 GTAmemory::GetCameraAddress(int handle) { unsigned int index = (unsigned int)(handle >> 8); UINT64 poolAddr = *_cameraPoolAddress; - if (*(BYTE *)(index + *(INT64*)(poolAddr + 8)) == (BYTE)(handle & 0xFF)) + if (*(BYTE*)(index + *(INT64*)(poolAddr + 8)) == (BYTE)(handle & 0xFF)) { - return (*(INT64*)poolAddr + (unsigned int)(index * *(UINT32 *)(poolAddr + 20))); + return (*(INT64*)poolAddr + (unsigned int)(index * *(UINT32*)(poolAddr + 20))); } return 0; } @@ -1299,6 +2205,10 @@ int GTAmemory::GetNumberOfVehicles() { if (*_vehiclePoolAddress) { + if (g_isEnhanced) { + VehiclePoolEnhanced* pool = *reinterpret_cast(*_vehiclePoolAddress); + return pool->itemCount; + } VehiclePool* pool = *reinterpret_cast(*_vehiclePoolAddress); return pool->itemCount; } @@ -1355,7 +2265,7 @@ void GTAmemory::GetEntityHandles(std::vector& result) GTAmemory::GetPropHandles(result); }*/ -uintptr_t GTAmemory::FindPattern(const char *pattern, const char *mask, const char* startAddress, size_t size) { +uintptr_t GTAmemory::FindPattern(const char* pattern, const char* mask, const char* startAddress, size_t size) { const char* address_end = startAddress + size; const auto mask_length = static_cast(strlen(mask) - 1); @@ -1373,17 +2283,17 @@ uintptr_t GTAmemory::FindPattern(const char *pattern, const char *mask, const ch return 0; } -uintptr_t GTAmemory::FindPattern(const char *pattern, const char *mask) +uintptr_t GTAmemory::FindPattern(const char* pattern, const char* mask) { MODULEINFO modInfo = g_MainModuleInfo; - const char *start_offset = reinterpret_cast(modInfo.lpBaseOfDll); + const char* start_offset = reinterpret_cast(modInfo.lpBaseOfDll); const uintptr_t size = static_cast(modInfo.SizeOfImage); intptr_t pos = 0; const uintptr_t searchLen = static_cast(strlen(mask) - 1); - for (const char *retAddress = start_offset; retAddress < start_offset + size; retAddress++) + for (const char* retAddress = start_offset; retAddress < start_offset + size; retAddress++) { if (*retAddress == pattern[pos] || mask[pos] == '?') { @@ -1410,11 +2320,11 @@ SpSnow _SpSnow; void SpSnow::EnableSnow(bool bEnable) { // Adresses - static auto SpSnow_addr1 = MemryScan::PatternScanner::FindPattern("\x80\x3D\x00\x00\x00\x00\x00\x74\x27\x84\xC0", "xx?????xxxx"); - static auto SpSnow_addr2 = MemryScan::PatternScanner::FindPattern("\x44\x38\x3D\x00\x00\x00\x00\x74\x0F", "xxx????xx"); - static auto SpSnow_addr12 = MemryScan::PatternScanner::FindPattern("\x40\x38\x35\x00\x00\x00\x00\x74\x18\x84\xdb\x74\x14", "xxx????xxxxxx"); - static auto SpSnow_addr13 = MemryScan::PatternScanner::FindPattern("\x80\x3D\x00\x00\x00\x00\x00\x74\x25\xB9\x40\x00\x00\x00", "xx????xxxxxxxx"); - static auto SpSnow_addr22 = MemryScan::PatternScanner::FindPattern("\x44\x38\x3D\x00\x00\x00\x00\x74\x1D\xB9\x40\x00\x00\x00", "xxx????xxxxxxx"); + static auto SpSnow_addr1 = MemryScan::PatternScanner::FindPattern("\x80\x3D\x00\x00\x00\x00\x00\x74\x27\x84\xC0", "xx?????xxxx"); // not found in latest Legacy builds (3521) + static auto SpSnow_addr2 = MemryScan::PatternScanner::FindPattern("44 38 3D ? ? ? ? 74 0F 83 3F"); // 80 3d ? ? ? ? ? 8b 86 ? ? ? ? 74 find out what is being patched in legacy and do the same here. + static auto SpSnow_addr12 = MemryScan::PatternScanner::FindPattern("\x40\x38\x35\x00\x00\x00\x00\x74\x18\x84\xdb\x74\x14", "xxx????xxxxxx"); // not found in latest Legacy builds (3521) + static auto SpSnow_addr13 = MemryScan::PatternScanner::FindPattern("\x80\x3D\x00\x00\x00\x00\x00\x74\x25\xB9\x40\x00\x00\x00", "xx????xxxxxxxx"); // not found in latest Legacy builds (3521) + static auto SpSnow_addr22 = MemryScan::PatternScanner::FindPattern("44 38 3D ? ? ? ? 74 1D B9 40 00 00 00"); // eb ? 80 3d ? ? ? ? ? 74 ? b9 ? ? ? ? e8 ? ? ? ? 84 c3 74 ? c7 86 its somewhere here. find it. auto& addr1 = SpSnow_addr1; auto& addr2 = SpSnow_addr2; @@ -1422,14 +2332,40 @@ void SpSnow::EnableSnow(bool bEnable) auto& addr13 = SpSnow_addr13; auto& addr22 = SpSnow_addr22; + static auto addrEnhanced = MemryScan::PatternScanner::FindPattern("48 89 f9 e8 ? ? ? ? e9 ? ? ? ? 83 f8"); + const bool isMinGameVersion3095 = GTAmemory::GetGameVersion() >= eGameVersion::VER_1_0_3095_0; - // Patterns may change - if (!addr1 && !isMinGameVersion3095) - { - if (!addr12) + if (!g_isEnhanced) { + // Patterns may change + if (!addr1 && !isMinGameVersion3095) // This is simply kept for backwards compatibility. + { + if (!addr12) + { + if (!addr13) + { + BEGIN_TEXT_COMMAND_PRINT("STRING"); + ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME("~r~Error:~s~ Snow is not compatible with this GTA Version."); + END_TEXT_COMMAND_PRINT(2000, 1); + //auto snow_ptr = GetTunablePtr(RawTunableIndex::TURN_SNOW_ON_OFF); + //*snow_ptr = bEnable ? 1 : 0; + return; + } + else + { + addr1 = addr13; + bUseAddr13 = true; + } + } + else + { + addr1 = addr12; + } + } + + if (!addr2) { - if (!addr13) + if (!addr22) { BEGIN_TEXT_COMMAND_PRINT("STRING"); ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME("~r~Error:~s~ Snow is not compatible with this GTA Version."); @@ -1440,61 +2376,72 @@ void SpSnow::EnableSnow(bool bEnable) } else { - addr1 = addr13; - bUseAddr13 = true; + addr2 = addr22; + bUseAddr22 = true; } } - else - { - addr1 = addr12; - } - } - - if (!addr2) - { - if (!addr22) - { - BEGIN_TEXT_COMMAND_PRINT("STRING"); - ADD_TEXT_COMPONENT_SUBSTRING_PLAYER_NAME("~r~Error:~s~ Snow is not compatible with this GTA Version."); - END_TEXT_COMMAND_PRINT(2000, 1); - //auto snow_ptr = GetTunablePtr(RawTunableIndex::TURN_SNOW_ON_OFF); - //*snow_ptr = bEnable ? 1 : 0; - return; - } - else - { - addr2 = addr22; - bUseAddr22 = true; - } } // Initialize if (!this->bInitialized) { - // Unprotect Memory - if(!isMinGameVersion3095) VirtualProtect((void*)addr1, 13, PAGE_EXECUTE_READWRITE, nullptr); - VirtualProtect((void*)addr2, 14, PAGE_EXECUTE_READWRITE, nullptr); + if (g_isEnhanced) { - // Copy original Memory - if (!isMinGameVersion3095) memcpy(&original1, (void*)addr1, 13); - memcpy(&original2, (void*)addr2, 14); + VirtualProtect((void*)(addrEnhanced - 11), 11, PAGE_EXECUTE_READWRITE, nullptr); + memcpy(&original1EnhancedSnow, (void*)(addrEnhanced - 11), 11); + VirtualProtect((void*)(addrEnhanced - 24), 7, PAGE_EXECUTE_READWRITE, nullptr); + memcpy(&original2EnhancedSnow, (void*)(addrEnhanced - 24), 7); - this->traxv_call = MemryScan::PatternScanner::FindPattern("\x40\x38\x3D\x00\x00\x00\x00\x48\x8B\x42\x20", "xxx????xxxx"); - if (this->traxv_call == NULL) this->tracks_available = false; + this->traxv_call = MemryScan::PatternScanner::FindPattern("0f b6 15 ? ? ? ? 00 d2 08 c2 88 91"); + if (this->traxv_call == NULL) this->tracks_available = false; - this->traxvt = MemryScan::PatternScanner::FindPattern("\xB9\x00\x00\x00\x00\x84\xC0\x44\x0F\x44\xF1", "x????xxxxxx"); - if (this->traxvt == NULL) this->tracks_available = false; + this->traxvt = MemryScan::PatternScanner::FindPattern("b8 ? ? ? ? 44 0f 44 f8 48 8b 86"); + if (this->traxvt == NULL) this->tracks_available = false; - this->traxp_call = MemryScan::PatternScanner::FindPattern("\x80\x3D\x00\x00\x00\x00\x00\x48\x8B\xD9\x74\x37", "xx?????xxxxx"); - if (this->traxp_call == NULL) this->tracks_available = false; + this->traxp_call = MemryScan::PatternScanner::FindPattern("0f b6 05 ? ? ? ? 0f b6 91"); + if (this->traxp_call == NULL) this->tracks_available = false; - this->traxpt = MemryScan::PatternScanner::FindPattern("\xB9\x00\x00\x00\x00\x84\xC0\x0F\x44\xD9\x48\x8B\x4F\x30", "x????xxxxxxxxx"); - if (this->traxpt == NULL) this->tracks_available = false; + this->traxpt = MemryScan::PatternScanner::FindPattern("b8 ? ? ? ? 44 89 f9 0f 45 c8 41 83 ff"); + if (this->traxpt == NULL) this->tracks_available = false; - if (this->tracks_available) - { - this->traxv = this->traxv_call + (*(int32_t *)(this->traxv_call + 3)) + 7; - this->traxp = this->traxp_call + (*(int32_t *)(this->traxp_call + 2)) + 7; + if (this->tracks_available) + { + this->traxv = this->traxv_call + (*(int32_t*)(this->traxv_call + 3)) + 7; + this->traxp = this->traxp_call + (*(int32_t*)(this->traxp_call + 3)) + 7; + } + } + else { + // Unprotect Memory + if (!isMinGameVersion3095) VirtualProtect((void*)addr1, 13, PAGE_EXECUTE_READWRITE, nullptr); + VirtualProtect((void*)(addr2 - 14), 14, PAGE_EXECUTE_READWRITE, nullptr); + + // Copy original Memory + if (!isMinGameVersion3095) memcpy(&original1, (void*)addr1, 13); + memcpy(&original2, (void*)(addr2 - 14), 14); + + this->traxv_call = MemryScan::PatternScanner::FindPattern("\x40\x38\x3D\x00\x00\x00\x00\x48\x8B\x42\x20", "xxx????xxxx"); + if (this->traxv_call == NULL) this->tracks_available = false; + + this->traxvt = MemryScan::PatternScanner::FindPattern("B9 ? ? ? ? 84 C0 44 0F 44 F1 48 8b 83"); + if (this->traxvt == NULL) this->tracks_available = false; + + this->traxp_call = MemryScan::PatternScanner::FindPattern("80 3D ? ? ? ? ? 48 8B D9 74 37"); + if (this->traxp_call == NULL) this->tracks_available = false; + + this->traxpt = MemryScan::PatternScanner::FindPattern("\xB9\x00\x00\x00\x00\x84\xC0\x0F\x44\xD9\x48\x8B\x4F\x30", "x????xxxxxxxxx"); + if (this->traxpt == NULL) + { + // The first pattern can't be found in newer legacy builds. Not sure starting from which version though. + // For that reason, if we don't find it, we look for the new one. (so that we don't break Menyoo for older versions) + this->traxpt = MemryScan::PatternScanner::FindPattern("bb ? ? ? ? 48 8b 4f ? 48 81 c1"); + if (this->traxpt == NULL) this->tracks_available = false; + } + + if (this->tracks_available) + { + this->traxv = this->traxv_call + (*(int32_t*)(this->traxv_call + 3)) + 7; + this->traxp = this->traxp_call + (*(int32_t*)(this->traxp_call + 2)) + 7; + } } this->bInitialized = true; @@ -1506,13 +2453,39 @@ void SpSnow::EnableSnow(bool bEnable) // Toggle if (bEnable) { - // NOP checks - if (!isMinGameVersion3095) - { - if (bUseAddr13) + if (g_isEnhanced) { + memset((void*)(addrEnhanced - 11), 0x90, 11); + memset((void*)(addrEnhanced - 24), 0x90, 7); + this->EnableTracks(true, true, true, true); + FORCE_GROUND_SNOW_PASS(true); + } + else { + // NOP checks + if (!isMinGameVersion3095) + { + if (bUseAddr13) + { + BYTE* pFrom = (BYTE*)addr1; + BYTE* pTo = (BYTE*)addr1 + 0x1B; + DWORD protect; + VirtualProtect(pFrom, 16, PAGE_EXECUTE_READWRITE, &protect); + pFrom[0] = 0x48; // mov rax, func + pFrom[1] = 0xB8; + *reinterpret_cast(&pFrom[2]) = pTo; + pFrom[10] = 0x50; // push rax + pFrom[11] = 0xC3; // ret + VirtualProtect(pFrom, 16, protect, &protect); + } + else + { + memset((void*)addr1, 0x90, 13); + } + } + + if (bUseAddr22) { - BYTE* pFrom = (BYTE*)addr1; - BYTE* pTo = (BYTE*)addr1 + 0x1B; + BYTE* pFrom = (BYTE*)addr2; + BYTE* pTo = (BYTE*)addr2 + 0x1C; DWORD protect; VirtualProtect(pFrom, 16, PAGE_EXECUTE_READWRITE, &protect); pFrom[0] = 0x48; // mov rax, func @@ -1522,60 +2495,51 @@ void SpSnow::EnableSnow(bool bEnable) pFrom[11] = 0xC3; // ret VirtualProtect(pFrom, 16, protect, &protect); } - else + else // This is the case relevant to the latest legacy builds { - memset((void*)addr1, 0x90, 13); + memset((void*)addr2, 0x90, 14); } - } - - if (bUseAddr22) - { - BYTE* pFrom = (BYTE*)addr2; - BYTE* pTo = (BYTE*)addr2 + 0x1C; - DWORD protect; - VirtualProtect(pFrom, 16, PAGE_EXECUTE_READWRITE, &protect); - pFrom[0] = 0x48; // mov rax, func - pFrom[1] = 0xB8; - *reinterpret_cast(&pFrom[2]) = pTo; - pFrom[10] = 0x50; // push rax - pFrom[11] = 0xC3; // ret - VirtualProtect(pFrom, 16, protect, &protect); - } - else - { - memset((void*)addr2, 0x90, 14); - } - // Weather - //SET_WEATHER_TYPE_NOW_PERSIST("Snow"); + // Weather + //SET_WEATHER_TYPE_NOW_PERSIST("Snow"); - //*snow_ptr = 1; + //*snow_ptr = 1; - //USE_SNOW_FOOT_VFX_WHEN_UNSHELTERED(true); - //USE_SNOW_WHEEL_VFX_WHEN_UNSHELTERED(true); - this->EnableTracks(true, true, true, true); - if (isMinGameVersion3095) - FORCE_GROUND_SNOW_PASS(true); - // Now on + //USE_SNOW_FOOT_VFX_WHEN_UNSHELTERED(true); + //USE_SNOW_WHEEL_VFX_WHEN_UNSHELTERED(true); + this->EnableTracks(true, true, true, true); + if (isMinGameVersion3095) + FORCE_GROUND_SNOW_PASS(true); + // Now on + } } else { - // Copy original bytes back - if (!isMinGameVersion3095) memcpy((void*)addr1, &original1, 13); - memcpy((void*)addr2, &original2, 14); - - // Weather - //CLEAR_WEATHER_TYPE_PERSIST(); - //SET_WEATHER_TYPE_NOW("Sunny"); - - //*snow_ptr = 0; - //USE_SNOW_FOOT_VFX_WHEN_UNSHELTERED(false); - //USE_SNOW_WHEEL_VFX_WHEN_UNSHELTERED(false); - this->EnableTracks(false, false, false, false); - if (isMinGameVersion3095) + if (g_isEnhanced) { + memcpy((void*)(addrEnhanced - 11), &original1EnhancedSnow, 11); + memcpy((void*)(addrEnhanced - 24), &original2EnhancedSnow, 7); + this->EnableTracks(false, false, false, false); FORCE_GROUND_SNOW_PASS(false); - // Now off + } + else { + // Copy original bytes back + if (!isMinGameVersion3095) memcpy((void*)addr1, &original1, 13); + memcpy((void*)addr2, &original2, 14); + + // Weather + //CLEAR_WEATHER_TYPE_PERSIST(); + //SET_WEATHER_TYPE_NOW("Sunny"); + + //*snow_ptr = 0; + + //USE_SNOW_FOOT_VFX_WHEN_UNSHELTERED(false); + //USE_SNOW_WHEEL_VFX_WHEN_UNSHELTERED(false); + this->EnableTracks(false, false, false, false); + if (isMinGameVersion3095) + FORCE_GROUND_SNOW_PASS(false); + // Now off + } } } void SpSnow::EnableTracks(bool tracksPed, bool deepTracksPed, bool tracksVehicle, bool deepTracksVehicle) @@ -1652,68 +2616,88 @@ void SpSnow::Tick() void GeneralGlobalHax::DisableAnnoyingRecordingUI(bool uSure) { - // Has to be updated every patch. - switch (GTAmemory::GetGameVersion()) - { - case eGameVersion::VER_1_0_757_4_NOSTEAM: case eGameVersion::VER_1_0_757_4_STEAM: - case eGameVersion::VER_1_0_791_2_NOSTEAM: case eGameVersion::VER_1_0_791_2_STEAM: - *GTAmemory::GetGlobalPtr(0x42DE + 0x9) = uSure ? 1 : 0; break; - case eGameVersion::VER_1_0_877_1_NOSTEAM: case eGameVersion::VER_1_0_877_1_STEAM: - case eGameVersion::VER_1_0_944_2_NOSTEAM: case eGameVersion::VER_1_0_944_2_STEAM: - case eGameVersion::VER_1_0_1011_1_NOSTEAM: case eGameVersion::VER_1_0_1011_1_STEAM: - case eGameVersion::VER_1_0_1032_1_NOSTEAM: case eGameVersion::VER_1_0_1032_1_STEAM: - case eGameVersion::VER_1_0_1103_2_NOSTEAM: case eGameVersion::VER_1_0_1103_2_STEAM: - case eGameVersion::VER_1_0_1180_2_NOSTEAM: case eGameVersion::VER_1_0_1180_2_STEAM: - *GTAmemory::GetGlobalPtr(0x42FF + 0x9) = uSure ? 1 : 0; - *GTAmemory::GetGlobalPtr(0x42FF + 0x82) = uSure ? 1 : 0; - break; - case eGameVersion::VER_1_0_1290_1_NOSTEAM: case eGameVersion::VER_1_0_1290_1_STEAM: - case eGameVersion::VER_1_0_1365_1_NOSTEAM: case eGameVersion::VER_1_0_1365_1_STEAM: - *GTAmemory::GetGlobalPtr(0x430A + 0x82) = uSure ? 1 : 0; break; - case eGameVersion::VER_1_0_1493_0_NOSTEAM: case eGameVersion::VER_1_0_1493_0_STEAM: - case eGameVersion::VER_1_0_1493_1_NOSTEAM: case eGameVersion::VER_1_0_1493_1_STEAM: - *GTAmemory::GetGlobalPtr(0x4336 + 0x82) = uSure ? 1 : 0; break; - case eGameVersion::VER_1_0_1604_0_NOSTEAM: case eGameVersion::VER_1_0_1604_0_STEAM: - case eGameVersion::VER_1_0_1604_1_NOSTEAM: case eGameVersion::VER_1_0_1604_1_STEAM: - *GTAmemory::GetGlobalPtr(0x434C + 0x82) = uSure ? 1 : 0; break; - case eGameVersion::VER_1_0_1737_0_NOSTEAM: case eGameVersion::VER_1_0_1737_0_STEAM: - case eGameVersion::VER_1_0_1737_6_NOSTEAM: case eGameVersion::VER_1_0_1737_6_STEAM: - *GTAmemory::GetGlobalPtr(0x4378 + 0x82) = uSure ? 1 : 0; break; - case eGameVersion::VER_1_0_1868_0_NOSTEAM: case eGameVersion::VER_1_0_1868_0_STEAM: - case eGameVersion::VER_1_0_1868_1_NOSTEAM: case eGameVersion::VER_1_0_1868_1_STEAM: - *GTAmemory::GetGlobalPtr(0x56C3 + 0x82) = uSure ? 1 : 0; break; - } -} - -//https://github.com/ikt32/GTAVAddonLoader/blob/master/GTAVAddonLoader/NativeMemory.cpp -void GeneralGlobalHax::EnableBlockedMpVehiclesInSp() -{ - const char* patt617_1 = "\x2C\x01\x00\x00\x20\x56\x04\x00\x6E\x2E\x00\x01\x5F\x00\x00\x00\x00\x04\x00\x6E\x2E\x00\x01"; - const char* mask617_1 = "xx??xxxxxx?xx????xxxx?x"; - const unsigned int offset617_1 = 13; - - const char* patt1604_0 = "\x2D\x00\x00\x00\x00\x2C\x01\x00\x00\x56\x04\x00\x6E\x2E\x00\x01\x5F\x00\x00\x00\x00\x04\x00\x6E\x2E\x00\x01"; - const char* mask1604_0 = "x??xxxx??xxxxx?xx????xxxx?x"; - const unsigned int offset1064_0 = 17; - - // Updated pattern entirely thanks to @alexguirre - const char* patt2802_0 = "\x2D\x00\x00\x00\x00\x2C\x01\x00\x00\x56\x04\x00\x71\x2E\x00\x01\x62\x00\x00\x00\x00\x04\x00\x71\x2E\x00\x01"; - const char* mask2802_0 = "x??xxxx??xxxxx?xx????xxxx?x"; - const unsigned int offset2802_0 = 17; + if (g_isEnhanced) { + return; // Current global is : 24009 + 130. For some reason getting it using pattern matching failed, even tho it works when tried in another mod. + // you could simply try to implement this. The pattern to scan for is 25 19 2C ? ? ? 2A 06 56 08 00 71 25 44 2C ? ? ? 20 56 04 00 71 2e 01 01 + // In Enhanced. The globalId is at +27, and add the byte at +30 to it. + // and 73 25 13 2C 09 ? ? 06 2A 56 09 00 73 25 13 2C 09 ? ? 06 1F 56 06 00 71 52 ? ? 42 ? 73 in Legacy. + // The globalId is at +26, and add the byte at +29 to it. + } + else { + // Has to be updated every patch. + switch (GTAmemory::GetGameVersion()) + { + case eGameVersion::VER_1_0_757_4_NOSTEAM: case eGameVersion::VER_1_0_757_4_STEAM: + case eGameVersion::VER_1_0_791_2_NOSTEAM: case eGameVersion::VER_1_0_791_2_STEAM: + *GTAmemory::GetGlobalPtr(0x42DE + 0x9) = uSure ? 1 : 0; break; + case eGameVersion::VER_1_0_877_1_NOSTEAM: case eGameVersion::VER_1_0_877_1_STEAM: + case eGameVersion::VER_1_0_944_2_NOSTEAM: case eGameVersion::VER_1_0_944_2_STEAM: + case eGameVersion::VER_1_0_1011_1_NOSTEAM: case eGameVersion::VER_1_0_1011_1_STEAM: + case eGameVersion::VER_1_0_1032_1_NOSTEAM: case eGameVersion::VER_1_0_1032_1_STEAM: + case eGameVersion::VER_1_0_1103_2_NOSTEAM: case eGameVersion::VER_1_0_1103_2_STEAM: + case eGameVersion::VER_1_0_1180_2_NOSTEAM: case eGameVersion::VER_1_0_1180_2_STEAM: + *GTAmemory::GetGlobalPtr(0x42FF + 0x9) = uSure ? 1 : 0; + *GTAmemory::GetGlobalPtr(0x42FF + 0x82) = uSure ? 1 : 0; + break; + case eGameVersion::VER_1_0_1290_1_NOSTEAM: case eGameVersion::VER_1_0_1290_1_STEAM: + case eGameVersion::VER_1_0_1365_1_NOSTEAM: case eGameVersion::VER_1_0_1365_1_STEAM: + *GTAmemory::GetGlobalPtr(0x430A + 0x82) = uSure ? 1 : 0; break; + case eGameVersion::VER_1_0_1493_0_NOSTEAM: case eGameVersion::VER_1_0_1493_0_STEAM: + case eGameVersion::VER_1_0_1493_1_NOSTEAM: case eGameVersion::VER_1_0_1493_1_STEAM: + *GTAmemory::GetGlobalPtr(0x4336 + 0x82) = uSure ? 1 : 0; break; + case eGameVersion::VER_1_0_1604_0_NOSTEAM: case eGameVersion::VER_1_0_1604_0_STEAM: + case eGameVersion::VER_1_0_1604_1_NOSTEAM: case eGameVersion::VER_1_0_1604_1_STEAM: + *GTAmemory::GetGlobalPtr(0x434C + 0x82) = uSure ? 1 : 0; break; + case eGameVersion::VER_1_0_1737_0_NOSTEAM: case eGameVersion::VER_1_0_1737_0_STEAM: + case eGameVersion::VER_1_0_1737_6_NOSTEAM: case eGameVersion::VER_1_0_1737_6_STEAM: + *GTAmemory::GetGlobalPtr(0x4378 + 0x82) = uSure ? 1 : 0; break; + case eGameVersion::VER_1_0_1868_0_NOSTEAM: case eGameVersion::VER_1_0_1868_0_STEAM: + case eGameVersion::VER_1_0_1868_1_NOSTEAM: case eGameVersion::VER_1_0_1868_1_STEAM: + *GTAmemory::GetGlobalPtr(0x56C3 + 0x82) = uSure ? 1 : 0; break; + } + } +} - const char* pattern = patt617_1; - const char* mask = mask617_1; - int offset = offset617_1; - if (getGameVersion() >= 80) { - pattern = patt2802_0; - mask = mask2802_0; - offset = offset2802_0; +void GeneralGlobalHax::EnableBlockedMpVehiclesInSp() +{ + const char* pattern; + const char* mask; + int offset; + if (g_isEnhanced) { + pattern = "\x2D\x00\x00\x00\x00\x2C\x00\x00\x00\x56\x00\x00\x71\x2E\x00\x00\x62"; + mask = "x????x???x??xx??x"; + offset = 17; } - else if (getGameVersion() >= 46) { - pattern = patt1604_0; - mask = mask1604_0; - offset = offset1064_0; + else { + // https://github.com/ikt32/GTAVAddonLoader/blob/master/GTAVAddonLoader/NativeMemory.cpp + const char* patt617_1 = "\x2C\x01\x00\x00\x20\x56\x04\x00\x6E\x2E\x00\x01\x5F\x00\x00\x00\x00\x04\x00\x6E\x2E\x00\x01"; + const char* mask617_1 = "xx??xxxxxx?xx????xxxx?x"; + const unsigned int offset617_1 = 13; + + const char* patt1604_0 = "\x2D\x00\x00\x00\x00\x2C\x01\x00\x00\x56\x04\x00\x6E\x2E\x00\x01\x5F\x00\x00\x00\x00\x04\x00\x6E\x2E\x00\x01"; + const char* mask1604_0 = "x??xxxx??xxxxx?xx????xxxx?x"; + const unsigned int offset1064_0 = 17; + + // Updated pattern entirely thanks to @alexguirre + const char* patt2802_0 = "\x2D\x00\x00\x00\x00\x2C\x01\x00\x00\x56\x04\x00\x71\x2E\x00\x01\x62\x00\x00\x00\x00\x04\x00\x71\x2E\x00\x01"; + const char* mask2802_0 = "x??xxxx??xxxxx?xx????xxxx?x"; + const unsigned int offset2802_0 = 17; + + pattern = patt617_1; + mask = mask617_1; + offset = offset617_1; + + if (getGameVersion() >= 80) { + pattern = patt2802_0; + mask = mask2802_0; + offset = offset2802_0; + } + else if (getGameVersion() >= 46) { + pattern = patt1604_0; + mask = mask1604_0; + offset = offset1064_0; + } } for (int i = 0; i < shopController->CodePageCount(); i++) @@ -1725,36 +2709,48 @@ void GeneralGlobalHax::EnableBlockedMpVehiclesInSp() if (address) { int globalindex = *(int*)(address + offset) & 0xFFFFFF; - addlog(ige::LogType::LOG_INFO, "Setting Global Variable " + std::to_string(globalindex) + " to true", __FILENAME__); + addlog(ige::LogType::LOG_INFO, "Setting Global Variable " + std::to_string(globalindex) + " to true", __FILENAME__); *GTAmemory::GetGlobalPtr(globalindex) = 1; return; } } } - addlog(ige::LogType::LOG_ERROR, "Global Variable not found, check game version >= 1.0.678.1", __FILENAME__); + addlog(ige::LogType::LOG_ERROR, "Global Variable not found, check game version >= 1.0.678.1", __FILENAME__); } // from EnableMPCars by drp4lyf bool GTAmemory::FindShopController() { - __int64 patternAddr = FindPattern("\x48\x03\x15\x00\x00\x00\x00\x4C\x23\xC2\x49\x8B\x08", "xxx????xxxxxx"); + return FindScript(0x39DA738B); // joaat("shop_controller") +} + +bool GTAmemory::FindScript(int hash) { + __int64 patternAddr; + if (g_isEnhanced) { + patternAddr = MemryScan::PatternScanner::FindPattern("48 03 05 ? ? ? ? 4c 85 c0 0f 84 ? ? ? ? e9"); + } + else { + patternAddr = FindPattern("\x48\x03\x15\x00\x00\x00\x00\x4C\x23\xC2\x49\x8B\x08", "xxx????xxxxxx"); + } + if (!patternAddr) { - addlog(ige::LogType::LOG_ERROR, "ERROR: finding address 1", __FILENAME__); - addlog(ige::LogType::LOG_ERROR, "Aborting...", __FILENAME__); + addlog(ige::LogType::LOG_ERROR, "ERROR: finding address 1", __FILENAME__); + addlog(ige::LogType::LOG_ERROR, "Aborting...", __FILENAME__); return false; } scriptTable = (ScriptTable*)(patternAddr + *(int*)(patternAddr + 3) + 7); - - ScriptTableItem* Item = scriptTable->FindScript(0x39DA738B); + + ScriptTableItem* Item = scriptTable->FindScript(hash); if (Item == NULL) { - addlog(ige::LogType::LOG_ERROR, "ERROR: finding script 0x39DA738B", __FILENAME__); - addlog(ige::LogType::LOG_ERROR, "Aborting...", __FILENAME__); + addlog(ige::LogType::LOG_ERROR, "ERROR: finding script shop_controller ", __FILENAME__); + addlog(ige::LogType::LOG_ERROR, "Aborting...", __FILENAME__); return false; } while (!Item->IsLoaded()) Sleep(100); - + shopController = Item->Header; + //addlog(ige::LogType::LOG_INFO, "Found shopcontroller", __FILENAME__); return true; } @@ -1764,7 +2760,13 @@ void** GeneralGlobalHax::WorldPtrPtr() static DWORD64 __dwWorldPtrAddr = 0x0U; if (!__dwWorldPtrAddr) { - __dwWorldPtrAddr = MemryScan::PatternScanner::FindPattern("48 8B 05 ? ? ? ? 45 ? ? ? ? 48 8B 48 08 48 85 C9 74 07"); + if (g_isEnhanced) { + __dwWorldPtrAddr = MemryScan::PatternScanner::FindPattern("48 8b 05 ? ? ? ? 48 8b 40 ? 48 85 c0 0f 84 ? ? ? ? 0f 28 b0"); + } + else { + __dwWorldPtrAddr = MemryScan::PatternScanner::FindPattern("48 8B 05 ? ? ? ? 45 ? ? ? ? 48 8B 48 08 48 85 C9 74 07"); + } + if (__dwWorldPtrAddr) { __dwWorldPtrAddr = __dwWorldPtrAddr + *reinterpret_cast(__dwWorldPtrAddr + 3) + 7; @@ -1772,19 +2774,26 @@ void** GeneralGlobalHax::WorldPtrPtr() } return reinterpret_cast(__dwWorldPtrAddr); } + +// Offsets are quite fragile and I don't have a clue when they changed, which might break Menyoo for people using older versions. +// The best way to handle them is use pattern scanning to fetch them dynamically. For that reason I'll leave them as is. + float GeneralGlobalHax::GetPlayerHeight() { - auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_2802_0) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})); + if (!g_isEnhanced) { + auto baddr = *GeneralGlobalHax::WorldPtrPtr(); + if (baddr) + { + auto gameVersion = GTAmemory::GetGameVersion(); + if (gameVersion <= eGameVersion::VER_1_0_2802_0) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})); + } } return 1.0f; } void GeneralGlobalHax::SetPlayerHeight(float value) { + if (g_isEnhanced) return; auto baddr = *GeneralGlobalHax::WorldPtrPtr(); if (baddr) { @@ -1793,29 +2802,35 @@ void GeneralGlobalHax::SetPlayerHeight(float value) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})) = value; } } + +// For 3521 (Legacy) and 814.9 (Enhanced), PlayerSwimSpeed is at {0x8, 0x10A8, 0x1C8}. + float GeneralGlobalHax::GetPlayerSwimSpeed() { - auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_791_2_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x1088, 0xE4})); - else if (gameVersion <= eGameVersion::VER_1_0_877_1_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10A8, 0xE4})); - else if (gameVersion <= eGameVersion::VER_1_0_1103_2_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0xE4})); - else if (gameVersion <= eGameVersion::VER_1_0_1868_1_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0x148})); - else if (gameVersion <= eGameVersion::VER_1_0_2215_0_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0x150})); - else if (gameVersion <= eGameVersion::VER_1_0_2245_0_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0x170})); + if (!g_isEnhanced) { + auto baddr = *GeneralGlobalHax::WorldPtrPtr(); + if (baddr) + { + auto gameVersion = GTAmemory::GetGameVersion(); + if (gameVersion <= eGameVersion::VER_1_0_791_2_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x1088, 0xE4})); + else if (gameVersion <= eGameVersion::VER_1_0_877_1_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10A8, 0xE4})); + else if (gameVersion <= eGameVersion::VER_1_0_1103_2_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0xE4})); + else if (gameVersion <= eGameVersion::VER_1_0_1868_1_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0x148})); + else if (gameVersion <= eGameVersion::VER_1_0_2215_0_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0x150})); + else if (gameVersion <= eGameVersion::VER_1_0_2245_0_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0x170})); + } } return 1.0f; } void GeneralGlobalHax::SetPlayerSwimSpeed(float value) { + if (g_isEnhanced) return; auto baddr = *GeneralGlobalHax::WorldPtrPtr(); if (baddr) { @@ -1834,30 +2849,35 @@ void GeneralGlobalHax::SetPlayerSwimSpeed(float value) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0x170})) = value; } } + +// For 3521 (Legacy) and 814.9 (Enhanced), PlayerMovementSpeed is at {0x8, 0x10A8, 0xD50}. float GeneralGlobalHax::GetPlayerMovementSpeed() { - auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_791_2_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x1088, 0xE8})); - else if (gameVersion <= eGameVersion::VER_1_0_877_1_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10A8, 0xE8})); - else if (gameVersion <= eGameVersion::VER_1_0_1103_2_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0xE8})); - else if (gameVersion <= eGameVersion::VER_1_0_1868_1_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0x14C})); - else if (gameVersion <= eGameVersion::VER_1_0_2215_0_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0xCD0})); - else if (gameVersion <= eGameVersion::VER_1_0_2245_0_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0xCF0})); - + if (!g_isEnhanced) { + auto baddr = *GeneralGlobalHax::WorldPtrPtr(); + if (baddr) + { + auto gameVersion = GTAmemory::GetGameVersion(); + if (gameVersion <= eGameVersion::VER_1_0_791_2_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x1088, 0xE8})); + else if (gameVersion <= eGameVersion::VER_1_0_877_1_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10A8, 0xE8})); + else if (gameVersion <= eGameVersion::VER_1_0_1103_2_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0xE8})); + else if (gameVersion <= eGameVersion::VER_1_0_1868_1_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0x14C})); + else if (gameVersion <= eGameVersion::VER_1_0_2215_0_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0xCD0})); + else if (gameVersion <= eGameVersion::VER_1_0_2245_0_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0xCF0})); + + } } return 1.0f; } void GeneralGlobalHax::SetPlayerMovementSpeed(float value) { + if (g_isEnhanced) return; auto baddr = *GeneralGlobalHax::WorldPtrPtr(); if (baddr) { @@ -1870,26 +2890,29 @@ void GeneralGlobalHax::SetPlayerMovementSpeed(float value) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0xE8})) = value; else if (gameVersion <= eGameVersion::VER_1_0_1868_1_NOSTEAM) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10B8, 0x14C})) = value; - else if (gameVersion <= eGameVersion::VER_1_0_2215_0_NOSTEAM) + else if (gameVersion <= eGameVersion::VER_1_0_2215_0_NOSTEAM) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0xCD0})) = value; - else if (gameVersion <= eGameVersion::VER_1_0_2245_0_NOSTEAM) + else if (gameVersion <= eGameVersion::VER_1_0_2245_0_NOSTEAM) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x10C8, 0xCF0})) = value; } } int GeneralGlobalHax::GetVehicleBoostState() { - auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_2372_0_NOSTEAM) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0xD28, 0x318})); + if (!g_isEnhanced) { + auto baddr = *GeneralGlobalHax::WorldPtrPtr(); + if (baddr) + { + auto gameVersion = GTAmemory::GetGameVersion(); + if (gameVersion <= eGameVersion::VER_1_0_2372_0_NOSTEAM) + return *(GetMultilayerPointer(baddr, std::vector{0x8, 0xD28, 0x318})); + } } return 0; } void GeneralGlobalHax::SetVehicleBoostState(int value) { + if (g_isEnhanced) return; auto baddr = *GeneralGlobalHax::WorldPtrPtr(); if (baddr) { @@ -1900,14 +2923,16 @@ void GeneralGlobalHax::SetVehicleBoostState(int value) } float* GeneralGlobalHax::GetVehicleBoostChargePtr() { - auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_1103_2_NOSTEAM) - return (GetMultilayerPointer(baddr, std::vector{0x8, 0xD28, 0x31C})); - if (gameVersion <= eGameVersion::VER_1_0_2372_0_NOSTEAM)//VER_1_0_1868_1_NOSTEAM - return (GetMultilayerPointer(baddr, std::vector{0x8, 0xD28, 0x320})); // Might be off + if (!g_isEnhanced) { + auto baddr = *GeneralGlobalHax::WorldPtrPtr(); + if (baddr) + { + auto gameVersion = GTAmemory::GetGameVersion(); + if (gameVersion <= eGameVersion::VER_1_0_1103_2_NOSTEAM) + return (GetMultilayerPointer(baddr, std::vector{0x8, 0xD28, 0x31C})); + if (gameVersion <= eGameVersion::VER_1_0_2372_0_NOSTEAM)//VER_1_0_1868_1_NOSTEAM + return (GetMultilayerPointer(baddr, std::vector{0x8, 0xD28, 0x320})); // Might be off + } } return nullptr; } diff --git a/Solution/source/Memory/GTAmemory.h b/Solution/source/Memory/GTAmemory.h index af807df2..af128d44 100644 --- a/Solution/source/Memory/GTAmemory.h +++ b/Solution/source/Memory/GTAmemory.h @@ -34,8 +34,8 @@ typedef signed int INT32; typedef unsigned long DWORD; typedef unsigned long long size_t; typedef unsigned __int64 DWORD64, UINT64; -typedef void *LPVOID; -typedef const char *LPCSTR; +typedef void* LPVOID; +typedef const char* LPCSTR; typedef int Entity; typedef unsigned long Hash; typedef uint8_t eModelType; @@ -48,215 +48,215 @@ typedef uint32_t eVehicleFlag5; typedef uint32_t eVehicleFlag6; // Various snippets from FiveM source and Unknown Modder namespace rage { - class fwArchetype { - public: - virtual ~fwArchetype() = default; - - char _0x0008[0x10]; // 0x0000 - Hash m_hash; // 0x0018 - char _0x001C[0x10]; // 0x001C - float m_radius; // 0x002C - float m_aabbMin[4]; // 0x0030 - float m_aabbMax[4]; // 0x0040 - uint32_t m_flags; // 0x0050 - char _0x0054[0x12]; // 0x0054 - uint16_t m_index; // 0x0066 - }; - - class fwEntity - { - public: - virtual ~fwEntity() = 0; - }; - - class fwArchetypeDef - { - public: - virtual ~fwArchetypeDef(); - - virtual int64_t GetTypeIdentifier(); - - float lodDist; - uint32_t flags; // 0x10000 = alphaclip - uint32_t specialAttribute; // lower 5 bits == 31 -> use alpha clip, get masked to 31 in InitializeFromArchetypeDef - uint32_t pad; - void* pad2; - float bbMin[4]; - float bbMax[4]; - float bsCentre[4]; - float bsRadius; - float hdTextureDist; - uint32_t name; - uint32_t textureDictionary; - uint32_t clipDictionary; - uint32_t drawableDictionary; - uint32_t physicsDictionary; - uint32_t assetType; - uint32_t assetName; - uint32_t pad5[7]; - - public: - fwArchetypeDef() - { - flags = 0x10000; // was 0x2000 - lodDist = 299.0f; - hdTextureDist = 375.0f; - - drawableDictionary = 0; - assetType = 3; - assetName = 0x12345678; - - specialAttribute = 31; - - pad = 0; - pad2 = 0; - clipDictionary = 0; - physicsDictionary = 0; - memset(pad5, 0, sizeof(physicsDictionary)); - } - }; + class fwArchetype { + public: + virtual ~fwArchetype() = default; + + char _0x0008[0x10]; // 0x0000 + Hash m_hash; // 0x0018 + char _0x001C[0x10]; // 0x001C + float m_radius; // 0x002C + float m_aabbMin[4]; // 0x0030 + float m_aabbMax[4]; // 0x0040 + uint32_t m_flags; // 0x0050 + char _0x0054[0x12]; // 0x0054 + uint16_t m_index; // 0x0066 + }; + + class fwEntity + { + public: + virtual ~fwEntity() = 0; + }; + + class fwArchetypeDef + { + public: + virtual ~fwArchetypeDef(); + + virtual int64_t GetTypeIdentifier(); + + float lodDist; + uint32_t flags; // 0x10000 = alphaclip + uint32_t specialAttribute; // lower 5 bits == 31 -> use alpha clip, get masked to 31 in InitializeFromArchetypeDef + uint32_t pad; + void* pad2; + float bbMin[4]; + float bbMax[4]; + float bsCentre[4]; + float bsRadius; + float hdTextureDist; + uint32_t name; + uint32_t textureDictionary; + uint32_t clipDictionary; + uint32_t drawableDictionary; + uint32_t physicsDictionary; + uint32_t assetType; + uint32_t assetName; + uint32_t pad5[7]; + + public: + fwArchetypeDef() + { + flags = 0x10000; // was 0x2000 + lodDist = 299.0f; + hdTextureDist = 375.0f; + + drawableDictionary = 0; + assetType = 3; + assetName = 0x12345678; + + specialAttribute = 31; + + pad = 0; + pad2 = 0; + clipDictionary = 0; + physicsDictionary = 0; + memset(pad5, 0, sizeof(physicsDictionary)); + } + }; } class CBaseModelInfo : public rage::fwArchetype { public: - virtual ~CBaseModelInfo() {} - virtual void Initialize() {} - virtual void InitializeFromArchetypeDef(uint32_t, rage::fwArchetypeDef*, bool) {} - virtual rage::fwEntity* CreateEntity() { return nullptr; } - // and lots of other functions... + virtual ~CBaseModelInfo() {} + virtual void Initialize() {} + virtual void InitializeFromArchetypeDef(uint32_t, rage::fwArchetypeDef*, bool) {} + virtual rage::fwEntity* CreateEntity() { return nullptr; } + // and lots of other functions... public: - eModelType GetModelType() const - { - return m_modelType & 0x1F; - } + eModelType GetModelType() const + { + return m_modelType & 0x1F; + } protected: - char _0x0068[0x35]; // 0x0068 - eModelType m_modelType; // 0x009D (& 0x1F) - char _0x009E[0x2]; // 0x009E - uint32_t m_unkFlag; // 0x00A0 - char _0x00A4[0x4]; // 0x00A4 - void* m_0x00A8; // 0x00A8 + char _0x0068[0x35]; // 0x0068 + eModelType m_modelType; // 0x009D (& 0x1F) + char _0x009E[0x2]; // 0x009E + uint32_t m_unkFlag; // 0x00A0 + char _0x00A4[0x4]; // 0x00A4 + void* m_0x00A8; // 0x00A8 }; class CVehicleModelInfo : public CBaseModelInfo { public: - virtual ~CVehicleModelInfo() {} - virtual void Initialize() {} - virtual void InitializeFromArchetypeDef(uint32_t, rage::fwArchetypeDef*, bool) {} - virtual rage::fwEntity* CreateEntity() { return nullptr; } - // and lots of other functions... + virtual ~CVehicleModelInfo() {} + virtual void Initialize() {} + virtual void InitializeFromArchetypeDef(uint32_t, rage::fwArchetypeDef*, bool) {} + virtual rage::fwEntity* CreateEntity() { return nullptr; } + // and lots of other functions... public: - void* m_0x00B0; // 0x00B0 - char _0x00B8[0x40]; // 0x00B8 - uint8_t m_primaryColorCombinations[25]; // 0x00F8 - uint8_t m_secondaryColorCombinations[25]; // 0x0111 - uint8_t m_unkColor1Combinations[25]; // 0x012A - uint8_t m_unkColor2Combinations[25]; // 0x0143 - uint8_t m_interiorColorCombinations[25]; // 0x015C - uint8_t m_dashboardColorCombinations[25]; // 0x0175 - char _0x018E[0xE2]; // 0x018E - char m_displayName[12]; // 0x0270 (aka gameName) - char m_manufacturerName[12]; // 0x027C (aka makeName) - uint8_t* m_modKits; // 0x0288 - uint16_t m_modKitsCount; // 0x0290 - char _0x0292[0x46]; // 0x0292 - void* m_driverInfo; // 0x02D8 - uint8_t m_numDrivers; // 0x02E0 - char _0x02E1[0x37]; // 0x02E1 - eVehicleType m_vehicleType; // 0x0318 - uint32_t m_unkVehicleType; // 0x031C - uint32_t m_diffuseTint; // 0x0320 - char _0x0324[0x90]; // 0x0324 - uint8_t m_unkModKitVal; // 0x03B4 - char _0x03B5[0xA7]; // 0x03B5 - float m_wheelScale; // 0x045C - float m_wheelScaleRear; // 0x0460 - float m_defaultBodyHealth; // 0x0464 - char _0x0468[0x20]; // 0x0468 - uint32_t m_handlingIndex; // 0x0488 - uint32_t m_identicalModelSpawnDistance; // 0x048C - char _0x0490[0x4]; // 0x0490 - uint32_t m_numColorCombinations; // 0x0494 - char _0x0498[0x30]; // 0x0498 - void* m_0x04C8; // 0x04C8 (wheel data? 0xAC -> burnout mult?) - char _0x04D0[0x3B]; // 0x04D0 - uint8_t m_sirenInfoId; // 0x050B - char _0x050C[0xC]; // 0x050C - uint8_t m_vehicleClass; // 0x0518 (& 0x1F; (>> 5) & 3 -> plate type) - char _0x0519[0x2F]; // 0x0519 - int m_seatCount; // 0x0548 - eVehicleFlag1 m_flags1; // 0x054C - eVehicleFlag2 m_flags2; // 0x0550 - eVehicleFlag3 m_flags3; // 0x0554 - eVehicleFlag4 m_flags4; // 0x0558 - eVehicleFlag5 m_flags5; // 0x055C + void* m_0x00B0; // 0x00B0 + char _0x00B8[0x40]; // 0x00B8 + uint8_t m_primaryColorCombinations[25]; // 0x00F8 + uint8_t m_secondaryColorCombinations[25]; // 0x0111 + uint8_t m_unkColor1Combinations[25]; // 0x012A + uint8_t m_unkColor2Combinations[25]; // 0x0143 + uint8_t m_interiorColorCombinations[25]; // 0x015C + uint8_t m_dashboardColorCombinations[25]; // 0x0175 + char _0x018E[0xE2]; // 0x018E + char m_displayName[12]; // 0x0270 (aka gameName) + char m_manufacturerName[12]; // 0x027C (aka makeName) + uint8_t* m_modKits; // 0x0288 + uint16_t m_modKitsCount; // 0x0290 + char _0x0292[0x46]; // 0x0292 + void* m_driverInfo; // 0x02D8 + uint8_t m_numDrivers; // 0x02E0 + char _0x02E1[0x37]; // 0x02E1 + eVehicleType m_vehicleType; // 0x0318 + uint32_t m_unkVehicleType; // 0x031C + uint32_t m_diffuseTint; // 0x0320 + char _0x0324[0x90]; // 0x0324 + uint8_t m_unkModKitVal; // 0x03B4 + char _0x03B5[0xA7]; // 0x03B5 + float m_wheelScale; // 0x045C + float m_wheelScaleRear; // 0x0460 + float m_defaultBodyHealth; // 0x0464 + char _0x0468[0x20]; // 0x0468 + uint32_t m_handlingIndex; // 0x0488 + uint32_t m_identicalModelSpawnDistance; // 0x048C + char _0x0490[0x4]; // 0x0490 + uint32_t m_numColorCombinations; // 0x0494 + char _0x0498[0x30]; // 0x0498 + void* m_0x04C8; // 0x04C8 (wheel data? 0xAC -> burnout mult?) + char _0x04D0[0x3B]; // 0x04D0 + uint8_t m_sirenInfoId; // 0x050B + char _0x050C[0xC]; // 0x050C + uint8_t m_vehicleClass; // 0x0518 (& 0x1F; (>> 5) & 3 -> plate type) + char _0x0519[0x2F]; // 0x0519 + int m_seatCount; // 0x0548 + eVehicleFlag1 m_flags1; // 0x054C + eVehicleFlag2 m_flags2; // 0x0550 + eVehicleFlag3 m_flags3; // 0x0554 + eVehicleFlag4 m_flags4; // 0x0558 + eVehicleFlag5 m_flags5; // 0x055C }; class CVehicleModelInfo1290 : public CBaseModelInfo { public: - virtual ~CVehicleModelInfo1290() {} - virtual void Initialize() {} - virtual void InitializeFromArchetypeDef(uint32_t, rage::fwArchetypeDef*, bool) {} - virtual rage::fwEntity* CreateEntity() { return nullptr; } - // and lots of other functions... + virtual ~CVehicleModelInfo1290() {} + virtual void Initialize() {} + virtual void InitializeFromArchetypeDef(uint32_t, rage::fwArchetypeDef*, bool) {} + virtual rage::fwEntity* CreateEntity() { return nullptr; } + // and lots of other functions... public: - void* m_0x00B0; // 0x00B0 - char _0x00B8[0x40]; // 0x00B8 - uint8_t m_primaryColorCombinations[25]; // 0x00F8 - uint8_t m_secondaryColorCombinations[25]; // 0x0111 - uint8_t m_unkColor1Combinations[25]; // 0x012A - uint8_t m_unkColor2Combinations[25]; // 0x0143 - uint8_t m_interiorColorCombinations[25]; // 0x015C - uint8_t m_dashboardColorCombinations[25]; // 0x0175 - char _0x018E[0x10A]; // 0x018E - char m_displayName[12]; // 0x0298 (aka gameName) - char m_manufacturerName[12]; // 0x02A4 (aka makeName) - uint16_t* m_modKits; // 0x02B0 - uint16_t m_modKitsCount; // 0x02B8 - char _0x02BA[0x46]; // 0x02BA - void* m_driverInfo; // 0x0300 - uint8_t m_numDrivers; // 0x0308 - char _0x0309[0x37]; // 0x02E3 - eVehicleType m_vehicleType; // 0x0340 - uint32_t m_unkVehicleType; // 0x0344 - uint32_t m_diffuseTint; // 0x0348 - char _0x034C[0x90]; // 0x034C - uint8_t m_unkModKitVal; // 0x03DC (also uint16_t now?) - char _0x03DD[0xA7]; // 0x03DD - float m_wheelScale; // 0x0484 - float m_wheelScaleRear; // 0x0488 - float m_defaultBodyHealth; // 0x048C - char _0x0490[0x20]; // 0x0490 - uint32_t m_handlingIndex; // 0x04B8 - uint32_t m_identicalModelSpawnDistance; // 0x04BC - char _0x04C0[0x4]; // 0x04C0 - uint32_t m_numColorCombinations; // 0x04C4 - uint32_t m_fragmentIndex; // 0x04C8 - char _0x04CC[0x2C]; // 0x04CC - void* m_0x04F8; // 0x04F8 (wheel data? 0xAC -> burnout mult?) - char _0x0500[0x3B]; // 0x0500 - uint8_t m_sirenInfoId; // 0x053B - char _0x053C[0x7]; // 0x053C - uint8_t m_0x0543; // 0x0543 - char _0x0544_[0x4]; // 0x0544 - uint8_t m_vehicleClass; // 0x0548 (& 0x1F; (>> 5) & 3 -> plate type) - char _0x0549[0x2F]; // 0x0549 - int m_seatCount; // 0x0578 (use only if unk_0x00B0->seatCount can't be used) - eVehicleFlag1 m_flags1; // 0x057C - eVehicleFlag2 m_flags2; // 0x0580 - eVehicleFlag3 m_flags3; // 0x0584 - eVehicleFlag4 m_flags4; // 0x0588 - eVehicleFlag5 m_flags5; // 0x058C - eVehicleFlag6 m_flags6; // 0x0590 - char _0x0594[0xC]; // 0x0594 + void* m_0x00B0; // 0x00B0 + char _0x00B8[0x40]; // 0x00B8 + uint8_t m_primaryColorCombinations[25]; // 0x00F8 + uint8_t m_secondaryColorCombinations[25]; // 0x0111 + uint8_t m_unkColor1Combinations[25]; // 0x012A + uint8_t m_unkColor2Combinations[25]; // 0x0143 + uint8_t m_interiorColorCombinations[25]; // 0x015C + uint8_t m_dashboardColorCombinations[25]; // 0x0175 + char _0x018E[0x10A]; // 0x018E + char m_displayName[12]; // 0x0298 (aka gameName) + char m_manufacturerName[12]; // 0x02A4 (aka makeName) + uint16_t* m_modKits; // 0x02B0 + uint16_t m_modKitsCount; // 0x02B8 + char _0x02BA[0x46]; // 0x02BA + void* m_driverInfo; // 0x0300 + uint8_t m_numDrivers; // 0x0308 + char _0x0309[0x37]; // 0x02E3 + eVehicleType m_vehicleType; // 0x0340 + uint32_t m_unkVehicleType; // 0x0344 + uint32_t m_diffuseTint; // 0x0348 + char _0x034C[0x90]; // 0x034C + uint8_t m_unkModKitVal; // 0x03DC (also uint16_t now?) + char _0x03DD[0xA7]; // 0x03DD + float m_wheelScale; // 0x0484 + float m_wheelScaleRear; // 0x0488 + float m_defaultBodyHealth; // 0x048C + char _0x0490[0x20]; // 0x0490 + uint32_t m_handlingIndex; // 0x04B8 + uint32_t m_identicalModelSpawnDistance; // 0x04BC + char _0x04C0[0x4]; // 0x04C0 + uint32_t m_numColorCombinations; // 0x04C4 + uint32_t m_fragmentIndex; // 0x04C8 + char _0x04CC[0x2C]; // 0x04CC + void* m_0x04F8; // 0x04F8 (wheel data? 0xAC -> burnout mult?) + char _0x0500[0x3B]; // 0x0500 + uint8_t m_sirenInfoId; // 0x053B + char _0x053C[0x7]; // 0x053C + uint8_t m_0x0543; // 0x0543 + char _0x0544_[0x4]; // 0x0544 + uint8_t m_vehicleClass; // 0x0548 (& 0x1F; (>> 5) & 3 -> plate type) + char _0x0549[0x2F]; // 0x0549 + int m_seatCount; // 0x0578 (use only if unk_0x00B0->seatCount can't be used) + eVehicleFlag1 m_flags1; // 0x057C + eVehicleFlag2 m_flags2; // 0x0580 + eVehicleFlag3 m_flags3; // 0x0584 + eVehicleFlag4 m_flags4; // 0x0588 + eVehicleFlag5 m_flags5; // 0x058C + eVehicleFlag6 m_flags6; // 0x0590 + char _0x0594[0xC]; // 0x0594 }; struct ScriptHeader { @@ -313,7 +313,7 @@ struct ScriptTable { if (TablePtr == NULL) { return NULL;//table initialisation hasnt happened yet } - for (int i = 0; i pattern); static DWORD64 FindPattern(const char* bMaskc, const char* sMaskc); @@ -422,20 +431,22 @@ class GTAmemory final static UINT64(*_playerAddressFunc)(int handle); static UINT64(*_ptfxAddressFunc)(int handle); static int(*_addEntityToPoolFunc)(UINT64 address); - static UINT64(*_entityPositionFunc)(UINT64 address, float *position); + static UINT64(*_entityPositionFunc)(UINT64 address, float* position); static UINT64(*_entityModel1Func)(UINT64 address), (*_entityModel2Func)(UINT64 address); - static UINT64 *_entityPoolAddress, *_vehiclePoolAddress, *_pedPoolAddress, *_objectPoolAddress, *_cameraPoolAddress, *_pickupObjectPoolAddress; + static inline UINT64* _entityPoolAddress, * _vehiclePoolAddress, * _pedPoolAddress, * _objectPoolAddress, * _cameraPoolAddress, * _pickupObjectPoolAddress; static unsigned char(*SetNmBoolAddress)(__int64, __int64, unsigned char); static unsigned char(*SetNmIntAddress)(__int64, __int64, int); static unsigned char(*SetNmFloatAddress)(__int64, __int64, float); static unsigned char(*SetNmVec3Address)(__int64, __int64, float, float, float); static unsigned char(*SetNmStringAddress)(__int64, __int64, __int64); - static UINT64 CreateNmMessageFunc, GiveNmMessageFunc; + static UINT64(*CreateNmMessageFunc)(uint64_t, uint64_t, int); + static void(*GiveNmMessageFunc)(uint64_t, void*, uint64_t); + static UINT64(*CheckpointBaseAddr)(); static UINT64(*CheckpointHandleAddr)(UINT64 baseAddr, int Handle); - static UINT64 *checkpointPoolAddress; - static float *_readWorldGravityAddress, *_writeWorldGravityAddress; - static UINT64 *_gamePlayCameraAddr; + static UINT64* checkpointPoolAddress; + static float* _readWorldGravityAddress, * _writeWorldGravityAddress; + static UINT64* _gamePlayCameraAddr; static int* _cursorSpriteAddr; static bool* _isMultiplayer; static INT32* _transitionStatus; @@ -443,6 +454,8 @@ class GTAmemory final static BlipList* _blipList; static BlipList* GetBlipList(); + static void InitEnhancedPools(); + // Unknown_Modder struct GXT2Entry { @@ -455,7 +468,7 @@ class GTAmemory final static void EditGXTLabel(DWORD labelHash, LPCSTR string); static UINT64 _gxtLabelFromHashAddr1; // Zorg - static char*(__fastcall *_gxtLabelFromHashFuncAddr)(UINT64 address, unsigned int hash); + static char* (__fastcall* _gxtLabelFromHashFuncAddr)(UINT64 address, unsigned int hash); static inline char* GetGXTEntry(unsigned int labelHash) { return _gxtLabelFromHashFuncAddr(_gxtLabelFromHashAddr1, labelHash); @@ -475,6 +488,10 @@ class GTAmemory final return __getGameVersion_value; } + static inline bool GetIsEnhanced() { + return g_isEnhanced; + } + template static inline T* GetGlobalPtr(int globalId) { //auto addr = getGameVersion() == VER_1_0_678_1_STEAM ? 142B15D00 : 0x142B11810; @@ -558,6 +575,7 @@ class GTAmemory final static UINT64 GetPlayerAddress(int handle); static UINT64 GetCheckpointAddress(int handle); static UINT64 GetPtfxAddress(int handle); + static void GetEntityPos(uint64_t address, float* position); static UINT64 GetEntityBoneMatrixAddress(int handle, int boneIndex); static int GetEntityBoneCount(int handle); @@ -593,7 +611,7 @@ class GTAmemory final static void GetPickupObjectHandles(std::vector& result, const Vector3& position, float radius); static int GetNumberOfVehicles(); - + static float WorldGravity_get(); static void WorldGravity_set(float value); @@ -605,11 +623,12 @@ class GTAmemory final static void GenerateVehicleModelList(); static INT32 TransitionStatus(); - - static uintptr_t FindPattern(const char *pattern, const char *mask, const char *startAddress, size_t size); - static uintptr_t FindPattern(const char *pattern, const char *mask); - - static bool FindShopController(); + + static uintptr_t FindPattern(const char* pattern, const char* mask, const char* startAddress, size_t size); + static uintptr_t FindPattern(const char* pattern, const char* mask); + + static bool FindShopController(); + static bool FindScript(int hash); static std::string GetVehicleModelName(Hash modelHash); static std::string GetVehicleMakeName(Hash modelHash); @@ -622,7 +641,6 @@ class GTAmemory final static const UINT16 poolCount_vehicles; static const UINT16 poolCount_peds; static const UINT16 poolCount_objects; - }; class SpSnow final// This is for sp since the global doesn't work in sp @@ -639,6 +657,8 @@ class SpSnow final// This is for sp since the global doesn't work in sp DWORD64 traxvt; //vehicleTrackTypes UINT8 original1[14]; UINT8 original2[15]; + UINT8 original1EnhancedSnow[8]; + UINT8 original2EnhancedSnow[12]; void EnableSnow(bool bEnable); void EnableTracks(bool tracksPed, bool deepTracksPed, bool tracksVehicle, bool deepTracksVehicle); public: diff --git a/Solution/source/Menu/Menu.cpp b/Solution/source/Menu/Menu.cpp index d57ac70b..ae1a0921 100644 --- a/Solution/source/Menu/Menu.cpp +++ b/Solution/source/Menu/Menu.cpp @@ -433,7 +433,7 @@ void Menu::background() float temp; if (totalop > GTA_MAXOP) temp = GTA_MAXOP; else temp = (float)totalop; // Calculate last option number to draw rect - // Calculate Y Coord + // Calculate Y Coord float bg_Y = ((temp * 0.035f) / 2.0f) + 0.159f; float bg_length = temp * 0.035f; @@ -526,10 +526,15 @@ void Menu::while_closed() { if (isBinds()) { + + addlog(ige::LogType::LOG_TRACE, "Binds Pressed, opening Menyoo", __FILENAME__); if (g_menuNotOpenedYet) justopened(); + GTAmemory::InitEnhancedPools(); + Game::Sound::PlayFrontend("FocusIn", "HintCamSounds"); + currentsub = LOOCsub; if (currentsub == SUB::MAINMENU) { @@ -547,7 +552,10 @@ void Menu::while_opened() totalop = printingop; printingop = 0; totalbreaks = breakcount; breakcount = 0; breakscroll = 0; - if (IS_PAUSE_MENU_ACTIVE()) SetSub_closed(); + if (IS_PAUSE_MENU_ACTIVE()) { + addlog(ige::LogType::LOG_TRACE, "Game Paused, closing Menyoo", __FILENAME__); + SetSub_closed(); + } if (IS_GAMEPLAY_HINT_ACTIVE()) STOP_GAMEPLAY_HINT(false); DISPLAY_AMMO_THIS_FRAME(0); @@ -567,6 +575,7 @@ void Menu::while_opened() // Scroll up if (MenuPressTimer::IsButtonHeldOrTapped(MenuPressTimer::Button::Up)) { + addlog(ige::LogType::LOG_TRACE, "Up Pressed, moving selection up", __FILENAME__); if (currentop <= 1) Bottom(); else @@ -576,6 +585,7 @@ void Menu::while_opened() // Scroll down if (MenuPressTimer::IsButtonHeldOrTapped(MenuPressTimer::Button::Down)) { + addlog(ige::LogType::LOG_TRACE, "Down Pressed, moving selection down", __FILENAME__); if (currentop >= totalop) Top(); else @@ -585,6 +595,7 @@ void Menu::while_opened() // B press if (MenuPressTimer::IsButtonTapped(MenuPressTimer::Button::Back)) { + addlog(ige::LogType::LOG_TRACE, "Back Pressed, returning to previous menu", __FILENAME__); if (currentsub == SUB::MAINMENU) SetSub_closed(); else @@ -594,9 +605,10 @@ void Menu::while_opened() // Binds press if (isBinds())//&& currentsub != SUB::MAINMENU) { + addlog(ige::LogType::LOG_TRACE, "Binds Pressed, closing Menyoo", __FILENAME__); SetSub_closed(); } - + } void Menu::Up(bool playSound) { @@ -640,7 +652,7 @@ void Menu::SetSub_previous() currentsub = currentsub_ar[currentsub_ar_index]; // Get previous submenu from array and set as current submenu currentop = currentop_ar[currentsub_ar_index]; // Get last selected option from array and set as current selected option - + currentsub_ar[currentsub_ar_index] = -2; currentop_ar[currentsub_ar_index] = -2; @@ -847,13 +859,20 @@ void Menu::draw_IB() void Menu::sub_handler() { + static bool firstRun = true; + if(firstRun) + { + addlog(ige::LogType::LOG_TRACE, "First Run sub_handler", __FILENAME__);; + } if (currentsub == SUB::CLOSED) { + if (firstRun) addlog(ige::LogType::LOG_TRACE, "Sub Currently Closed", __FILENAME__);; while_closed(); } else { + if (firstRun) addlog(ige::LogType::LOG_TRACE, "Sub Currently Open", __FILENAME__);; submenu_switch(); if (Menu::currentop > Menu::printingop) { Menu::currentop = Menu::printingop + 1; Menu::Up(false); } @@ -877,7 +896,7 @@ void Menu::sub_handler() delayedTimer = GET_GAME_TIMER() + 810; // Delay for rainbow related loops if (delayedTimer > INT_MAX - 1000) delayedTimer = 0; } - + firstRun = false; } //--------------------------------MouseSupport--------------------------------------------------- diff --git a/Solution/source/Menu/MenuConfig.cpp b/Solution/source/Menu/MenuConfig.cpp index 7b2ac926..ca67d6b1 100644 --- a/Solution/source/Menu/MenuConfig.cpp +++ b/Solution/source/Menu/MenuConfig.cpp @@ -69,6 +69,7 @@ void MenuConfig::ConfigInit() addlog(ige::LogType::LOG_ERROR, "Failed to load menyooConfig from " + GetPathffA(Pathff::Main, true) + "menyooConfig.ini.", __FILENAME__); else { ConfigRead(); + addlog(ige::LogType::LOG_INFO, "Logging level " + std::to_string(g_loglevel) + " active. Edit loglevel in menyooconfig.ini to change.", __FILENAME__); addlog(ige::LogType::LOG_INFO, "Config loaded from " + GetPathffA(Pathff::Main, true) + "menyooConfig.ini.", __FILENAME__); } } diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index faf9f707..aacca314 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -99,50 +99,51 @@ void Menu::justopened() SET_THIS_SCRIPT_CAN_BE_PAUSED(0); SET_THIS_SCRIPT_CAN_REMOVE_BLIPS_CREATED_BY_ANY_SCRIPT(0); // lol poopoo dummy me this isn't a ysc - if ( - IS_DLC_PRESENT(GET_HASH_KEY("mp2023_01_g9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("mp2023_02_g9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("mpchristmas3_g9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("mpg9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("mpSum2_G9EC")) or - IS_DLC_PRESENT(GET_HASH_KEY("patch2023_01_g9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("patchday27g9ecng")) or - IS_DLC_PRESENT(GET_HASH_KEY("patchday28g9ecng")) or - IS_DLC_PRESENT(GET_HASH_KEY("patchdayg9ecng")) or - IS_DLC_PRESENT(GET_HASH_KEY("patch2024_01_g9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("mp2024_01_g9ec")) or - IS_DLC_PRESENT(GET_HASH_KEY("mp2024_02_g9ec")) //this hardcoding needs to get in the bin. - ) - { - Game::Print::PrintBottomCentre("~r~Warning~s~: 9th Gen content detected, Game may crash. Read Menyoolog for fix instructions."); - ige::myLog << ige::LogType::LOG_WARNING << "Gen9 Content found in dlcpacks, this can cause instability when attempted to be loaded by Menyoo." << std::endl - << " You can find these in your dlclist.xml by searching for \"g9\" and removing these lines or using a comment." << std::endl - << " For example: " << std::endl << std::endl - << " Current known Gen9 Packs:" << std::endl - << " patchdayg9ecng" << std::endl - << " mpsum2_g9ec" << std::endl - << " patchday27g9ecng" << std::endl - << " mpchristmas3_g9ec" << std::endl - << " patchday28g9ecng" << std::endl - << " mp2023_01_g9ec" << std::endl - << " mp2023_02_g9ec" << std::endl - << " patch2024_01_g9ec" << std::endl - << " mp2024_01_g9ec" << std::endl - << " mp2024_02_g9ec" << std::endl << std::endl - << " Note: mp2024_02 also contains bugged content. If you continue to experience issues, removing this may help" << std::endl << std::endl; - } - else if ( - IS_DLC_PRESENT(GET_HASH_KEY("mp2024_02")) //f*cking rockstar cocked up some clothes, this warning is the only protection. - ) - { - Game::Print::PrintBottomCentre("~r~Warning~s~: DLCPack mp2024_02 present, Game may crash. Read Menyoolog for fix instructions."); - ige::myLog << ige::LogType::LOG_WARNING << "mp2024_02 found in dlcpacks, certain bugged clothing can cause instability when attempted to be loaded by Menyoo." << std::endl - << " You can find this in your dlclist.xml by searching for \"mp2024_02\" and removing these lines or using a comment." << std::endl - << " For example: " << std::endl << std::endl - << " Note: this issue can be ignored if bugged content has been fixed by a mod" << std::endl; + if (!GTAmemory::GetIsEnhanced()) { + if ( + IS_DLC_PRESENT(GET_HASH_KEY("mp2023_01_g9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("mp2023_02_g9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("mpchristmas3_g9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("mpg9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("mpSum2_G9EC")) or + IS_DLC_PRESENT(GET_HASH_KEY("patch2023_01_g9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("patchday27g9ecng")) or + IS_DLC_PRESENT(GET_HASH_KEY("patchday28g9ecng")) or + IS_DLC_PRESENT(GET_HASH_KEY("patchdayg9ecng")) or + IS_DLC_PRESENT(GET_HASH_KEY("patch2024_01_g9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("mp2024_01_g9ec")) or + IS_DLC_PRESENT(GET_HASH_KEY("mp2024_02_g9ec")) //this hardcoding needs to get in the bin. + ) + { + Game::Print::PrintBottomCentre("~r~Warning~s~: 9th Gen content detected, Game may crash. Read Menyoolog for fix instructions."); + ige::myLog << ige::LogType::LOG_WARNING << "Gen9 Content found in dlcpacks, this can cause instability when attempted to be loaded by Menyoo." << std::endl + << " You can find these in your dlclist.xml by searching for \"g9\" and removing these lines or using a comment." << std::endl + << " For example: " << std::endl << std::endl + << " Current known Gen9 Packs:" << std::endl + << " patchdayg9ecng" << std::endl + << " mpsum2_g9ec" << std::endl + << " patchday27g9ecng" << std::endl + << " mpchristmas3_g9ec" << std::endl + << " patchday28g9ecng" << std::endl + << " mp2023_01_g9ec" << std::endl + << " mp2023_02_g9ec" << std::endl + << " patch2024_01_g9ec" << std::endl + << " mp2024_01_g9ec" << std::endl + << " mp2024_02_g9ec" << std::endl << std::endl + << " Note: mp2024_02 also contains bugged content. If you continue to experience issues, removing this may help" << std::endl << std::endl; + } + else if ( + IS_DLC_PRESENT(GET_HASH_KEY("mp2024_02")) //f*cking rockstar cocked up some clothes, this warning is the only protection. + ) + { + Game::Print::PrintBottomCentre("~r~Warning~s~: DLCPack mp2024_02 present, Game may crash. Read Menyoolog for fix instructions."); + ige::myLog << ige::LogType::LOG_WARNING << "mp2024_02 found in dlcpacks, certain bugged clothing can cause instability when attempted to be loaded by Menyoo." << std::endl + << " You can find this in your dlclist.xml by searching for \"mp2024_02\" and removing these lines or using a comment." << std::endl + << " For example: " << std::endl << std::endl + << " Note: this issue can be ignored if bugged content has been fixed by a mod" << std::endl; + } } - //sub::SettingsThemes_catind::g_menyooTheme_temp = sub::SettingsThemes_catind::MenyooTheme::CurrentlyActiveTheme(); sub::PopulateAllPaintIDs(); @@ -151,16 +152,28 @@ void Menu::justopened() } inline void MenyooMain() { + bool firstTick = true; + addlog(ige::LogType::LOG_TRACE, "Loading Textures", __FILENAME__); DxHookIMG::LoadAllMenyooTexturesInit(); + addlog(ige::LogType::LOG_TRACE, "Populate Anims List", __FILENAME__); sub::AnimationSub_catind::PopulateAllPedAnimsList(); + addlog(ige::LogType::LOG_TRACE, "Populate Favourites", __FILENAME__); sub::WeaponFavourites_catind::PopulateFavouritesInfo(); + addlog(ige::LogType::LOG_TRACE, "Populate Decals", __FILENAME__); sub::PedDecals_catind::PopulateDecalsDict(); + addlog(ige::LogType::LOG_TRACE, "Populate Animals", __FILENAME__); sub::AnimalRiding_catind::PopulateAnimals(); + addlog(ige::LogType::LOG_TRACE, "Populate Vehicle Previews", __FILENAME__); sub::SpawnVehicle_catind::PopulateVehicleBmps(); + addlog(ige::LogType::LOG_TRACE, "Populate Folder Previews", __FILENAME__); sub::FolderPreviewBmps_catind::PopulateFolderBmps(); + addlog(ige::LogType::LOG_TRACE, "Populate Voice Data", __FILENAME__); sub::Speech_catind::PopulateVoiceData(); + addlog(ige::LogType::LOG_TRACE, "Populate Timecycle Names", __FILENAME__); TimecycleModification::PopulateTimecycleNames(); + addlog(ige::LogType::LOG_TRACE, "Populate Global Entity Arrays", __FILENAME__); PopulateGlobalEntityModelsArrays(); + addlog(ige::LogType::LOG_TRACE, "Populate Cutscene Labels", __FILENAME__); sub::CutscenePlayer_catind::PopulateCutsceneLabels(); srand(GetTickCount()); @@ -171,43 +184,69 @@ inline void MenyooMain() g_MenyooConfigTick = GetTickCount(); g_FaderTick = GetTickCount(); + + addlog(ige::LogType::LOG_TRACE, "Check Valid for Block Vehicles", __FILENAME__); if (!NETWORK_IS_SESSION_STARTED() && !IS_COMMANDLINE_END_USER_BENCHMARK() && !LANDING_SCREEN_STARTED_END_USER_BENCHMARK()) { + addlog(ige::LogType::LOG_TRACE, "Valid, Enabling Blocked Vehicles", __FILENAME__); if (GTAmemory::FindShopController()) GeneralGlobalHax::EnableBlockedMpVehiclesInSp(); } + else + { + addlog(ige::LogType::LOG_ERROR, "Invalid, Unable to Unblock Vehicles", __FILENAME__); + } + addlog(ige::LogType::LOG_TRACE, "Creating Tick loop", __FILENAME__); for (;;) { + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - Textures", __FILENAME__); DxHookIMG::DxTexture::GlobalDrawOrderRef() = -9999; - + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - Tick", __FILENAME__); Menu::Tick(); + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - Load MenyooConfig", __FILENAME__); TickMenyooConfig(); + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - Rainbow Fader", __FILENAME__); TickRainbowFader(); WAIT(0); + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - looping", __FILENAME__); + firstTick = false; } } void ThreadMenyooMain() { + addlog(ige::LogType::LOG_TRACE, "Launching MenyooMain", __FILENAME__); MenyooMain(); } void TickMenyooConfig() { + static bool firstTick = true; + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - Run TickMenyooConfig", __FILENAME__); //if (GetTickCount() > g_MenyooConfigOnceTick + 9000U) - if (GetTickCount() > g_MenyooConfigTick + 30000U) + if (GetTickCount() > g_MenyooConfigTick + 30000U) + { + if (MenuConfig::bSaveAtIntervals) { - if (MenuConfig::bSaveAtIntervals) - { - MenuConfig::ConfigSave(); - } - g_MenyooConfigTick = GetTickCount(); + MenuConfig::ConfigSave(); } + g_MenyooConfigTick = GetTickCount(); + } + firstTick = false; } void TickRainbowFader() { + static bool firstTick = true; + if (firstTick) + addlog(ige::LogType::LOG_TRACE, "First Tick - Run TickRainbowFader", __FILENAME__); if (GetTickCount() > g_FaderTick + 20U) { auto& colour = g_fadedRGB; if (colour.R > 0 && colour.B == 0) @@ -225,6 +264,7 @@ void TickRainbowFader() colour.R++; colour.B--; } + firstTick = false; g_FaderTick = GetTickCount(); } @@ -382,13 +422,14 @@ void update_nearby_stuff_arrays_tick() _worldVehicles.clear(); _worldObjects.clear(); _worldEntities.clear(); - //bool alreadyIn; - GTAmemory::GetVehicleHandles(_worldVehicles); - GTAmemory::GetPedHandles(_worldPeds); - GTAmemory::GetPropHandles(_worldObjects); - GTAmemory::GetEntityHandles(_worldEntities); - + if(false) + { + GTAmemory::GetVehicleHandles(_worldVehicles); + GTAmemory::GetPedHandles(_worldPeds); + GTAmemory::GetPropHandles(_worldObjects); + GTAmemory::GetEntityHandles(_worldEntities); + } /*INT i, offsettedID, count = 80; Ped *peds = new Ped[count * 2 + 2]; @@ -423,7 +464,7 @@ void update_nearby_stuff_arrays_tick() INT i, offsettedID, count = 100; - Ped *peds = new Ped[count * 2 + 2]; + Ped* peds = new Ped[count * 2 + 2]; peds[0] = count; INT found = GET_PED_NEARBY_PEDS(me, (Any*)peds, -1); for (i = 0; i < found; i++) @@ -446,7 +487,7 @@ void update_nearby_stuff_arrays_tick() delete[] peds; - Vehicle *vehicles = new Vehicle[count * 2 + 2]; + Vehicle* vehicles = new Vehicle[count * 2 + 2]; vehicles[0] = count; found = GET_PED_NEARBY_VEHICLES(me, (Any*)vehicles); for (i = 0; i < found; i++) @@ -1262,7 +1303,7 @@ void set_forge_gun_dist(float& distance) inline void set_forge_gun_rot_hotkeys() { Vector3 Rot = GET_ENTITY_ROTATION(targ_slot_entity, 2); - FLOAT &precision = _globalForgeGun_prec; + FLOAT& precision = _globalForgeGun_prec; if (!Menu::bit_controller) { @@ -2794,11 +2835,11 @@ void set_vehicle_wheels_invisible(GTAvehicle vehicle, bool enable) g_vehWheelsInvisForRussian.insert(vehicle.Handle()); vehicle.RequestControl(800); - vehicle.SetForwardSpeed(DBL_MAX*DBL_MAX); + vehicle.SetForwardSpeed(DBL_MAX * DBL_MAX); WAIT(100); - SET_VEHICLE_CHEAT_POWER_INCREASE(vehicle.Handle(), DBL_MAX*DBL_MAX); - MODIFY_VEHICLE_TOP_SPEED(vehicle.Handle(), DBL_MAX*DBL_MAX); - vehicle.ApplyForceRelative(Vector3(0, 0, -DBL_MAX*DBL_MAX)); + SET_VEHICLE_CHEAT_POWER_INCREASE(vehicle.Handle(), DBL_MAX * DBL_MAX); + MODIFY_VEHICLE_TOP_SPEED(vehicle.Handle(), DBL_MAX * DBL_MAX); + vehicle.ApplyForceRelative(Vector3(0, 0, -DBL_MAX * DBL_MAX)); WAIT(100); if (g_multList_rpm.count(vehicle.Handle())) { @@ -2886,7 +2927,7 @@ void Set_Walkunderwater(Entity PlayerPed) SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::IsSwimming, false); SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::WasSwimming, false); SET_PED_CONFIG_FLAG(PlayerPed, ePedConfigFlags::_0xD8072639, false); - + Vector3 PlayerPos = GET_ENTITY_COORDS(PlayerPed, 0); DRAW_LIGHT_WITH_RANGEEX(PlayerPos.x, PlayerPos.y, (PlayerPos.z + 1.5f), 255, 255, 251, 100.0f, 1.5f, 0.0f); DRAW_LIGHT_WITH_RANGEEX(PlayerPos.x, PlayerPos.y, (PlayerPos.z + 50.0f), 255, 255, 251, 200.0f, 1.0f, 0.0f); @@ -2906,7 +2947,7 @@ void Set_Walkunderwater(Entity PlayerPed) APPLY_FORCE_TO_ENTITY(PlayerPed, true, 0, 0, -0.7f, 0, 0, 0, true, true, true, true, false, true); } - if (GET_IS_TASK_ACTIVE(PlayerPed, 281)|| IS_PED_SWIMMING(PlayerPed) || IS_PED_SWIMMING_UNDER_WATER(PlayerPed)) // Stop Swimming + if (GET_IS_TASK_ACTIVE(PlayerPed, 281) || IS_PED_SWIMMING(PlayerPed) || IS_PED_SWIMMING_UNDER_WATER(PlayerPed)) // Stop Swimming { CLEAR_PED_TASKS_IMMEDIATELY(PlayerPed); } @@ -2980,11 +3021,12 @@ void Menu::loops() bool gameIsPaused = IS_PAUSE_MENU_ACTIVE() != 0; int iped, player; GTAplayer player2; - if (!GET_IS_LOADING_SCREEN_ACTIVE() && !defaultPedSet) {//This will load a preset Outfit XML from the menyooStuff folder on startup - sub::ComponentChanger_Outfit_catind::Apply(PLAYER_PED_ID(), "menyooStuff/defaultPed.xml", true, false, false, false, false, false); - sub::ComponentChanger_Outfit_catind::Apply(PLAYER_PED_ID(), "menyooStuff/defaultPed.xml", false, true, true, true, true, true); - defaultPedSet = true; -} + if (!GET_IS_LOADING_SCREEN_ACTIVE() && !defaultPedSet) //This will load a preset Outfit XML from the menyooStuff folder on startup + { + sub::ComponentChanger_Outfit_catind::Apply(PLAYER_PED_ID(), "menyooStuff/defaultPed.xml", true, false, false, false, false, false); + sub::ComponentChanger_Outfit_catind::Apply(PLAYER_PED_ID(), "menyooStuff/defaultPed.xml", false, true, true, true, true, true); + defaultPedSet = true; + } Game::CustomHelpText::Tick(); update_nearby_stuff_arrays_tick(); @@ -3078,7 +3120,7 @@ void Menu::loops() if (_JumpAroundMode_::bEnabled) _JumpAroundMode_::Tick(); } - + if (loop_player_Walkunderwater) Set_Walkunderwater(PLAYER_PED_ID()); @@ -3280,7 +3322,7 @@ void Menu::loops() if (loop_self_refillHealthInCover) set_self_refill_health_when_in_cover(); - + // PLAYER_ID() invincibility if (loop_player_invincibility/* && !GET_PLAYER_INVINCIBLE(PLAYER_ID())*/) { diff --git a/Solution/source/Menyoo.rc b/Solution/source/Menyoo.rc index 8deceaaf..2bf4b1d0 100644 --- a/Solution/source/Menyoo.rc +++ b/Solution/source/Menyoo.rc @@ -116,4 +116,9 @@ END FX_ASI_BUILD 3570 BEGIN "\0" +END + +FX_ASI_BUILD 3586 +BEGIN +"\0" END \ No newline at end of file diff --git a/Solution/source/Menyoo.vcxproj b/Solution/source/Menyoo.vcxproj index 67c8e2ff..a7d12d0d 100644 --- a/Solution/source/Menyoo.vcxproj +++ b/Solution/source/Menyoo.vcxproj @@ -247,7 +247,7 @@ DynamicLibrary true - v141 + v143 Unicode diff --git a/Solution/source/Menyoo.vcxproj.filters b/Solution/source/Menyoo.vcxproj.filters index abe9bc38..bfcf88c1 100644 --- a/Solution/source/Menyoo.vcxproj.filters +++ b/Solution/source/Menyoo.vcxproj.filters @@ -313,6 +313,7 @@ Menu + @@ -643,6 +644,7 @@ Menu + diff --git a/Solution/source/Scripting/ModelNames.cpp b/Solution/source/Scripting/ModelNames.cpp index d680f90a..c132a860 100644 --- a/Solution/source/Scripting/ModelNames.cpp +++ b/Solution/source/Scripting/ModelNames.cpp @@ -120,7 +120,7 @@ void PopulatePedModelsArray() { "StoryScenarioFemale", &g_pedModels_StoryScenarioFemale }, { "StoryScenarioMale", &g_pedModels_StoryScenarioMale }, { "Others", &g_pedModels_Others }, - }) + }) { auto nodeCat = nodeRoot.find_child_by_attribute("name", cta.first.c_str()); if (nodeCat) @@ -202,13 +202,14 @@ void PopulateVehicleModelsArray() }; const bool isMinGameVersion3095 = GTAmemory::GetGameVersion() >= eGameVersion::VER_1_0_3095_0; + bool tmpEnhanced = GTAmemory::GetIsEnhanced(); for (int d = 0x0; d < 0x20; d++) { for (auto& dd : hashes[d]) { if (std::find(g_vehHashes.begin(), g_vehHashes.end(), Model(dd)) == g_vehHashes.end()) { - if (!isMinGameVersion3095 || !IS_VEHICLE_GEN9_EXCLUSIVE_MODEL(dd)) + if (tmpEnhanced || !isMinGameVersion3095 || !IS_VEHICLE_GEN9_EXCLUSIVE_MODEL(dd)) { if (Model(dd).VehicleModelName().starts_with("drift")) { diff --git a/Solution/source/Scripting/World.cpp b/Solution/source/Scripting/World.cpp index 5b388003..5760ee76 100644 --- a/Solution/source/Scripting/World.cpp +++ b/Solution/source/Scripting/World.cpp @@ -211,7 +211,7 @@ namespace World void GetNearbyPeds(std::vector& result, GTAped ped, float radius, int maxAmount) { const Vector3 position = ped.Position_get(); - int *handles = new int[maxAmount * 2 + 2]; + int* handles = new int[maxAmount * 2 + 2]; handles[0] = maxAmount; @@ -257,7 +257,7 @@ namespace World void GetNearbyVehicles(std::vector& result, GTAped ped, float radius, int maxAmount) { const Vector3 position = ped.Position_get(); - int *handles = new int[maxAmount * 2 + 2]; + int* handles = new int[maxAmount * 2 + 2]; handles[0] = maxAmount; @@ -687,7 +687,7 @@ namespace World const Vector3& originCoord = originPed.Position_get(); - Ped *peds = new Ped[140 * 2 + 2]; // Five minutes into doubled stack size and chill and it gives you that ped handle + Ped* peds = new Ped[140 * 2 + 2]; // Five minutes into doubled stack size and chill and it gives you that ped handle peds[0] = 140; INT found = GET_PED_NEARBY_PEDS(originPed.Handle(), (Any*)peds, -1); for (i = 0; i < found; i++) @@ -761,7 +761,7 @@ namespace World // World - clear area void clear_area_of_entities(const EntityType& type, const Vector3& coords, float radius, const std::vector& excludes) { - + if (GTAmemory::GetIsEnhanced()) return; // It actually works for enhanced now, but after some time of clearing entities, the game crashes? TODO: investigate why that is. //LOAD_ALL_OBJECTS_NOW(); //LOAD_SCENE(coords.x, coords.y, coords.z); //SET_STREAMING(TRUE); @@ -819,7 +819,7 @@ void clear_area_of_vehicles_around_entity(Entity entity, float radius, bool memr if (IS_PED_SITTING_IN_ANY_VEHICLE(entity)) oldcar = GET_VEHICLE_PED_IS_IN(entity, 0); - Vehicle *vehicles = new Vehicle[160 * 2 + 2]; + Vehicle* vehicles = new Vehicle[160 * 2 + 2]; vehicles[0] = 160; found = GET_PED_NEARBY_VEHICLES(entity, (Any*)vehicles); for (i = 0; i < found; i++) @@ -865,7 +865,7 @@ void clear_area_of_peds_around_entity(Entity entity, float radius, bool memry) { INT i, offsettedID, found; - Ped *peds = new Ped[160 * 2 + 2]; + Ped* peds = new Ped[160 * 2 + 2]; peds[0] = 160; found = GET_PED_NEARBY_PEDS(entity, (Any*)peds, -1); for (i = 0; i < found; i++) diff --git a/Solution/source/Submenus/MainMenu.cpp b/Solution/source/Submenus/MainMenu.cpp index 23df7499..f1f5e05d 100644 --- a/Solution/source/Submenus/MainMenu.cpp +++ b/Solution/source/Submenus/MainMenu.cpp @@ -14,12 +14,19 @@ #include "..\Menu\Menu.h" #include "..\Menu\Routine.h" + #include "..\Natives\natives2.h" +#include "../Util/FileLogger.h" namespace sub { void MainMenu() { + static bool firstLoad = true; + if(firstLoad) { + firstLoad = false; + addlog(ige::LogType::LOG_TRACE, "First Load of MainMenu Submenu", __FILENAME__); + } AddTitle("MENYOO"); AddOption("Players", null, nullFunc, SUB::PLAYERSSUB); diff --git a/Solution/source/Submenus/PedModelChanger.cpp b/Solution/source/Submenus/PedModelChanger.cpp index 37e5acad..ab0c598a 100644 --- a/Solution/source/Submenus/PedModelChanger.cpp +++ b/Solution/source/Submenus/PedModelChanger.cpp @@ -17,6 +17,7 @@ #include "..\Natives\natives2.h" #include "..\Scripting\Model.h" #include "..\Util\ExePath.h" +#include "..\Util\FileLogger.h" #include "..\Util\StringManip.h" #include "..\Util\keyboard.h" #include "..\Scripting\Game.h" @@ -340,6 +341,7 @@ namespace sub void ModelChanger_() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger", __FILENAME__); bool ModelChangerRandomPedVariation_ = 0, ModelChangerInput_ = 0; // ModelChangerVariationWarning_ = 0, @@ -366,8 +368,9 @@ namespace sub AddOption("Others", null, nullFunc, SUB::MODELCHANGER_OTHERS); AddOption("~b~Input~s~ Model", ModelChangerInput_); - + addlog(ige::LogType::LOG_TRACE, "Created ModelChanger Options", __FILENAME__); if (ModelChangerRandomPedVariation_) { + addlog(ige::LogType::LOG_TRACE, "Random Ped Selected", __FILENAME__); SET_PED_RANDOM_COMPONENT_VARIATION(Static_241, 0); SET_PED_RANDOM_PROPS(Static_241); return; @@ -404,6 +407,7 @@ namespace sub // I would really like this whole section to be refactored into one function - IJC void ModelChanger_Player() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Player", __FILENAME__); AddTitle("Player"); std::pair rngped; do { @@ -417,6 +421,7 @@ namespace sub } void ModelChanger_Animal() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Animal", __FILENAME__); AddTitle("Animals"); std::pair rngped; do { @@ -430,12 +435,19 @@ namespace sub } void ModelChanger_AmbientFemale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_AmbientFemale", __FILENAME__); AddTitle("Ambient Females"); + addlog(ige::LogType::LOG_TRACE, "Creating rngped variable", __FILENAME__); std::pair rngped; + addlog(ige::LogType::LOG_TRACE, "Getting Ped Model options", __FILENAME__); do { + addlog(ige::LogType::LOG_TRACE, "Starting Loop", __FILENAME__); rngped = g_pedModels_AmbientFemale[std::rand() % g_pedModels_AmbientFemale.size()]; + addlog(ige::LogType::LOG_TRACE, "Got rngped: " + rngped.first + ", " + rngped.second, __FILENAME__); } while (rngped.first == Game::PlayerPed().Model()); + addlog(ige::LogType::LOG_TRACE, "Creating Random Option", __FILENAME__); AddmodelOption_("Random", (rngped.first), nullptr, 0); + addlog(ige::LogType::LOG_TRACE, "Creating Ped Model options", __FILENAME__); for (auto& pmn : g_pedModels_AmbientFemale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -443,6 +455,7 @@ namespace sub } void ModelChanger_AmbientMale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_AmbientMale", __FILENAME__); AddTitle("Ambient Males"); std::pair rngped; do { @@ -456,6 +469,7 @@ namespace sub } void ModelChanger_Cutscene() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Cutscene", __FILENAME__); AddTitle("Cutscene Models"); std::pair rngped; do { @@ -469,6 +483,7 @@ namespace sub } void ModelChanger_GangFemale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_GangFemale", __FILENAME__); AddTitle("Gang Females"); std::pair rngped; do { @@ -482,6 +497,7 @@ namespace sub } void ModelChanger_GangMale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_GangMale", __FILENAME__); AddTitle("Gang Males"); std::pair rngped; do { @@ -495,6 +511,7 @@ namespace sub } void ModelChanger_Story() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Story", __FILENAME__); AddTitle("Story Models"); std::pair rngped; do { @@ -508,6 +525,7 @@ namespace sub } void ModelChanger_Multiplayer() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Multiplayer", __FILENAME__); AddTitle("Multiplayer Models"); std::pair rngped; do { @@ -521,6 +539,7 @@ namespace sub } void ModelChanger_ScenarioFemale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_ScenarioFemale", __FILENAME__); AddTitle("Scenario Females"); std::pair rngped; do { @@ -534,6 +553,7 @@ namespace sub } void ModelChanger_ScenarioMale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_ScenarioMale", __FILENAME__); AddTitle("Scenario Males"); std::pair rngped; do { @@ -547,6 +567,7 @@ namespace sub } void ModelChanger_Story_ScenarioFemale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Story_ScenarioFemale", __FILENAME__); AddTitle("Story Scenario Females"); std::pair rngped; do { @@ -560,6 +581,7 @@ namespace sub } void ModelChanger_Story_ScenarioMale() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Story_ScenarioMale", __FILENAME__); AddTitle("Story Scenario Males"); std::pair rngped; do { @@ -573,6 +595,7 @@ namespace sub } void ModelChanger_Others() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Others", __FILENAME__); AddTitle("Others"); std::pair rngped; do { diff --git a/Solution/source/Submenus/PlayerOptions.cpp b/Solution/source/Submenus/PlayerOptions.cpp index 73ad3656..5330121e 100644 --- a/Solution/source/Submenus/PlayerOptions.cpp +++ b/Solution/source/Submenus/PlayerOptions.cpp @@ -72,10 +72,11 @@ namespace sub std::vector forcefield_names{ "Off", "Push Out", "Destroy" }; + float& fHeight = g_playerVerticalElongationMultiplier;//GeneralGlobalHax::GetPlayerHeight(); - //float fMovementSpeed = 0.0f, fSwimSpeed = 0.0f; - float fMovementSpeed = GeneralGlobalHax::GetPlayerMovementSpeed(); - float fSwimSpeed = GeneralGlobalHax::GetPlayerSwimSpeed(); + float fMovementSpeed = 0.0f, fSwimSpeed = 0.0f; + //float fMovementSpeed = GeneralGlobalHax::GetPlayerMovementSpeed(); //Memory hax causing crash in enhanced + //float fSwimSpeed = GeneralGlobalHax::GetPlayerSwimSpeed(); bool butAmIOnline = NETWORK_IS_IN_SESSION() != 0; @@ -149,11 +150,13 @@ namespace sub //AddOption("Collision ON", vcollisionon); //AddOption("Collision OFF", vcollisionoff); + if (vcollisionon || vcollisionoff) myPed.IsCollisionEnabled_set(!myPed.IsCollisionEnabled_get()); //if (vcollisionon) SET_ENTITY_COLLISION(PLAYER_PED_ID(), TRUE, 0); //if (vcollisionoff) SET_ENTITY_COLLISION(PLAYER_PED_ID(), FALSE, 0); if (PlayerOpsReplenishPlayer_) { + addlog(ige::LogType::LOG_TRACE, "Replenishing Player", __FILENAME__); myPed.Health_set(myPed.MaxHealth_get()); myPed.Armour_set(myPlayer.MaxArmour_get()); PedDamageTextures_catind::ClearAllBloodDamage(myPed); @@ -162,6 +165,7 @@ namespace sub } if (PlayerOpsInvincibilityOff_) { + addlog(ige::LogType::LOG_TRACE, "Turning Off Invincibility", __FILENAME__); SET_PLAYER_INVINCIBLE(PLAYER_ID(), 0); set_ped_invincible_off(PLAYER_PED_ID()); return; diff --git a/Solution/source/Submenus/WeatherOptions.cpp b/Solution/source/Submenus/WeatherOptions.cpp index 1f224eeb..e226aa60 100644 --- a/Solution/source/Submenus/WeatherOptions.cpp +++ b/Solution/source/Submenus/WeatherOptions.cpp @@ -49,7 +49,8 @@ namespace sub { 24.9f, "Jupiter 24.9" }, { 274.0f, "Sun 274.0" } }; - float mult_0_gravity = GTAmemory::WorldGravity_get(); + //float mult_0_gravity = GTAmemory::WorldGravity_get(); + float mult_0_gravity = 9.8f; float windSpeed = GET_WIND_SPEED(); float wavesHeight = GET_DEEP_OCEAN_SCALER(); @@ -96,39 +97,46 @@ namespace sub if (windSpeed_plus) { + addlog(ige::LogType::LOG_TRACE, "windSpeed_plus", __FILENAME__); windSpeed += 0.1f; SET_WIND_SPEED(windSpeed); } if (windSpeed_minus) { + addlog(ige::LogType::LOG_TRACE, "windSpeed_minus", __FILENAME__); windSpeed -= 0.1f; SET_WIND_SPEED(windSpeed); } if (wavesHeight_plus) { + addlog(ige::LogType::LOG_TRACE, "wavesHeight_plus", __FILENAME__); wavesHeight += 0.1f; WATER::SET_DEEP_OCEAN_SCALER(wavesHeight); } if (wavesHeight_minus) { + addlog(ige::LogType::LOG_TRACE, "wavesHeight_minus", __FILENAME__); wavesHeight -= 0.1f; WATER::SET_DEEP_OCEAN_SCALER(wavesHeight); } if (rainfxi_plus) { + addlog(ige::LogType::LOG_TRACE, "rainfxit_plus", __FILENAME__); if (_globalRainFXIntensity < 45.0f) _globalRainFXIntensity += 0.1f; SET_RAIN(_globalRainFXIntensity); } if (rainfxi_minus) { + addlog(ige::LogType::LOG_TRACE, "rainfxit_minus", __FILENAME__); if (_globalRainFXIntensity > 0.0f) _globalRainFXIntensity -= 0.1f; SET_RAIN(_globalRainFXIntensity); } if (gravityLevel_plus) { + addlog(ige::LogType::LOG_TRACE, "gravityLevel_plus", __FILENAME__); auto git = v0gravities.find(mult_0_gravity); git++; if (git != v0gravities.end()) @@ -139,6 +147,7 @@ namespace sub } if (gravityLevel_minus) { + addlog(ige::LogType::LOG_TRACE, "gravityLevel_minus", __FILENAME__); auto git = std::map::reverse_iterator(v0gravities.find(mult_0_gravity)); git++; if (git != v0gravities.rend()) @@ -194,6 +203,7 @@ namespace sub bool bPressed = false; AddOption(name, bPressed); if (bPressed) { + addlog(ige::LogType::LOG_DEBUG, "Set Clouds: " + name, __FILENAME__); LOAD_CLOUD_HAT(name.c_str(), 0.5f); } } diff --git a/Solution/source/Util/FileLogger.cpp b/Solution/source/Util/FileLogger.cpp index 3fea8427..cc0b0abb 100644 --- a/Solution/source/Util/FileLogger.cpp +++ b/Solution/source/Util/FileLogger.cpp @@ -17,6 +17,115 @@ #include "../Natives/natives.h" #include "../Menu/Menu.h" #include "../Menu/MenuConfig.h" +#include "../Memory/GTAmemory.h" + +const char* VersionString(eGameVersion version) //this is fucking awful. Look into xMacros to do it better. +{ + static const char* versionStrings[] = { + "VER_1_0_335_2_STEAM", + "VER_1_0_335_2_NOSTEAM", + "VER_1_0_350_1_STEAM", + "VER_1_0_350_2_NOSTEAM", + "VER_1_0_372_2_STEAM", + "VER_1_0_372_2_NOSTEAM", + "VER_1_0_393_2_STEAM", + "VER_1_0_393_2_NOSTEAM", + "VER_1_0_393_4_STEAM", + "VER_1_0_393_4_NOSTEAM", + "VER_1_0_463_1_STEAM", + "VER_1_0_463_1_NOSTEAM", + "VER_1_0_505_2_STEAM", + "VER_1_0_505_2_NOSTEAM", + "VER_1_0_573_1_STEAM", + "VER_1_0_573_1_NOSTEAM", + "VER_1_0_617_1_STEAM", + "VER_1_0_617_1_NOSTEAM", + "VER_1_0_678_1_STEAM", + "VER_1_0_678_1_NOSTEAM", + "VER_1_0_757_2_STEAM", + "VER_1_0_757_2_NOSTEAM", + "VER_1_0_757_4_STEAM", + "VER_1_0_757_4_NOSTEAM", + "VER_1_0_791_2_STEAM", + "VER_1_0_791_2_NOSTEAM", + "VER_1_0_877_1_STEAM", + "VER_1_0_877_1_NOSTEAM", + "VER_1_0_944_2_STEAM", + "VER_1_0_944_2_NOSTEAM", + "VER_1_0_1011_1_STEAM", + "VER_1_0_1011_1_NOSTEAM", + "VER_1_0_1032_1_STEAM", + "VER_1_0_1032_1_NOSTEAM", + "VER_1_0_1103_2_STEAM", + "VER_1_0_1103_2_NOSTEAM", + "VER_1_0_1180_2_STEAM", + "VER_1_0_1180_2_NOSTEAM", + "VER_1_0_1290_1_STEAM", + "VER_1_0_1290_1_NOSTEAM", + "VER_1_0_1365_1_STEAM", + "VER_1_0_1365_1_NOSTEAM", + "VER_1_0_1493_0_STEAM", + "VER_1_0_1493_0_NOSTEAM", + "VER_1_0_1493_1_STEAM", + "VER_1_0_1493_1_NOSTEAM", + "VER_1_0_1604_0_STEAM", + "VER_1_0_1604_0_NOSTEAM", + "VER_1_0_1604_1_STEAM", + "VER_1_0_1604_1_NOSTEAM", + "VER_1_0_1737_0_STEAM", + "VER_1_0_1737_0_NOSTEAM", + "VER_1_0_1737_6_STEAM", + "VER_1_0_1737_6_NOSTEAM", + "VER_1_0_1868_0_STEAM", + "VER_1_0_1868_0_NOSTEAM", + "VER_1_0_1868_1_STEAM", + "VER_1_0_1868_1_NOSTEAM", + "VER_1_0_1868_4_EGS", + "VER_1_0_2060_0_STEAM", + "VER_1_0_2060_0_NOSTEAM", + "VER_1_0_2060_1_STEAM", + "VER_1_0_2060_1_NOSTEAM", + "VER_1_0_2189_0_STEAM", + "VER_1_0_2189_0_NOSTEAM", + "VER_1_0_2215_0_STEAM", + "VER_1_0_2215_0_NOSTEAM", + "VER_1_0_2245_0_STEAM", + "VER_1_0_2245_0_NOSTEAM", + "VER_1_0_2372_0_STEAM", + "VER_1_0_2372_0_NOSTEAM", + "VER_1_0_2545_0_STEAM", + "VER_1_0_2545_0_NOSTEAM", + "VER_1_0_2612_1_STEAM", + "VER_1_0_2612_1_NOSTEAM", + "VER_1_0_2628_2_STEAM", + "VER_1_0_2628_2_NOSTEAM", + "VER_1_0_2699_0_STEAM", + "VER_1_0_2699_0_NOSTEAM", + "VER_1_0_2699_16", + "VER_1_0_2802_0", + "VER_1_0_2824_0", + "VER_1_0_2845_0", + "VER_1_0_2944_0", + "VER_1_0_3028_0", + "VER_1_0_3095_0", + "VER_1_0_3179_0", + "VER_1_0_3258_0", + "VER_1_0_3274_0", + "VER_1_0_3323_0", + "VER_1_0_3337_0", + "VER_1_0_3351_0", + "VER_1_0_3407_0", + "VER_1_0_3411_0", + "VER_1_0_3442_0", + "VER_1_0_812_8" + }; + + int idx = static_cast(version); + if (idx >= 0 && idx < static_cast(eGameVersion::VER_SIZE)) + return versionStrings[idx]; + + return "Unknown"; +} namespace ige { @@ -25,7 +134,6 @@ namespace ige FileLogger::FileLogger(std::string fname) { - MenuConfig::ConfigInit(); myFile.open(fname.c_str()); if (myFile.is_open()) @@ -35,9 +143,9 @@ namespace ige localtime_s(&t, &now); myFile << "Menyoo " << MENYOO_CURRENT_VER_ << std::endl; + myFile << "Gameversion " << std::to_string(GTAmemory::GetGameVersion()) << std::endl; //myFile << "Player Name: " << PLAYER::GET_PLAYER_NAME(-1) << std::endl; myFile << "Log file created " << std::setfill('0') << std::setw(2) << t.tm_mday << "/" << std::setfill('0') << std::setw(2) << (t.tm_mon + 1) << "/" << t.tm_year + 1900 << std::endl; - myFile << "Logging level " << std::to_string(g_loglevel) << " active. Edit loglevel in menyooconfig.ini to change." << std::endl << std::endl; } } diff --git a/Solution/source/Util/FileLogger.h b/Solution/source/Util/FileLogger.h index 296d77e1..28dd9ebc 100644 --- a/Solution/source/Util/FileLogger.h +++ b/Solution/source/Util/FileLogger.h @@ -11,6 +11,7 @@ #include #include "../Menu/Menu.h" +#include "../Memory/GTAmemory.h" #define __FILENAME__ strrchr("\\" __FILE__, '\\') + 1 @@ -38,6 +39,7 @@ namespace ige extern FileLogger menyooLogObject; extern std::ofstream& myLog; + const char* VersionString(eGameVersion version); extern void addlog(LogType logType, std::string message, std::string filename, int loglevel = g_loglevel); inline void addlog(LogType logType, std::string message) { addlog(logType, message, __FILENAME__, g_loglevel); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index f34e5da5..cd73693f 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,8 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS - -#define MENYOO_CURRENT_VER_ "2.2.0a1" +#define MENYOO_CURRENT_VER_ "2.2.0a2" #define GAME_PLAYERCOUNT 30 diff --git a/Solution/source/main.cpp b/Solution/source/main.cpp index d08fe42f..3fac3612 100644 --- a/Solution/source/main.cpp +++ b/Solution/source/main.cpp @@ -23,16 +23,31 @@ THIS FILE IS A PART OF GTA V SCRIPT HOOK SDK #include #include +#include + BOOL APIENTRY DllMain(HMODULE hInstance, DWORD reason, LPVOID lpReserved) { switch (reason) { case DLL_PROCESS_ATTACH: + { //g_MainModule = hInstance; g_MainModule = GetModuleHandle(NULL); + MenuConfig::ConfigInit(); + + g_isEnhanced = [] { + char path[MAX_PATH]; + GetModuleFileNameA(GetModuleHandleA(nullptr), path, MAX_PATH); + + const char* filename = strrchr(path, '\\'); + filename = filename ? filename + 1 : path; + return (_stricmp(filename, "GTA5_Enhanced.exe") == 0); + }(); + + std::string gameName = g_isEnhanced ? "GTA5_Enhanced" : "GTA5"; if (!GetModuleInformation(GetCurrentProcess(), g_MainModule, &g_MainModuleInfo, sizeof(g_MainModuleInfo))) - addlog(ige::LogType::LOG_INIT, "Unable to get MODULEINFO from GTA5.exe", __FILENAME__); + addlog(ige::LogType::LOG_ERROR, "Unable to get MODULEINFO from " + gameName + ".exe", __FILENAME__); else { std::ostringstream moduleinfostream; @@ -40,23 +55,28 @@ BOOL APIENTRY DllMain(HMODULE hInstance, DWORD reason, LPVOID lpReserved) << ", SizeOfImage=" << g_MainModuleInfo.SizeOfImage << ", EntryPoint=" << g_MainModuleInfo.EntryPoint; - addlog(ige::LogType::LOG_INIT, moduleinfostream.str(), __FILENAME__); + addlog(ige::LogType::LOG_INFO, moduleinfostream.str(), __FILENAME__); } - + addlog(ige::LogType::LOG_TRACE, "Attempting to Setup Hooks", __FILENAME__); setupHooks(); + addlog(ige::LogType::LOG_TRACE, "Initialising GTAmemory", __FILENAME__); GTAmemory::Init(); + addlog(ige::LogType::LOG_TRACE, "Registering Script ThreadMenyooMain", __FILENAME__); scriptRegister(hInstance, ThreadMenyooMain); + addlog(ige::LogType::LOG_TRACE, "Registering Script Thread_menu_loops2", __FILENAME__); scriptRegisterAdditionalThread(hInstance, Thread_menu_loops2); + addlog(ige::LogType::LOG_TRACE, "Registering Keyboard Handler", __FILENAME__); keyboardHandlerRegister(OnKeyboardMessage); + addlog(ige::LogType::LOG_TRACE, "Finished Registering scripts", __FILENAME__); break; - + } case DLL_PROCESS_DETACH: scriptUnregister(hInstance); keyboardHandlerUnregister(OnKeyboardMessage); - + break; } return TRUE; diff --git a/Solution/source/main.h b/Solution/source/main.h index b6c39f39..42ea83d3 100644 --- a/Solution/source/main.h +++ b/Solution/source/main.h @@ -290,6 +290,20 @@ enum eGameVersion : int VER_1_0_3521_0, VER_1_0_3570_0, + + VER_1_0_3586_0, + + VER_1_0_811_8 = 1001, + + VER_1_0_812_8 = 1002, + + VER_1_0_813_11 = 1003, + + VER_1_0_814_9 = 1004, + + VER_1_0_889_15 = 1005, + + VER_1_0_889_19 = 1006, VER_SIZE, VER_UNK = -1 From 3c1e49ef146b00fdc08f6756095dbc83c82ea054 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:50:58 +0400 Subject: [PATCH 13/49] Enhanced (#356) Add logging points for legacy compatibility --- Solution/source/Memory/GTAmemory.cpp | 11 +++++++++-- Solution/source/Scripting/ModelNames.cpp | 6 ++++++ Solution/source/macros.h | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index 1c9afab1..21219b15 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -1734,6 +1734,7 @@ void GTAmemory::InitEnhancedPools() { } + Vector3 GTAmemory::ReadVector3(UINT64 address) { const float* data = (float*)address; @@ -1756,14 +1757,16 @@ struct HashNode }; void GTAmemory::GenerateVehicleModelList() { - + addlog(ige::LogType::LOG_DEBUG, "Generating Vehicle Model List. isEnhanced = " + g_isEnhanced, __FILENAME__); int classOffset; uintptr_t address; HashNode** HashMap; if (g_isEnhanced) { + addlog(ige::LogType::LOG_TRACE, "Scanning Enhanced Address", __FILENAME__); address = MemryScan::PatternScanner::FindPattern("0f b6 88 ? ? ? ? 83 e1 ? e9"); if (address) { + addlog(ige::LogType::LOG_TRACE, "Found Address, scanning for Hashes", __FILENAME__); classOffset = *(uint*)(address + 3); address = MemryScan::PatternScanner::FindPattern("74 ? 49 89 d0 4c 8b 1d"); @@ -1781,8 +1784,10 @@ void GTAmemory::GenerateVehicleModelList() } } else { + addlog(ige::LogType::LOG_TRACE, "Scanning Legacy Address", __FILENAME__); address = FindPattern("\x66\x81\xF9\x00\x00\x74\x10\x4D\x85\xC0", "xxx??xxxxx"); if (address) { + addlog(ige::LogType::LOG_TRACE, "Found Address, scanning for Hashes", __FILENAME__); address = address - 0x21; //UINT64 baseFuncAddr = *reinterpret_cast(address - 0x21) + address - 0x1D; UINT64 baseFuncAddr = address + *reinterpret_cast(address) + 0x4; @@ -1802,6 +1807,7 @@ void GTAmemory::GenerateVehicleModelList() if (address) { + addlog(ige::LogType::LOG_TRACE, "Patterns Scanned Success", __FILENAME__); HashMap = reinterpret_cast(modelHashTable); //I know 0x20 items are defined but there are only 0x16 vehicle classes. //But keeping it at 0x20 is just being safe as the & 0x1F in theory supports up to 0x20 @@ -1831,6 +1837,7 @@ void GTAmemory::GenerateVehicleModelList() } } } + addlog(ige::LogType::LOG_TRACE, "Exiting GenerateVehicleModelList()", __FILENAME__); } bool GTAmemory::IsModelAPed(unsigned int modelHash) @@ -2951,4 +2958,4 @@ std::string GTAmemory::GetVehicleMakeName(Hash modelHash) { return ((CVehicleModelInfo*)modelInfo)->m_manufacturerName; } return ((CVehicleModelInfo1290*)modelInfo)->m_manufacturerName; -} \ No newline at end of file +} diff --git a/Solution/source/Scripting/ModelNames.cpp b/Solution/source/Scripting/ModelNames.cpp index c132a860..77932d18 100644 --- a/Solution/source/Scripting/ModelNames.cpp +++ b/Solution/source/Scripting/ModelNames.cpp @@ -26,6 +26,7 @@ #include #include #include // std::sort, VS 2019 update 16.7.1 +#include "../Util/FileLogger.h" #pragma region Vehicle model labels std::vector g_vehHashes; @@ -188,6 +189,7 @@ void PopulateVehicleModelsArray() g_vehHashes_OTHER.clear(); g_vehHashes_DRIFT.clear(); + addlog(ige::LogType::LOG_TRACE, "Call GenerateVehicleModelList()", __FILENAME__); GTAmemory::GenerateVehicleModelList(); auto& hashes = GTAmemory::VehicleModels(); std::unordered_map*> vDestMap @@ -287,9 +289,13 @@ void PopulateObjectModelsArray() } void PopulateGlobalEntityModelsArrays() { + addlog(ige::LogType::LOG_TRACE, "Call PopulatePedModelsArray()", __FILENAME__); PopulatePedModelsArray(); + addlog(ige::LogType::LOG_TRACE, "Call PopulateVehicleModelsArray()", __FILENAME__); PopulateVehicleModelsArray(); + addlog(ige::LogType::LOG_TRACE, "Call PopulateObjectModelsArray()", __FILENAME__); PopulateObjectModelsArray(); + addlog(ige::LogType::LOG_TRACE, "Exit PopulateGlobalEntityModelsArrays()", __FILENAME__); } // Model - labels diff --git a/Solution/source/macros.h b/Solution/source/macros.h index cd73693f..48f36f6b 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a2" +#define MENYOO_CURRENT_VER_ "2.2.0a3" #define GAME_PLAYERCOUNT 30 From 0c260a42261860dfe486a21c8b37cb5070eeb170 Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Thu, 30 Oct 2025 19:03:15 +0400 Subject: [PATCH 14/49] Add Enhanced filter to Chameleon Paint option --- Solution/source/Submenus/VehicleModShop.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/Submenus/VehicleModShop.cpp b/Solution/source/Submenus/VehicleModShop.cpp index 2fdeb5be..6cb36ab1 100644 --- a/Solution/source/Submenus/VehicleModShop.cpp +++ b/Solution/source/Submenus/VehicleModShop.cpp @@ -825,7 +825,7 @@ namespace sub AddOption("Matte", null, nullFunc, SUB::MSPAINTS2_MATTE, true, true); // CMOD_COL1_5 AddOption("Metallic", null, nullFunc, SUB::MSPAINTS2_METALLIC, true, true); // CMOD_COL1_3 AddOption("Metal", null, nullFunc, SUB::MSPAINTS2_METAL, true, true); // CMOD_COL1_4 - if(IS_DLC_PRESENT(GET_HASH_KEY("spchameleon"))) + if(g_isEnhanced||IS_DLC_PRESENT(GET_HASH_KEY("spchameleon"))) AddOption("Chameleon", null, nullFunc, SUB::MSPAINTS2_CHAMELEON, true, true); // CMOD_COL1_4 AddOption("Utility", null, nullFunc, SUB::MSPAINTS2_UTIL); AddOption("Worn", null, nullFunc, SUB::MSPAINTS2_WORN); From 740760a7fefb19bd99da6f1056fc37e920121aad Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:38:00 +0400 Subject: [PATCH 15/49] Remove condition for setting output in workflow --- .github/workflows/master_build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 207a24a9..6ab93c16 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -108,7 +108,6 @@ jobs: - name: Set output id: set_output - if: env.CANCELJOB != 'true' run: echo "CANCELJOB=${{ env.CANCELJOB }}" >> $GITHUB_OUTPUT build: From bbec40738cfcce49b59766c9114284eca9276065 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 30 Oct 2025 19:45:59 +0400 Subject: [PATCH 16/49] Update master_build.yml Add conditional check for pre-release job Remove condition for build --- .github/workflows/master_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 6ab93c16..8ea6881e 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -111,7 +111,6 @@ jobs: run: echo "CANCELJOB=${{ env.CANCELJOB }}" >> $GITHUB_OUTPUT build: - if: github.ref == 'refs/heads/main' || (github.ref == 'refs/heads/Development' && needs.check-version-and-merge.outputs.CANCELJOB != 'true') runs-on: windows-latest needs: check-version-and-merge @@ -151,6 +150,7 @@ jobs: pre-release: + if: github.ref == 'refs/heads/main' || (github.ref == 'refs/heads/Development' && needs.check-version-and-merge.outputs.CANCELJOB != 'true') needs: build permissions: write-all name: "Pre Release" From 9bf55045eb58b656cafd8b0c6e87ad9654f44027 Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Sun, 2 Nov 2025 15:39:36 +0400 Subject: [PATCH 17/49] Fix Legacy Vehicle list issue --- Solution/source/Memory/GTAmemory.cpp | 58 +++++++++++------------- Solution/source/Menu/Menu.cpp | 5 +- Solution/source/Menu/Routine.cpp | 11 ++--- Solution/source/Scripting/ModelNames.cpp | 49 ++++++++++++++++++-- 4 files changed, 79 insertions(+), 44 deletions(-) diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index 21219b15..a201cba6 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -1726,11 +1726,11 @@ void GTAmemory::InitEnhancedPools() { } address = address - 0x2C; addlog(ige::LogType::LOG_TRACE, "Found Pattern: " + std::to_string(address), __FILENAME__); - - GetModelInfo = (GetModelInfo_t)(address); - - _SpSnow = SpSnow(); -} + + GetModelInfo = (GetModelInfo_t)(address); + + _SpSnow = SpSnow(); + } } @@ -1757,10 +1757,12 @@ struct HashNode }; void GTAmemory::GenerateVehicleModelList() { - addlog(ige::LogType::LOG_DEBUG, "Generating Vehicle Model List. isEnhanced = " + g_isEnhanced, __FILENAME__); + addlog(ige::LogType::LOG_DEBUG, "Generating Vehicle Model List. isEnhanced = " + std::to_string(g_isEnhanced), __FILENAME__); + int classOffset; uintptr_t address; HashNode** HashMap; + //Zorg if (g_isEnhanced) { addlog(ige::LogType::LOG_TRACE, "Scanning Enhanced Address", __FILENAME__); address = MemryScan::PatternScanner::FindPattern("0f b6 88 ? ? ? ? 83 e1 ? e9"); @@ -1784,7 +1786,6 @@ void GTAmemory::GenerateVehicleModelList() } } else { - addlog(ige::LogType::LOG_TRACE, "Scanning Legacy Address", __FILENAME__); address = FindPattern("\x66\x81\xF9\x00\x00\x74\x10\x4D\x85\xC0", "xxx??xxxxx"); if (address) { addlog(ige::LogType::LOG_TRACE, "Found Address, scanning for Hashes", __FILENAME__); @@ -1792,7 +1793,7 @@ void GTAmemory::GenerateVehicleModelList() //UINT64 baseFuncAddr = *reinterpret_cast(address - 0x21) + address - 0x1D; UINT64 baseFuncAddr = address + *reinterpret_cast(address) + 0x4; //int classOffset = *reinterpret_cast(address + 0x10); - int classOffset = *reinterpret_cast(address + 0x31); + classOffset = *reinterpret_cast(address + 0x31); modelHashEntries = *reinterpret_cast(baseFuncAddr + *reinterpret_cast(baseFuncAddr + 3) + 7); modelNum1 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x52) + baseFuncAddr + 0x56); //cmp modelNum2 = *reinterpret_cast(*reinterpret_cast(baseFuncAddr + 0x63) + baseFuncAddr + 0x67); //mov @@ -1803,34 +1804,29 @@ void GTAmemory::GenerateVehicleModelList() } } - //Zorg - - if (address) + addlog(ige::LogType::LOG_TRACE, "Patterns Scanned Success", __FILENAME__); + HashMap = reinterpret_cast(modelHashTable); + //I know 0x20 items are defined but there are only 0x16 vehicle classes. + //But keeping it at 0x20 is just being safe as the & 0x1F in theory supports up to 0x20 + auto& vehicleHashes = GTAmemory::vehicleModels; + for (auto& vec : vehicleHashes) + vec.clear(); + for (int i = 0; i < modelHashEntries; i++) { - addlog(ige::LogType::LOG_TRACE, "Patterns Scanned Success", __FILENAME__); - HashMap = reinterpret_cast(modelHashTable); - //I know 0x20 items are defined but there are only 0x16 vehicle classes. - //But keeping it at 0x20 is just being safe as the & 0x1F in theory supports up to 0x20 - auto& vehicleHashes = GTAmemory::vehicleModels; - for (auto& vec : vehicleHashes) - vec.clear(); - for (int i = 0; i < modelHashEntries; i++) + for (HashNode* cur = HashMap[i]; cur; cur = cur->next) { - for (HashNode* cur = HashMap[i]; cur; cur = cur->next) + UINT16 data = cur->data; + if ((int)data < modelNum1 && bittest(*reinterpret_cast(modelNum2 + (4 * data >> 5)), data & 0x1F)) { - UINT16 data = cur->data; - if ((int)data < modelNum1 && bittest(*reinterpret_cast(modelNum2 + (4 * data >> 5)), data & 0x1F)) + UINT64 addr1 = modelNum4 + modelNum3 * data; + if (addr1) { - UINT64 addr1 = modelNum4 + modelNum3 * data; - if (addr1) + UINT64 addr2 = *reinterpret_cast(addr1); + if (addr2) { - UINT64 addr2 = *reinterpret_cast(addr1); - if (addr2) + if ((*reinterpret_cast(addr2 + 157) & 0x1F) == 5) // Vehicle { - if ((*reinterpret_cast(addr2 + 157) & 0x1F) == 5) // Vehicle - { - vehicleHashes[*reinterpret_cast(addr2 + classOffset) & 0x1F].push_back((unsigned int)cur->hash); - } + vehicleHashes[*reinterpret_cast(addr2 + classOffset) & 0x1F].push_back((unsigned int)cur->hash); } } } @@ -2958,4 +2954,4 @@ std::string GTAmemory::GetVehicleMakeName(Hash modelHash) { return ((CVehicleModelInfo*)modelInfo)->m_manufacturerName; } return ((CVehicleModelInfo1290*)modelInfo)->m_manufacturerName; -} +} \ No newline at end of file diff --git a/Solution/source/Menu/Menu.cpp b/Solution/source/Menu/Menu.cpp index ae1a0921..e5a300c9 100644 --- a/Solution/source/Menu/Menu.cpp +++ b/Solution/source/Menu/Menu.cpp @@ -528,9 +528,10 @@ void Menu::while_closed() { addlog(ige::LogType::LOG_TRACE, "Binds Pressed, opening Menyoo", __FILENAME__); - if (g_menuNotOpenedYet) + if (g_menuNotOpenedYet) { justopened(); - GTAmemory::InitEnhancedPools(); + GTAmemory::InitEnhancedPools(); + } Game::Sound::PlayFrontend("FocusIn", "HintCamSounds"); diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index aacca314..8665cc88 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -423,13 +423,10 @@ void update_nearby_stuff_arrays_tick() _worldObjects.clear(); _worldEntities.clear(); //bool alreadyIn; - if(false) - { - GTAmemory::GetVehicleHandles(_worldVehicles); - GTAmemory::GetPedHandles(_worldPeds); - GTAmemory::GetPropHandles(_worldObjects); - GTAmemory::GetEntityHandles(_worldEntities); - } + GTAmemory::GetVehicleHandles(_worldVehicles); + GTAmemory::GetPedHandles(_worldPeds); + GTAmemory::GetPropHandles(_worldObjects); + GTAmemory::GetEntityHandles(_worldEntities); /*INT i, offsettedID, count = 80; Ped *peds = new Ped[count * 2 + 2]; diff --git a/Solution/source/Scripting/ModelNames.cpp b/Solution/source/Scripting/ModelNames.cpp index 77932d18..5b6b6501 100644 --- a/Solution/source/Scripting/ModelNames.cpp +++ b/Solution/source/Scripting/ModelNames.cpp @@ -160,6 +160,38 @@ void PopulatePedModelsArray() std::sort(hlist->begin(), hlist->end(), [](const std::pair& a, const std::pair& b) -> bool { return boost::to_lower_copy(a.second) < boost::to_lower_copy(b.second); }); } } + +std::string getVehicleClassName(VehicleClass vclass) +{ + switch (vclass) + { + case VehicleClass::Openwheel: return "Openwheel"; + case VehicleClass::Super: return "Super"; + case VehicleClass::Sport: return "Sport"; + case VehicleClass::SportsClassic: return "SportsClassic"; + case VehicleClass::Coupe: return "Coupe"; + case VehicleClass::Muscle: return "Muscle"; + case VehicleClass::Offroad: return "Offroad"; + case VehicleClass::SUV: return "SUV"; + case VehicleClass::Sedan: return "Sedan"; + case VehicleClass::Compact: return "Compact"; + case VehicleClass::Van: return "Van"; + case VehicleClass::Service: return "Service"; + case VehicleClass::Train: return "Train"; + case VehicleClass::Emergency: return "Emergency"; + case VehicleClass::Motorcycle: return "Motorcycle"; + case VehicleClass::Cycle: return "Bicycle"; + case VehicleClass::Plane: return "Plane"; + case VehicleClass::Helicopter: return "Helicopter"; + case VehicleClass::Boat: return "Boat"; + case VehicleClass::Industrial: return "Industrial"; + case VehicleClass::Commercial: return "Commercial"; + case VehicleClass::Utility: return "Utility"; + case VehicleClass::Military: return "Military"; + default: return "Other"; + } +} + void PopulateVehicleModelsArray() { g_vehHashes.clear(); @@ -202,27 +234,36 @@ void PopulateVehicleModelsArray() { VehicleClass::Train, &g_vehHashes_TRAIN },{ VehicleClass::Emergency, &g_vehHashes_EMERGENCY },{ VehicleClass::Motorcycle, &g_vehHashes_MOTORCYCLE }, { VehicleClass::Cycle, &g_vehHashes_BICYCLE },{ VehicleClass::Plane, &g_vehHashes_PLANE },{ VehicleClass::Helicopter, &g_vehHashes_HELICOPTER },{ VehicleClass::Boat, &g_vehHashes_BOAT } }; - + const bool isMinGameVersion3095 = GTAmemory::GetGameVersion() >= eGameVersion::VER_1_0_3095_0; - bool tmpEnhanced = GTAmemory::GetIsEnhanced(); for (int d = 0x0; d < 0x20; d++) { for (auto& dd : hashes[d]) { + addlog(ige::LogType::LOG_TRACE, "Read vehicle model: " + Model(dd).VehicleModelName(), __FILENAME__); if (std::find(g_vehHashes.begin(), g_vehHashes.end(), Model(dd)) == g_vehHashes.end()) { - if (tmpEnhanced || !isMinGameVersion3095 || !IS_VEHICLE_GEN9_EXCLUSIVE_MODEL(dd)) + if (g_isEnhanced || !isMinGameVersion3095 || !IS_VEHICLE_GEN9_EXCLUSIVE_MODEL(dd)) { if (Model(dd).VehicleModelName().starts_with("drift")) { + addlog(ige::LogType::LOG_TRACE, " - Add to Vehicle Class Drift", __FILENAME__); g_vehHashes_DRIFT.push_back(dd); } else { + if (g_loglevel == 4) + { + std::string vclassName = getVehicleClassName(VehicleClass(d)); + addlog(ige::LogType::LOG_TRACE, " - Add to Vehicle Class " + vclassName, __FILENAME__); + } auto dit = vDestMap.find(VehicleClass(d)); if (dit != vDestMap.end()) dit->second->push_back(dd); - else g_vehHashes_OTHER.push_back(dd); + else + { + g_vehHashes_OTHER.push_back(dd); + } } g_vehHashes.push_back(dd); } From 8c740aea97ff1695151d8d20cd92989fd9eb4734 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sun, 2 Nov 2025 15:40:27 +0400 Subject: [PATCH 18/49] Update MENYOO_CURRENT_VER_ to version 2.2.0a4 --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 48f36f6b..2255507b 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a3" +#define MENYOO_CURRENT_VER_ "2.2.0a4" #define GAME_PLAYERCOUNT 30 From 6aa5bfc5ac086785a533bdae93f7f90c8f688b1f Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Sun, 2 Nov 2025 18:51:48 +0400 Subject: [PATCH 19/49] Additional Trace Logs --- Solution/source/Memory/GTAmemory.cpp | 18 +++++++++++------- Solution/source/Scripting/ModelNames.cpp | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index a201cba6..aab7739c 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -53,10 +53,11 @@ typedef CVehicleModelInfo* (*InitVehicleArchetypeEnhanced_t)(uint32_t, const cha GetModelInfo_t GetModelInfo; std::unordered_map g_vehicleHashes; -CallHook* g_InitVehicleArchetypeLegacy = nullptr; +CallHook* g_InitVehicleArchetype = nullptr; CVehicleModelInfo* initVehicleArchetype_stub(const char* name, bool a2, unsigned int a3) { + addlog(ige::LogType::LOG_DEBUG, "getting hashkey for " + std::string(name), __FILENAME__); g_vehicleHashes.insert({ GET_HASH_KEY(name), boost::to_lower_copy(name) }); - return g_InitVehicleArchetypeLegacy->fn(name, a2, a3); + return g_InitVehicleArchetype->fn(name, a2, a3); } // InitVehicleArchetype has been inlined in Enhanced, instead we hook one of functions which are called after it and take its first parameter. @@ -74,7 +75,7 @@ void setupHooks() { addlog(ige::LogType::LOG_ERROR, "Couldn't find InitVehicleArchetypeEnahnced", __FILENAME__); return; } - addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at " + std::to_string(addr), __FILENAME__); + addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetypeEnhanced at " + std::to_string(addr), __FILENAME__); g_InitVehicleArchetypeEnhanced = HookManager::SetCall(addr, initVehicleArchetypeEnhanced_stub); } else { @@ -84,14 +85,14 @@ void setupHooks() { return; } addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at " + std::to_string(addr), __FILENAME__); - g_InitVehicleArchetypeLegacy = HookManager::SetCall(addr, initVehicleArchetype_stub); + g_InitVehicleArchetype = HookManager::SetCall(addr, initVehicleArchetype_stub); } } void removeHooks() { - if (g_InitVehicleArchetypeLegacy) { - delete g_InitVehicleArchetypeLegacy; - g_InitVehicleArchetypeLegacy = nullptr; + if (g_InitVehicleArchetype) { + delete g_InitVehicleArchetype; + g_InitVehicleArchetype = nullptr; } if (g_InitVehicleArchetypeEnhanced) { delete g_InitVehicleArchetypeEnhanced; @@ -2941,6 +2942,9 @@ float* GeneralGlobalHax::GetVehicleBoostChargePtr() } std::string GTAmemory::GetVehicleModelName(Hash hash) { + if(g_vehicleHashes.empty()) { + addlog(ige::LogType::LOG_ERROR, "g_vehicleHashes Empty", __FILENAME__); + } auto modelIt = g_vehicleHashes.find(hash); if (modelIt != g_vehicleHashes.end()) return modelIt->second; return "NOTFOUND"; diff --git a/Solution/source/Scripting/ModelNames.cpp b/Solution/source/Scripting/ModelNames.cpp index 5b6b6501..5cf68e15 100644 --- a/Solution/source/Scripting/ModelNames.cpp +++ b/Solution/source/Scripting/ModelNames.cpp @@ -240,7 +240,7 @@ void PopulateVehicleModelsArray() { for (auto& dd : hashes[d]) { - addlog(ige::LogType::LOG_TRACE, "Read vehicle model: " + Model(dd).VehicleModelName(), __FILENAME__); + addlog(ige::LogType::LOG_TRACE, "Read vehicle model: " + std::to_string(Model(dd).hash) + " - " + Model(dd).VehicleModelName(), __FILENAME__); if (std::find(g_vehHashes.begin(), g_vehHashes.end(), Model(dd)) == g_vehHashes.end()) { if (g_isEnhanced || !isMinGameVersion3095 || !IS_VEHICLE_GEN9_EXCLUSIVE_MODEL(dd)) From f3f1ef3b91b8d6b5de9dce000d9d704acf120ef3 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 4 Nov 2025 22:16:30 +0400 Subject: [PATCH 20/49] Wheels fix (#364) * Additional Trace Logs * Add more verbose logging Fix #198 --- Solution/source/Memory/GTAmemory.cpp | 18 +++-- Solution/source/Menu/Menu.cpp | 14 +++- Solution/source/Scripting/Game.cpp | 11 +-- Solution/source/Scripting/Game.h | 4 +- Solution/source/Scripting/ModelNames.cpp | 2 +- Solution/source/Submenus/MiscOptions.cpp | 2 +- Solution/source/Submenus/PedAnimation.cpp | 4 +- .../source/Submenus/PedComponentChanger.cpp | 10 +-- Solution/source/Submenus/PedModelChanger.cpp | 8 +-- Solution/source/Submenus/PlayerOptions.cpp | 2 +- Solution/source/Submenus/Settings.cpp | 6 +- .../Submenus/Spooner/EntityManagement.cpp | 6 +- Solution/source/Submenus/Spooner/Submenus.cpp | 20 +++--- .../Spooner/Submenus_TaskSequence.cpp | 16 ++--- Solution/source/Submenus/StatManager.cpp | 4 +- .../Submenus/Teleport/Teleport_Submenus.cpp | 2 +- Solution/source/Submenus/VehicleModShop.cpp | 67 +++++++++++-------- Solution/source/Submenus/VehicleOptions.cpp | 2 +- Solution/source/Submenus/VehicleSpawner.cpp | 16 ++--- Solution/source/Submenus/WeaponOptions.cpp | 24 +++---- Solution/source/macros.h | 2 +- 21 files changed, 134 insertions(+), 106 deletions(-) diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index a201cba6..aab7739c 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -53,10 +53,11 @@ typedef CVehicleModelInfo* (*InitVehicleArchetypeEnhanced_t)(uint32_t, const cha GetModelInfo_t GetModelInfo; std::unordered_map g_vehicleHashes; -CallHook* g_InitVehicleArchetypeLegacy = nullptr; +CallHook* g_InitVehicleArchetype = nullptr; CVehicleModelInfo* initVehicleArchetype_stub(const char* name, bool a2, unsigned int a3) { + addlog(ige::LogType::LOG_DEBUG, "getting hashkey for " + std::string(name), __FILENAME__); g_vehicleHashes.insert({ GET_HASH_KEY(name), boost::to_lower_copy(name) }); - return g_InitVehicleArchetypeLegacy->fn(name, a2, a3); + return g_InitVehicleArchetype->fn(name, a2, a3); } // InitVehicleArchetype has been inlined in Enhanced, instead we hook one of functions which are called after it and take its first parameter. @@ -74,7 +75,7 @@ void setupHooks() { addlog(ige::LogType::LOG_ERROR, "Couldn't find InitVehicleArchetypeEnahnced", __FILENAME__); return; } - addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at " + std::to_string(addr), __FILENAME__); + addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetypeEnhanced at " + std::to_string(addr), __FILENAME__); g_InitVehicleArchetypeEnhanced = HookManager::SetCall(addr, initVehicleArchetypeEnhanced_stub); } else { @@ -84,14 +85,14 @@ void setupHooks() { return; } addlog(ige::LogType::LOG_INFO, "Found InitVehicleArchetype at " + std::to_string(addr), __FILENAME__); - g_InitVehicleArchetypeLegacy = HookManager::SetCall(addr, initVehicleArchetype_stub); + g_InitVehicleArchetype = HookManager::SetCall(addr, initVehicleArchetype_stub); } } void removeHooks() { - if (g_InitVehicleArchetypeLegacy) { - delete g_InitVehicleArchetypeLegacy; - g_InitVehicleArchetypeLegacy = nullptr; + if (g_InitVehicleArchetype) { + delete g_InitVehicleArchetype; + g_InitVehicleArchetype = nullptr; } if (g_InitVehicleArchetypeEnhanced) { delete g_InitVehicleArchetypeEnhanced; @@ -2941,6 +2942,9 @@ float* GeneralGlobalHax::GetVehicleBoostChargePtr() } std::string GTAmemory::GetVehicleModelName(Hash hash) { + if(g_vehicleHashes.empty()) { + addlog(ige::LogType::LOG_ERROR, "g_vehicleHashes Empty", __FILENAME__); + } auto modelIt = g_vehicleHashes.find(hash); if (modelIt != g_vehicleHashes.end()) return modelIt->second; return "NOTFOUND"; diff --git a/Solution/source/Menu/Menu.cpp b/Solution/source/Menu/Menu.cpp index e5a300c9..ce5c128e 100644 --- a/Solution/source/Menu/Menu.cpp +++ b/Solution/source/Menu/Menu.cpp @@ -860,20 +860,28 @@ void Menu::draw_IB() void Menu::sub_handler() { - static bool firstRun = true; + static bool firstRun = true, isClosed = true; if(firstRun) { addlog(ige::LogType::LOG_TRACE, "First Run sub_handler", __FILENAME__);; } if (currentsub == SUB::CLOSED) { - if (firstRun) addlog(ige::LogType::LOG_TRACE, "Sub Currently Closed", __FILENAME__);; + if (!isClosed) + { + addlog(ige::LogType::LOG_TRACE, "Sub Closed", __FILENAME__);; + isClosed = true; + } while_closed(); } else { - if (firstRun) addlog(ige::LogType::LOG_TRACE, "Sub Currently Open", __FILENAME__);; + if (isClosed) + { + addlog(ige::LogType::LOG_TRACE, "Sub Opened", __FILENAME__);; + isClosed = false; + } submenu_switch(); if (Menu::currentop > Menu::printingop) { Menu::currentop = Menu::printingop + 1; Menu::Up(false); } diff --git a/Solution/source/Scripting/Game.cpp b/Solution/source/Scripting/Game.cpp index 32c25b7e..c11a9bc3 100644 --- a/Solution/source/Scripting/Game.cpp +++ b/Solution/source/Scripting/Game.cpp @@ -23,6 +23,7 @@ #include #include #include +#include "../Util/FileLogger.h" std::ostream& operator<<(std::ostream& stream, std::wstring& text) { @@ -398,13 +399,15 @@ namespace Game } // Messages - Errors - void PrintError_InvalidInput() + void PrintError_InvalidInput(std::string inputStr) { - Game::Print::PrintBottomCentre("~r~Error:~s~ Invalid Input."); + Game::Print::PrintBottomCentre("~r~Error:~s~ Invalid Input: " + inputStr); + addlog(ige::LogType::LOG_ERROR, "Invalid Input: " + inputStr, __FILENAME__); } - void PrintError_InvalidModel() + void PrintError_InvalidModel(std::string inputStr) { - Game::Print::PrintBottomCentre("~r~Error:~s~ Invalid Model."); + Game::Print::PrintBottomCentre("~r~Error:~s~ Invalid Model: " + inputStr); + addlog(ige::LogType::LOG_ERROR, "Invalid Model: " + inputStr, __FILENAME__); } // Text width diff --git a/Solution/source/Scripting/Game.h b/Solution/source/Scripting/Game.h index d21580ee..fb78ffb0 100644 --- a/Solution/source/Scripting/Game.h +++ b/Solution/source/Scripting/Game.h @@ -115,8 +115,8 @@ namespace Game Notification PrintBottomLeft(std::wostream& s, const std::string& sender, const std::string& subject, const std::string& picName, int iconType, bool flash, bool gxt); // Messages - Errors - void PrintError_InvalidInput(); - void PrintError_InvalidModel(); + void PrintError_InvalidInput(std::string inputStr); + void PrintError_InvalidModel(std::string inputStr); // Text width float GetTextWidth(const std::string& s, bool gxt = false); diff --git a/Solution/source/Scripting/ModelNames.cpp b/Solution/source/Scripting/ModelNames.cpp index 5b6b6501..5cf68e15 100644 --- a/Solution/source/Scripting/ModelNames.cpp +++ b/Solution/source/Scripting/ModelNames.cpp @@ -240,7 +240,7 @@ void PopulateVehicleModelsArray() { for (auto& dd : hashes[d]) { - addlog(ige::LogType::LOG_TRACE, "Read vehicle model: " + Model(dd).VehicleModelName(), __FILENAME__); + addlog(ige::LogType::LOG_TRACE, "Read vehicle model: " + std::to_string(Model(dd).hash) + " - " + Model(dd).VehicleModelName(), __FILENAME__); if (std::find(g_vehHashes.begin(), g_vehHashes.end(), Model(dd)) == g_vehHashes.end()) { if (g_isEnhanced || !isMinGameVersion3095 || !IS_VEHICLE_GEN9_EXCLUSIVE_MODEL(dd)) diff --git a/Solution/source/Submenus/MiscOptions.cpp b/Solution/source/Submenus/MiscOptions.cpp index 79212139..2ceaa410 100644 --- a/Solution/source/Submenus/MiscOptions.cpp +++ b/Solution/source/Submenus/MiscOptions.cpp @@ -399,7 +399,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); addlog(ige::LogType::LOG_ERROR, "Invalid input radius entered: " + inputStr, __FILENAME__); } } diff --git a/Solution/source/Submenus/PedAnimation.cpp b/Solution/source/Submenus/PedAnimation.cpp index f25ac286..b9b29b02 100644 --- a/Solution/source/Submenus/PedAnimation.cpp +++ b/Solution/source/Submenus/PedAnimation.cpp @@ -759,7 +759,7 @@ namespace sub std::string inputStr = Game::InputBox(_globalCustomAnim_dict, 126U, "Enter dict:", _globalCustomAnim_dict); if (inputStr.length() > 0) _globalCustomAnim_dict = inputStr; - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1String, _globalCustomAnim_dict, 126U, "Enter dict:", _globalCustomAnim_dict); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_globalCustomAnim_dict); return; @@ -770,7 +770,7 @@ namespace sub std::string inputStr = Game::InputBox(_globalCustomAnim_name, 126U, "Enter name:", _globalCustomAnim_name); if (inputStr.length() > 0) _globalCustomAnim_name = inputStr; - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1String, _globalCustomAnim_name, 126U, "Enter name:", _globalCustomAnim_name); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_globalCustomAnim_name); return; diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index 6cc1fc74..ee70dbb7 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -282,10 +282,10 @@ namespace sub if (compon_drawable_current > GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(Static_241, Static_12) - 1) { compon_drawable_current = compon_drawable_old; - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } } else if (compon_plus) @@ -1650,7 +1650,7 @@ namespace sub ComponentChanger_Outfit_catind::Create(Static_241, _dir + "\\" + inputStr + ".xml"); Game::Print::PrintBottomLeft("File ~b~created~s~."); } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStr); return; //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SavepIndexOutfitToFile, std::string(), 28U, "FMMC_KEY_TIP9"); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_dir); @@ -1674,7 +1674,7 @@ namespace sub addlog(ige::LogType::LOG_ERROR, "Attempt to create folder " + inputStr + " failed", __FILENAME__); } } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStr); return; // No OnscreenKeyboard! } @@ -1753,7 +1753,7 @@ namespace sub else Game::Print::PrintBottomCentre("~r~Error:~s~ Unable to rename file."); addlog(ige::LogType::LOG_ERROR, "Attempt to rename file " + _name + " to " + newName + "failed", __FILENAME__); } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(newName); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::RenameOutfitFile, std::string(), 28U, "FMMC_KEY_TIP9", _name); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_name); //OnscreenKeyboard::State::arg2._ptr = reinterpret_cast(&_dir); diff --git a/Solution/source/Submenus/PedModelChanger.cpp b/Solution/source/Submenus/PedModelChanger.cpp index ab0c598a..13993e0a 100644 --- a/Solution/source/Submenus/PedModelChanger.cpp +++ b/Solution/source/Submenus/PedModelChanger.cpp @@ -171,11 +171,11 @@ namespace sub } else Game::Print::PrintBottomLeft("~r~Error:~s~ Unable to add ped model."); } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(customNameStr); } - else Game::Print::PrintError_InvalidModel(); + else Game::Print::PrintError_InvalidModel(hashNameStr); } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(hashNameStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::FavouritePedModelEntryName, std::string(), 40U, "Enter model name (e.g. IG_BENNY):"); } @@ -384,7 +384,7 @@ namespace sub if (model.IsInCdImage()) ChangeModel_(model); else - Game::Print::PrintError_InvalidModel(); + Game::Print::PrintError_InvalidModel(inputStr); return; } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::ModelChangerInput, std::string(), 64U, "Enter ped model name (e.g. IG_BENNY):"); diff --git a/Solution/source/Submenus/PlayerOptions.cpp b/Solution/source/Submenus/PlayerOptions.cpp index 5330121e..d73b496b 100644 --- a/Solution/source/Submenus/PlayerOptions.cpp +++ b/Solution/source/Submenus/PlayerOptions.cpp @@ -356,7 +356,7 @@ namespace sub try { flagID = stoi(inputStr); } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); addlog(ige::LogType::LOG_ERROR, "Invalid flagID entered: " + inputStr, __FILENAME__); } } diff --git a/Solution/source/Submenus/Settings.cpp b/Solution/source/Submenus/Settings.cpp index 1c0b32f6..d8e24547 100644 --- a/Solution/source/Submenus/Settings.cpp +++ b/Solution/source/Submenus/Settings.cpp @@ -160,8 +160,8 @@ namespace sub try { tempHash = abs(std::stoi(Game::InputBox(std::to_string(*settings_rgba2), 4U, "", std::to_string(*settings_rgba2)))); } - catch (...) { Game::Print::PrintError_InvalidInput(); } - if (!(tempHash >= 0 && tempHash <= 255)) Game::Print::PrintError_InvalidInput(); + catch (...) { Game::Print::PrintError_InvalidInput(std::to_string(tempHash)); } + if (!(tempHash >= 0 && tempHash <= 255)) Game::Print::PrintError_InvalidInput(std::to_string(tempHash)); else *settings_rgba2 = tempHash; //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SettingsRgba, std::to_string(*settings_rgba2), 3U, "", std::to_string(*settings_rgba2)); return; @@ -235,7 +235,7 @@ namespace sub auto& settings_font = _g_settings_font; int tempHash = *settings_font; try { tempHash = abs(stoi(inputStr)); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } *settings_font = tempHash; //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SettingsFont, std::to_string(*settings_font), 6U, "", std::to_string(*settings_font)); } diff --git a/Solution/source/Submenus/Spooner/EntityManagement.cpp b/Solution/source/Submenus/Spooner/EntityManagement.cpp index c6ea445a..7460b35b 100644 --- a/Solution/source/Submenus/Spooner/EntityManagement.cpp +++ b/Solution/source/Submenus/Spooner/EntityManagement.cpp @@ -420,7 +420,8 @@ namespace sub::Spooner } if (!model.IsInCdImage()) { - Game::Print::PrintError_InvalidModel(); + Game::Print::PrintError_InvalidModel(name); + addlog(ige::LogType::LOG_ERROR, "Failed to spawn ped, invalid model: " + name, __FILENAME__); return SpoonerEntity(); } @@ -508,7 +509,8 @@ namespace sub::Spooner } if (!model.IsInCdImage()) { - Game::Print::PrintError_InvalidModel(); + Game::Print::PrintError_InvalidModel(name); + addlog(ige::LogType::LOG_ERROR, "Failed to spawn vehicle, invalid model: " + name, __FILENAME__); return SpoonerEntity(); } diff --git a/Solution/source/Submenus/Spooner/Submenus.cpp b/Solution/source/Submenus/Spooner/Submenus.cpp index 104cf36b..25587801 100644 --- a/Solution/source/Submenus/Spooner/Submenus.cpp +++ b/Solution/source/Submenus/Spooner/Submenus.cpp @@ -138,7 +138,7 @@ namespace sub if (inputStr.length() > 0) { try { val = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 10U, std::to_string(val).substr(0, 10)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&val); @@ -163,7 +163,7 @@ namespace sub if (inputStr.length() > 0) { try { val = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 10U, std::to_string(val).substr(0, 10)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&val); @@ -320,7 +320,7 @@ namespace sub } } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); return; // No OnscreenKeyboard! } @@ -1179,7 +1179,7 @@ namespace sub } ent.Health_set(thisHealth); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SpoonerEoHealth, std::string(), 4U, std::string(), std::to_string(thisHealth)); //OnscreenKeyboard::State::arg1._int = ent.GetHandle(); @@ -1415,7 +1415,7 @@ namespace sub // break; // } //} - //if (!found) Game::Print::PrintError_InvalidInput(); + //if (!found) Game::Print::PrintError_InvalidInput(inputStr); Menu::SetSub_delayed = SUB::SPOONER_ATTACHMENTOPS_SELECTBONE; } } @@ -1470,7 +1470,7 @@ namespace sub // break; // } //} - //if (!found) Game::Print::PrintError_InvalidInput(); + //if (!found) Game::Print::PrintError_InvalidInput(inputStr); Menu::SetSub_delayed = SUB::SPOONER_ATTACHMENTOPS_SELECTBONE; } } @@ -2292,7 +2292,7 @@ namespace sub thisArmour = stoi(inputStr); thisPed.Armour_set(thisArmour); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SpoonerEoArmour, std::string(), 4U, std::string(), std::to_string(thisHealth)); //OnscreenKeyboard::State::arg1._int = ent.GetHandle(); @@ -3227,7 +3227,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::AlphaLevelMenuInput, std::string(), 3U, "Enter an alpha level (0-255):", std::to_string(alphaLevel)); @@ -3802,7 +3802,7 @@ namespace sub { Entity tempEntity = Static_241; Hash tempHash = GET_HASH_KEY(inputStr); - if (!IS_MODEL_IN_CDIMAGE(tempHash)) Game::Print::PrintError_InvalidModel(); + if (!IS_MODEL_IN_CDIMAGE(tempHash)) Game::Print::PrintError_InvalidModel(inputStr); else { if (IS_PED_IN_ANY_VEHICLE(Static_241, 0)) tempEntity = GET_VEHICLE_PED_IS_IN(Static_241, 0); @@ -3857,7 +3857,7 @@ namespace sub if (inputStr.length() > 0) { Hash tempHash = GET_HASH_KEY(inputStr); - if (!IS_MODEL_IN_CDIMAGE(tempHash)) Game::Print::PrintError_InvalidModel(); + if (!IS_MODEL_IN_CDIMAGE(tempHash)) Game::Print::PrintError_InvalidModel(inputStr); else { Entity tempEntity = Static_241; diff --git a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp index a9359ed1..a4221c9c 100644 --- a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp +++ b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp @@ -86,7 +86,7 @@ namespace sub::Spooner if (inputStr.length()) { try { tskPtr->healthValue = stoi(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Int, std::string(), 5U, std::string(), std::to_string(tskPtr->healthValue)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->healthValue); @@ -611,7 +611,7 @@ namespace sub::Spooner if (inputStr.length() > 0) { try { tskPtr->speed = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 5U, std::string(), std::to_string(tskPtr->speed).substr(0, 5)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->speed); @@ -627,7 +627,7 @@ namespace sub::Spooner if (inputStr.length() > 0) { try { tskPtr->speedMultiplier = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 5U, std::string(), std::to_string(tskPtr->speedMultiplier).substr(0, 5)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->speedMultiplier); @@ -980,7 +980,7 @@ namespace sub::Spooner if (inputStr.length() > 0) { try { tskPtr->speedInKmph = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 5U, std::string(), std::to_string(tskPtr->speedInKmph).substr(0, 5)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->speedInKmph); @@ -1016,7 +1016,7 @@ namespace sub::Spooner if (inputStr.length() > 0) { try { tskPtr->speedInKmph = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 5U, std::string(), std::to_string(tskPtr->speedInKmph).substr(0, 5)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->speedInKmph); @@ -1054,7 +1054,7 @@ namespace sub::Spooner if (inputStr.length() > 0) { try { tskPtr->speedInKmph = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 5U, std::string(), std::to_string(tskPtr->speedInKmph).substr(0, 5)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->speedInKmph); @@ -1154,7 +1154,7 @@ namespace sub::Spooner if (inputStr.length() > 0) { try { tskPtr->speedInKmph = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 5U, std::string(), std::to_string(tskPtr->speedInKmph).substr(0, 5)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->speedInKmph); @@ -1451,7 +1451,7 @@ namespace sub::Spooner throw; tskPtr->opacityValue = inputVal; } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Int, std::string(), 5U, std::string(), std::to_string(tskPtr->opacityValue)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&tskPtr->opacityValue); diff --git a/Solution/source/Submenus/StatManager.cpp b/Solution/source/Submenus/StatManager.cpp index 8d26e217..99b8e6c4 100644 --- a/Solution/source/Submenus/StatManager.cpp +++ b/Solution/source/Submenus/StatManager.cpp @@ -151,7 +151,7 @@ namespace sub StatSetInt(statName, statValue); } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); addlog(ige::LogType::LOG_ERROR, "Invalid Stat Integer for " + stat.caption + " Entered", __FILENAME__); } } @@ -177,7 +177,7 @@ namespace sub StatSetFloat(statName, statValue); } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); addlog(ige::LogType::LOG_ERROR, "Invalid Stat Float for " + stat.caption + " Entered", __FILENAME__); } } diff --git a/Solution/source/Submenus/Teleport/Teleport_Submenus.cpp b/Solution/source/Submenus/Teleport/Teleport_Submenus.cpp index abed854d..963a7655 100644 --- a/Solution/source/Submenus/Teleport/Teleport_Submenus.cpp +++ b/Solution/source/Submenus/Teleport/Teleport_Submenus.cpp @@ -265,7 +265,7 @@ namespace sub::TeleportLocations_catind Game::Print::PrintBottomLeft("Location ~b~saved~s~."); } } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SaveEntityLocation, std::string(), 28U, "Enter name:"); //OnscreenKeyboard::State::arg1._int = Static_241; } diff --git a/Solution/source/Submenus/VehicleModShop.cpp b/Solution/source/Submenus/VehicleModShop.cpp index 6cb36ab1..3fec590c 100644 --- a/Solution/source/Submenus/VehicleModShop.cpp +++ b/Solution/source/Submenus/VehicleModShop.cpp @@ -721,7 +721,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -919,7 +919,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -1010,7 +1010,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -1346,7 +1346,7 @@ namespace sub { int newVal = abs(stoi(inputStr)); if (newVal < 0 || newVal > 255) - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); else { ms_paints_rgb_r = newVal; @@ -1355,7 +1355,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::CustomsRgbR, std::string(), 3U, std::string(), std::to_string(ms_paints_rgb_r)); @@ -1384,7 +1384,7 @@ namespace sub { int newVal = abs(stoi(inputStr)); if (newVal < 0 || newVal > 255) - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); else { ms_paints_rgb_g = newVal; @@ -1393,7 +1393,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::CustomsRgbG, std::string(), 3U, std::string(), std::to_string(ms_paints_rgb_g)); @@ -1422,7 +1422,7 @@ namespace sub { int newVal = abs(stoi(inputStr)); if (newVal < 0 || newVal > 255) - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); else { ms_paints_rgb_b = newVal; @@ -1431,7 +1431,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::CustomsRgbB, std::string(), 3U, std::string(), std::to_string(ms_paints_rgb_b)); @@ -1460,7 +1460,7 @@ namespace sub { int newVal = abs(stoi(inputStr)); if (newVal < 0 || newVal > 255) - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); else { ms_paints_rgb_a = newVal; @@ -1469,7 +1469,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::CustomsRgbA, std::string(), 3U, std::string(), std::to_string(ms_paints_rgb_a)); @@ -1506,15 +1506,15 @@ namespace sub rgb_mode_set_carcol(Static_12, ms_paints_rgb_r, ms_paints_rgb_g, ms_paints_rgb_b, 255); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } if (settings_hud_c_plus) { @@ -1531,7 +1531,7 @@ namespace sub /*int tempHash = settings_hud_c; try{ tempHash = abs(stoi(Game::InputBox(std::to_string(settings_hud_c)))); } catch (...){ tempHash = settings_hud_c; } - if (!(tempHash >= 0 && tempHash <= 180)) Game::Print::PrintError_InvalidInput(); + if (!(tempHash >= 0 && tempHash <= 180)) Game::Print::PrintError_InvalidInput(inputStr); else { settings_hud_c = tempHash; @@ -2191,7 +2191,7 @@ namespace sub vehicle.NumberPlateText_set(inputStr); Game::Print::PrintBottomLeft("CMOD_PLATEFIT", true); } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::CustomsPlateText, std::string(), 8U, "CMOD_MOD_18_D", ms_plateText); //OnscreenKeyboard::State::arg1._int = vehicle.Handle(); return; @@ -2218,7 +2218,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2275,7 +2275,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2332,7 +2332,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2389,7 +2389,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2626,42 +2626,50 @@ namespace sub } void __AddOption(const std::string& text, Vehicle vehicle, INT8 wheelType, INT16 wheelIndex, bool isBikeBack) { + addlog(ige::LogType::LOG_TRACE, "Starting Addoption", __FILENAME__); if (_globalLSC_Customs) { auto& lastwheelRelevant = isBikeBack ? lastbwheel : lastfwheel; bool pressed = false; + addlog(ige::LogType::LOG_TRACE, "Got lastwheelRelevant: " + std::to_string(lastwheelRelevant),__FILENAME__); AddTickol(text, lastwheelRelevant == wheelIndex && lastwheeltype == wheelType, pressed, pressed, IS_THIS_MODEL_A_BIKE(GET_ENTITY_MODEL(vehicle)) ? TICKOL::BIKETHING : TICKOL::CARTHING, TICKOL::NONE, true); bool allowSettingWheelPreview = GET_VEHICLE_WHEEL_TYPE(vehicle) != wheelType || (wheelType == WheelType::BikeWheels && isBikeBack ? GET_VEHICLE_MOD(vehicle, VehicleMod::BackWheels) != wheelIndex : GET_VEHICLE_MOD(vehicle, VehicleMod::FrontWheels) != wheelIndex); + addlog(ige::LogType::LOG_TRACE, "allowSettingWheelPreview: " + std::to_string(allowSettingWheelPreview), __FILENAME__); + addlog(ige::LogType::LOG_TRACE, "Comparing currrentopATM: " + std::to_string((int)(*Menu::currentopATM)) + " to printingop: " + std::to_string((int)(Menu::printingop)), __FILENAME__); if (*Menu::currentopATM == Menu::printingop && allowSettingWheelPreview) { + addlog(ige::LogType::LOG_TRACE, "Setting wheel preview: type " + std::to_string(wheelType) + ", index " + std::to_string(wheelIndex), __FILENAME__); GTAvehicle(vehicle).RequestControlOnce(); SET_VEHICLE_WHEEL_TYPE(vehicle, wheelType); if (wheelType == WheelType::BikeWheels) { - isBikeBack ? SET_VEHICLE_MOD(vehicle, VehicleMod::BackWheels, wheelIndex, GET_VEHICLE_MOD_VARIATION(vehicle, VehicleMod::BackWheels)) //for some reason, inverting this allows the previews to work, albeit reversed. - : SET_VEHICLE_MOD(vehicle, VehicleMod::FrontWheels, wheelIndex, GET_VEHICLE_MOD_VARIATION(vehicle, VehicleMod::FrontWheels)); //but as it stands now, refuses to preview the wheels at all. + addlog(ige::LogType::LOG_TRACE, "Setting Bike Wheels", __FILENAME__); + isBikeBack ? SET_VEHICLE_MOD(vehicle, VehicleMod::BackWheels, wheelIndex, GET_VEHICLE_MOD_VARIATION(vehicle, VehicleMod::BackWheels)) + : SET_VEHICLE_MOD(vehicle, VehicleMod::FrontWheels, wheelIndex, GET_VEHICLE_MOD_VARIATION(vehicle, VehicleMod::FrontWheels)); } else { + addlog(ige::LogType::LOG_TRACE, "Setting Car Wheels", __FILENAME__); SET_VEHICLE_MOD(vehicle, VehicleMod::FrontWheels, wheelIndex, GET_VEHICLE_MOD_VARIATION(vehicle, VehicleMod::FrontWheels)); //SET_VEHICLE_MOD(vehicle, VehicleMod::BackWheels, wheelIndex, GET_VEHICLE_MOD_VARIATION(vehicle, VehicleMod::BackWheels)); //redundant on non-bike tuning } } - + addlog(ige::LogType::LOG_TRACE, "ended comparison, waiting for selection", __FILENAME__); if (pressed) { + addlog(ige::LogType::LOG_TRACE, "Selection made", __FILENAME__); lastwheeltype = wheelType; lastfwheel = GET_VEHICLE_MOD(vehicle, VehicleMod::FrontWheels); lastbwheel = GET_VEHICLE_MOD(vehicle, VehicleMod::BackWheels); + addlog(ige::LogType::LOG_DEBUG, "Wheels Set, lastwheeltype = " + std::to_string(lastwheeltype) + ", lastfwheel = " + std::to_string(lastfwheel) + ", lastbwheel = " + std::to_string(lastbwheel), __FILENAME__); //Menu::SetSub_previous(); return; } - } else ///lsccustoms off { @@ -2692,6 +2700,7 @@ namespace sub //ms_wheel_windice_pressed = true; } } + addlog(ige::LogType::LOG_TRACE, "Looping Addoption", __FILENAME__); } } @@ -2929,15 +2938,16 @@ namespace sub //} //max -= 1; - int windices2; if (wtype == WheelType::BikeWheels) // Bike Normal/Chrome { + addlog(ige::LogType::LOG_TRACE, "Entering Bike Wheels section MSWheels3_ with vehicle handle: {}" + std::to_string(Static_12), __FILENAME__); bool bIsChromeSelected = chrtype == 1 || chrtype == 3; AddTitle(bIsChromeSelected ? "Chrome Wheels" : "Bike Wheels"); - + std::array ids{ 0, 13, 26, 48, ms_max_windices }; + addlog(ige::LogType::LOG_TRACE, "Adding " + std::to_string(ms_max_windices) + " Wheel Options", __FILENAME__); for (int j = bIsChromeSelected ? 0 : 0; j < ids.size(); j += 1) { for (i = ids[j]; i < ids[j + 1]; i++) @@ -2945,7 +2955,7 @@ namespace sub __AddOption(get_mod_text_label(Static_12, VehicleMod::FrontWheels, i, false), Static_12, wtype, i, chrtype == 2); } } - + addlog(ige::LogType::LOG_TRACE, "Finished Adding Wheel Options", __FILENAME__); if (_globalLSC_Customs && Menu::OnSubBack == nullptr) // this has been split out for bikes, see further comments on the original section below (line 2575) { Menu::OnSubBack = [&]() @@ -2954,6 +2964,7 @@ namespace sub : SET_VEHICLE_MOD(Static_12, VehicleMod::FrontWheels, lastfwheel, GET_VEHICLE_MOD_VARIATION(Static_12, VehicleMod::FrontWheels)); }; } + addlog(ige::LogType::LOG_TRACE, "Exiting Bike Wheels section MSWheels3_", __FILENAME__); return; } else //if (wtype == WheelType::Bennys || wtype == WheelType::BennysBespoke) // Benny's @@ -3396,7 +3407,7 @@ namespace sub if (inputStr.length()) { if (!Model(inputStr).IsVehicle()) - Game::Print::PrintError_InvalidModel(); + Game::Print::PrintError_InvalidInput(inputStr); else { GTAvehicle vehicle = Static_12; diff --git a/Solution/source/Submenus/VehicleOptions.cpp b/Solution/source/Submenus/VehicleOptions.cpp index b632f54d..d0acf96f 100644 --- a/Solution/source/Submenus/VehicleOptions.cpp +++ b/Solution/source/Submenus/VehicleOptions.cpp @@ -1103,7 +1103,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::to_string(_global_MultiPlatNeons_Intensity), 9U, "Enter Value:", std::to_string(_global_MultiPlatNeons_Intensity)); diff --git a/Solution/source/Submenus/VehicleSpawner.cpp b/Solution/source/Submenus/VehicleSpawner.cpp index 61dab146..0da05266 100644 --- a/Solution/source/Submenus/VehicleSpawner.cpp +++ b/Solution/source/Submenus/VehicleSpawner.cpp @@ -1253,7 +1253,7 @@ namespace sub if (!NETWORK_IS_IN_SESSION() && !_globalSpawnVehicle_persistent) SET_VEHICLE_AS_NO_LONGER_NEEDED(&spawnedVehicle); } - else Game::Print::PrintError_InvalidModel(); + else Game::Print::PrintError_InvalidModel(model.VehicleModelName()); } /*if (spawnvehicle_input) { @@ -1324,7 +1324,7 @@ namespace sub if (inputStr.length() > 0 && inputStr.length() <= 8) _globalSpawnVehicle_plateText = inputStr; else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::GSpawnVehiclePlateText, std::string(), 8U, "CMOD_MOD_18_D", _globalSpawnVehicle_plateText); break; } @@ -1577,7 +1577,7 @@ namespace sub } } else - Game::Print::PrintError_InvalidModel(); + Game::Print::PrintError_InvalidModel(inputStrModel); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::FavouriteVehicleModelEntryName, std::string(), 28U, "Enter model name (e.g. adder):"); } @@ -1598,7 +1598,7 @@ namespace sub } else Game::Print::PrintBottomLeft("~r~Error:~s~ Unable to add model."); } - else Game::Print::PrintError_InvalidInput(); + else Game::Print::PrintError_InvalidInput(inputStrName); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::FavouriteVehicleModelCurrent, std::string(), 28U, "Enter custom name:", myVehicleModel.VehicleDisplayName(true)); //OnscreenKeyboard::State::arg1._uint = myVehicleModel.hash; } @@ -1974,7 +1974,7 @@ namespace sub Model eModel = nodeVehicle.child("ModelHash").text().as_uint(); if (!eModel.IsInCdImage()) { - Game::Print::PrintError_InvalidModel(); + Game::Print::PrintError_InvalidModel(std::to_string(eModel.hash)); return; } eModel.Load(); @@ -2537,7 +2537,7 @@ namespace sub VehSaver_SaveToFile(_dir + "\\" + inputStr + ".xml", vehicle); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SaveVehicleToFile, std::string(), 28U, "Enter file name:"); //OnscreenKeyboard::State::arg1._int = vehicle; //OnscreenKeyboard::State::arg2._ptr = reinterpret_cast(&_dir); @@ -2571,7 +2571,7 @@ namespace sub } } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); return; // No OnscreenKeyboard! } @@ -2618,7 +2618,7 @@ namespace sub Game::Print::PrintBottomCentre("~r~Error~s~ renaming file."); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::RenameVehicleFile, std::string(), 28U, "Enter new name:", _name); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_name); //OnscreenKeyboard::State::arg2._ptr = reinterpret_cast(&_dir); diff --git a/Solution/source/Submenus/WeaponOptions.cpp b/Solution/source/Submenus/WeaponOptions.cpp index fb5b265b..73543475 100644 --- a/Solution/source/Submenus/WeaponOptions.cpp +++ b/Solution/source/Submenus/WeaponOptions.cpp @@ -195,7 +195,7 @@ namespace sub if (inputStr.length() > 0) { try { _globalForgeGun_shootForce = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 10U, std::to_string(_globalForgeGun_shootForce)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_globalForgeGun_shootForce); @@ -435,7 +435,7 @@ namespace sub if (inputStr.length() > 0) { try { shootForce = stof(inputStr); } - catch (...) { Game::Print::PrintError_InvalidInput(); } + catch (...) { Game::Print::PrintError_InvalidInput(inputStr); } } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SetArg1Float, std::string(), 10U, std::to_string(shootForce)); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&shootForce); @@ -524,7 +524,7 @@ namespace sub kaboom_gun_hash = model.hash; model.Load(); } - else Game::Print::PrintError_InvalidModel(); + else Game::Print::PrintError_InvalidModel(inputStr); } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::KaboomGunHash, std::string(), 64U, "Enter vehicle model name:"); } @@ -639,7 +639,7 @@ namespace sub ped_gun_hash = model; model.Load(); } - else Game::Print::PrintError_InvalidModel(); + else Game::Print::PrintError_InvalidModel(inputStr); } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::PedGunHash, std::string(), 64U, "Enter ped model name:"); } @@ -735,7 +735,7 @@ namespace sub object_gun_hash = model; model.Load(); } - else Game::Print::PrintError_InvalidModel(); + else Game::Print::PrintError_InvalidModel(inputStr); } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::ObjectGunHash, std::string(), 64U, "Enter object/vehicle model name:"); } @@ -925,13 +925,13 @@ namespace sub Game::Print::PrintBottomLeft("~r~Error:~s~ Unable to add weapon."); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(customNameStr); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(std::to_string(hashNameHash)); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(hashNameStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::FavouriteWeaponEntryName, std::string(), 40U, "Enter name (e.g. WEAPON_FLAMETHROWER):"); } @@ -953,7 +953,7 @@ namespace sub Game::Print::PrintBottomLeft("~r~Error:~s~ Unable to add weapon."); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(customNameStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::FavouriteWeaponCurrent, std::string(), 28U, "Enter custom name:"); //OnscreenKeyboard::State::arg1._uint = currentPedWeapon; } @@ -1545,7 +1545,7 @@ namespace sub Game::Print::PrintBottomLeft("~r~Error:~s~ Unable to save loadout."); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::SaveLoadoutToFile, std::string(), 28U, "Enter loadout name:"); //OnscreenKeyboard::State::arg1._int = _ped; //OnscreenKeyboard::State::arg2._ptr = reinterpret_cast(&_dir); @@ -1569,7 +1569,7 @@ namespace sub } } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); return; // No OnscreenKeyboard! } @@ -1611,7 +1611,7 @@ namespace sub Game::Print::PrintBottomCentre("~r~Error~s~ renaming file."); } else - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::RenameLoadoutFile, std::string(), 28U, "Enter new name:"); //OnscreenKeyboard::State::arg1._ptr = reinterpret_cast(&_name); //OnscreenKeyboard::State::arg2._ptr = reinterpret_cast(&_dir); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 2255507b..7467e443 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a4" +#define MENYOO_CURRENT_VER_ "2.2.0a5" #define GAME_PLAYERCOUNT 30 From f068b189676f658aa92e7cb49b1c95a637a69aba Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 4 Nov 2025 23:49:26 +0400 Subject: [PATCH 21/49] Fix #278 (#365) Add check for component count Ignore options where component count is zero --- .../source/Submenus/PedComponentChanger.cpp | 61 ++++++++++++++++--- Solution/source/macros.h | 2 +- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index ee70dbb7..332dc4b5 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -94,8 +94,30 @@ namespace sub AddOption("Head Features", null, nullFunc, SUB::PED_HEADFEATURES_MAIN); AddOption("Accessories", null, nullFunc, SUB::COMPONENTSPROPS); + std::vector components + { + "Head", + "Beard/Mask", + "Hair", + "Torso", + "Legs", + "Hands/Back", + "Shoes", + "Teeth/Scarf/Necklace/Bracelets", + "Accessory/Tops", + "Task/Armour", + "Emblem", + "Tops2 (Outer)" + }; + AddBreak("---Components---"); - AddpedcomponentOption_("Head", PV_COMP_HEAD); + + for ( int i = 0; i < PV_COMP_MAX; i++) + { + if(GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(Static_241, i) > 0) AddpedcomponentOption_(components[i], i); + } + + /*AddpedcomponentOption_("Head", PV_COMP_HEAD); AddpedcomponentOption_("Beard/Mask", PV_COMP_BERD); // Beard // FACE_BRD AddpedcomponentOption_("Hair", PV_COMP_HAIR); // Hair // FACE_HAIR AddpedcomponentOption_("Torso", PV_COMP_UPPR); @@ -106,7 +128,7 @@ namespace sub AddpedcomponentOption_("Accessory/Tops", PV_COMP_ACCS); // Accessory // PIM_TACCE AddpedcomponentOption_("Task/Armour", PV_COMP_TASK); AddpedcomponentOption_("Emblem", PV_COMP_DECL); - AddpedcomponentOption_("Tops2 (Outer)", PV_COMP_JBIB); + AddpedcomponentOption_("Tops2 (Outer)", PV_COMP_JBIB);*/ AddOption("Random Components", ComponentChanger_random); AddOption("Default Components", ComponentChanger_default); @@ -264,10 +286,11 @@ namespace sub AddTitle("Set Variation"); - AddNumber("Type", compon_drawable_current, 0, compon_input, compon_plus, compon_minus); - AddNumber("Texture", compon_texture_current, 0, null, compon_plus, compon_minus); + if(GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(Static_241, Static_12) > 0) AddNumber("Type", compon_drawable_current, 0, compon_input, compon_plus, compon_minus); + if(GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(Static_241, Static_12, compon_drawable_current)) AddNumber("Texture", compon_texture_current, 0, null, compon_plus, compon_minus); //AddNumber("Palette", compon_palette_current, 0, null, compon_plus, compon_minus); + switch (*Menu::currentopATM) { case 1: @@ -416,10 +439,29 @@ namespace sub } bool ComponentChanger_randomProps = 0, ComponentChanger_clearAllProps = 0; + std::vector components + { + "Hats", + "Glasses", + "Ear Pieces", + "Unknown 3", + "Unknown 4", + "Unknown 5", + "Watches", + "Bangles", + "Unknown 8", + "Unknown 9" + }; AddTitle("Accessories"); - AddpedpropOption_("Hats", 0); + for (int i = 0; i < components.size(); ++i) + { + if (GET_NUMBER_OF_PED_PROP_DRAWABLE_VARIATIONS(Static_241, i) > 0) + AddpedpropOption_(components[i], i); + } + + /*AddpedpropOption_("Hats", 0); AddpedpropOption_("Glasses", 1); AddpedpropOption_("Ear Pieces", 2); AddpedpropOption_("Watches", 6); @@ -430,7 +472,7 @@ namespace sub AddpedpropOption_("Unknown 4", 4); AddpedpropOption_("Unknown 5", 5); AddpedpropOption_("Unknown 8", 8); - AddpedpropOption_("Unknown 9", 9); + AddpedpropOption_("Unknown 9", 9);*/ AddBreak("---Utilities---"); AddOption("Random Accessories", ComponentChanger_randomProps); @@ -464,9 +506,8 @@ namespace sub AddTitle("Set Variation"); - AddNumber("Type", prop_type_current, 0, null, compon_plus, compon_minus); - AddNumber("Texture", prop_texture_current, 0, null, compon_plus, compon_minus); - + if (GET_NUMBER_OF_PED_PROP_DRAWABLE_VARIATIONS(Static_241, Static_12) > 0) AddNumber("Type", prop_type_current, 0, null, compon_plus, compon_minus); + if (GET_NUMBER_OF_PED_PROP_TEXTURE_VARIATIONS(Static_241, Static_12, prop_type_current) > 0) AddNumber("Texture", prop_texture_current, 0, null, compon_plus, compon_minus); switch (Menu::currentop) { @@ -553,7 +594,7 @@ namespace sub prop_texture_current = 0; } } - SET_PED_PROP_INDEX(ped.Handle(), propId, prop_type_current, prop_texture_current, NETWORK_IS_GAME_IN_PROGRESS(), 0); + SET_PED_PROP_INDEX(ped.Handle(), propId, prop_type_current, prop_texture_current, NETWORK_IS_GAME_IN_PROGRESS(), 0); } } } diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 7467e443..d97ccd4b 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a5" +#define MENYOO_CURRENT_VER_ "2.2.0a6" #define GAME_PLAYERCOUNT 30 From 60e31ca673dcff88e4a2a9f86357e21da3cc39f8 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Tue, 4 Nov 2025 23:58:38 +0400 Subject: [PATCH 22/49] Enable actual release by removing 'dry-run' option Removed the 'dry-run' option from the release step. --- .github/workflows/master_build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 8ea6881e..69ad6c86 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -195,4 +195,3 @@ jobs: prerelease: ${{ github.ref_name != 'main' }} title: ${{ steps.version.outputs.version}} files: MenyooSP.zip - dry-run: true From 0614fc9d2626f8039d5e926cf7a39abbfaafc80a Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 5 Nov 2025 20:15:26 +0400 Subject: [PATCH 23/49] 278 game freezes when trying to customize wardrobe of any vanilla peds or addon peds with menyoo 20 (#366) * Fix #222 Add check for component count Ignore options where component count is zero * Fix #278 Force pearl to Black when custom spawn colour set * unlock elongation referenced in #181 Remove version lock Added "experimental" note to function title. * Update MENYOO_CURRENT_VER_ to version 2.2.0a7 --- Solution/source/Memory/GTAmemory.cpp | 20 +++----------------- Solution/source/Submenus/PlayerOptions.cpp | 2 +- Solution/source/Submenus/VehicleModShop.cpp | 6 +++++- Solution/source/macros.h | 2 +- 4 files changed, 10 insertions(+), 20 deletions(-) diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index aab7739c..0e093337 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -2784,27 +2784,13 @@ void** GeneralGlobalHax::WorldPtrPtr() float GeneralGlobalHax::GetPlayerHeight() { - if (!g_isEnhanced) { - auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_2802_0) - return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})); - } - } - return 1.0f; + auto baddr = *GeneralGlobalHax::WorldPtrPtr(); + if (baddr) return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})); } void GeneralGlobalHax::SetPlayerHeight(float value) { - if (g_isEnhanced) return; auto baddr = *GeneralGlobalHax::WorldPtrPtr(); - if (baddr) - { - auto gameVersion = GTAmemory::GetGameVersion(); - if (gameVersion <= eGameVersion::VER_1_0_2802_0) - *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})) = value; - } + if (baddr) *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})) = value; } // For 3521 (Legacy) and 814.9 (Enhanced), PlayerSwimSpeed is at {0x8, 0x10A8, 0x1C8}. diff --git a/Solution/source/Submenus/PlayerOptions.cpp b/Solution/source/Submenus/PlayerOptions.cpp index d73b496b..eb58e8f2 100644 --- a/Solution/source/Submenus/PlayerOptions.cpp +++ b/Solution/source/Submenus/PlayerOptions.cpp @@ -140,7 +140,7 @@ namespace sub AddToggle("Never Wanted", loop_never_wanted, PlayerOpsNeverWantedOn_, PlayerOpsNeverWantedOff_); AddToggle("Burn Mode", loop_player_burn, PlayerOpsBurnModeOn_, PlayerOpsBurnModeOff_); //AddToggle("No Gravity (ALPHA)", loop_player_noGravity, null, PlayerOpsNoGravityOff_); - AddNumber("Height (Elongation)", fHeight, 2, null, bHeight_plus, bHeight_minus); + AddNumber("Height (Elongation) - Experimental", fHeight, 2, null, bHeight_plus, bHeight_minus); //AddNumber("Walk & Run Speed", fMovementSpeed, 2, null, bMovementSpeed_plus, bMovementSpeed_minus); //AddNumber("Swim Speed", fSwimSpeed, 2, null, bSwimSpeed_plus, bSwimSpeed_minus); AddNumber("Movement Speed (Alt)", mult69_0, 2, null, PlayerOps_i69_flt_MovementSpeed, PlayerOps_d69_flt_MovementSpeed); diff --git a/Solution/source/Submenus/VehicleModShop.cpp b/Solution/source/Submenus/VehicleModShop.cpp index 3fec590c..f66eccd3 100644 --- a/Solution/source/Submenus/VehicleModShop.cpp +++ b/Solution/source/Submenus/VehicleModShop.cpp @@ -1657,17 +1657,21 @@ namespace sub WAIT(50); + int colour1, colour2; + GET_VEHICLE_EXTRA_COLOURS(vehicle, &colour1, &colour2); if (prim_col_index != -3) // basic paint primary { CLEAR_VEHICLE_CUSTOM_PRIMARY_COLOUR(vehicle); GET_VEHICLE_COLOURS(vehicle, &i, &inull); - SET_VEHICLE_COLOURS(vehicle, prim_col_index, inull); + SET_VEHICLE_COLOURS(vehicle, prim_col_index, inull); + SET_VEHICLE_EXTRA_COLOURS(vehicle, 0, colour2); } if (sec_col_index != -3) // basic paint secondary { CLEAR_VEHICLE_CUSTOM_SECONDARY_COLOUR(vehicle); GET_VEHICLE_COLOURS(vehicle, &inull, &i); SET_VEHICLE_COLOURS(vehicle, inull, sec_col_index); + SET_VEHICLE_EXTRA_COLOURS(vehicle, 0, colour2); } WAIT(40); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index d97ccd4b..ecbd5002 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a6" +#define MENYOO_CURRENT_VER_ "2.2.0a7" #define GAME_PLAYERCOUNT 30 From e04c03faae4f485af54d607116fe9dabe806386e Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Wed, 5 Nov 2025 20:33:19 +0400 Subject: [PATCH 24/49] fix #204 Add zOffset for two vertical cylinder options. --- Solution/source/Scripting/World.cpp | 4 +++- Solution/source/Submenus/Spooner/FileManagement.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Solution/source/Scripting/World.cpp b/Solution/source/Scripting/World.cpp index 5760ee76..7072ea8d 100644 --- a/Solution/source/Scripting/World.cpp +++ b/Solution/source/Scripting/World.cpp @@ -646,12 +646,14 @@ namespace World { PCHAR dict = 0; PCHAR name = 0; + float zOffset = 0.0f; + if (type == 1 || type == 43) zOffset = -0.5f; if (textureDict.length() > 0 && textureName.length() > 0) { dict = (PCHAR)textureDict.c_str(); name = (PCHAR)textureName.c_str(); } - DRAW_MARKER(type, pos.x, pos.y, pos.z, dir.x, dir.y, dir.z, rot.x, rot.y, rot.z, scale.x, scale.y, scale.z, colour.R, colour.G, colour.B, colour.A, bobUpAndDown, faceCamY, unk2, rotateY, dict, name, drawOnEnt); + DRAW_MARKER(type, pos.x, pos.y, pos.z + zOffset, dir.x, dir.y, dir.z, rot.x, rot.y, rot.z, scale.x, scale.y, scale.z, colour.R, colour.G, colour.B, colour.A, bobUpAndDown, faceCamY, unk2, rotateY, dict, name, drawOnEnt); } void DrawLine(const Vector3& startPos, const Vector3& endPos, const RGBA& colour) diff --git a/Solution/source/Submenus/Spooner/FileManagement.h b/Solution/source/Submenus/Spooner/FileManagement.h index 8b8be781..eef5ccba 100644 --- a/Solution/source/Submenus/Spooner/FileManagement.h +++ b/Solution/source/Submenus/Spooner/FileManagement.h @@ -42,7 +42,8 @@ namespace sub::Spooner SpoonerMarkerWithInitHandle SpawnMarkerFromXmlNode(pugi::xml_node& nodeMarker); bool SaveDbToFile(const std::string& filePath, bool bForceReferenceCoords); - bool SaveWorldToFile(const std::string& filePath, std::vector& vEntityHandles, std::vector& vMarkers); + bool SaveWorldToFile(const std::string& filePath, std::vector& vEntityHandles, std::vector& v + ); bool LoadPlacementsFromFile(const std::string& filePath); bool LoadPlacementsFromSP00NFile(const std::string& filePath); From 8b7f4454fbe8a326b81f0f2fcc3691638aafc47a Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Wed, 5 Nov 2025 20:38:35 +0400 Subject: [PATCH 25/49] Correct marker zOffset value --- Solution/source/Scripting/World.cpp | 2 +- Solution/source/macros.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Solution/source/Scripting/World.cpp b/Solution/source/Scripting/World.cpp index 7072ea8d..c5ef4550 100644 --- a/Solution/source/Scripting/World.cpp +++ b/Solution/source/Scripting/World.cpp @@ -647,7 +647,7 @@ namespace World PCHAR dict = 0; PCHAR name = 0; float zOffset = 0.0f; - if (type == 1 || type == 43) zOffset = -0.5f; + if (type == 1 || type == 43) zOffset = -0.7f; if (textureDict.length() > 0 && textureName.length() > 0) { dict = (PCHAR)textureDict.c_str(); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index ecbd5002..120d26e5 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a7" +#define MENYOO_CURRENT_VER_ "2.2.0a8" #define GAME_PLAYERCOUNT 30 From 61c7656e9173d5d150eddf8f4f18b3a27449a884 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 5 Nov 2025 21:41:21 +0400 Subject: [PATCH 26/49] Update MENYOO_CURRENT_VER_ to version 2.2.0b1 --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 120d26e5..5b9c4fd5 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0a8" +#define MENYOO_CURRENT_VER_ "2.2.0b1" #define GAME_PLAYERCOUNT 30 From 849f8d7e08a20d97e60ae5ebd87c2dc336b5388b Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 12 Nov 2025 11:20:52 +0400 Subject: [PATCH 27/49] Create FUNDING.yml --- .github/FUNDING.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..33dfeecd --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,15 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +polar: # Replace with a single Polar username +buy_me_a_coffee: itsjustcurtis # Replace with a single Buy Me a Coffee username +thanks_dev: # Replace with a single thanks.dev username +custom: https://www.paypal.com/paypalme/curtisre # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] From 7326fc271ecd4f924c6a718a5f837f75944ebab2 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 12 Nov 2025 11:21:40 +0400 Subject: [PATCH 28/49] Update FUNDING.yml --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 33dfeecd..d9446e56 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -12,4 +12,4 @@ lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cl polar: # Replace with a single Polar username buy_me_a_coffee: itsjustcurtis # Replace with a single Buy Me a Coffee username thanks_dev: # Replace with a single thanks.dev username -custom: https://www.paypal.com/paypalme/curtisre # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: https://paypal.me/curtisre # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] From 382a283d91a4158b917db367138c52181c0ea2a7 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 12 Nov 2025 12:33:52 +0400 Subject: [PATCH 29/49] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 23 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..5031ff1a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,23 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[Bug Report]" +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Log** +Change your loglevel in the Menyoo .ini file to 3 and try again. Share your menyoolog.txt file with your report. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..12fef876 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[Feature Request]" +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context, screenshots, or examples of the feature that would help it get implemented. From 787e886d0640214e7f8ff1f7df996c3878e2938c Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Wed, 12 Nov 2025 22:14:24 +0400 Subject: [PATCH 30/49] Add component count check to loaded outfit files --- Solution/source/Submenus/PedComponentChanger.cpp | 9 ++++++++- Solution/source/macros.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index 332dc4b5..46a92a45 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -1509,7 +1509,14 @@ namespace sub int pedCompIdValueDrawable = stoi(pedCompIdValueStr.substr(0, pedCompIdValueStr.find(","))); int pedCompIdValueTexture = stoi(pedCompIdValueStr.substr(pedCompIdValueStr.find(",") + 1)); - SET_PED_COMPONENT_VARIATION(ep.Handle(), pedCompId, pedCompIdValueDrawable, pedCompIdValueTexture, 0); + if (GET_NUMBER_OF_PED_DRAWABLE_VARIATIONS(ep.Handle(), pedCompId) >= pedCompIdValueDrawable && GET_NUMBER_OF_PED_TEXTURE_VARIATIONS(ep.Handle(), pedCompId, pedCompIdValueDrawable) >= pedCompIdValueTexture) + { + SET_PED_COMPONENT_VARIATION(ep.Handle(), pedCompId, pedCompIdValueDrawable, pedCompIdValueTexture, 0); + addlog(ige::LogType::LOG_DEBUG, "Applied ped component " + std::to_string(pedCompId) + " with drawable " + std::to_string(pedCompIdValueDrawable) + " and texture " + std::to_string(pedCompIdValueTexture), __FILENAME__); + } + else + addlog(ige::LogType::LOG_WARNING, "Ped comp " + std::to_string(pedCompId) + " out of range - Drawable " + std::to_string(pedCompIdValueDrawable) + " and texture " + std::to_string(pedCompIdValueTexture), __FILENAME__); + } } if (applyProps) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 5b9c4fd5..43b1db0c 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b1" +#define MENYOO_CURRENT_VER_ "2.2.0b2" #define GAME_PLAYERCOUNT 30 From f5a7bd1240bfda4b48e0a4e35e3834fb635bc672 Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Thu, 13 Nov 2025 11:26:40 +0400 Subject: [PATCH 31/49] Fix inability to select null overlay colour tints without changing varation --- .../source/Submenus/PedComponentChanger.cpp | 29 +++++++++++++------ .../source/Submenus/PedComponentChanger.h | 4 +-- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index 46a92a45..2ad9d275 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -1144,12 +1144,17 @@ namespace sub { currentOverlayValue++; SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, currentOverlayData.colour=0, currentOverlayData.colourSecondary=0); + currentOverlayData.colour - 1; + currentOverlayData.colourSecondary = -1; + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, 0, 0); } else { currentOverlayValue = currentOverlayValue == 255 ? 0 : 255; SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); + currentOverlayData.colour - 1; + currentOverlayData.colourSecondary = -1; + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, 0, 0); SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, currentOverlayData.colour=0, currentOverlayData.colourSecondary=0); } } @@ -1191,7 +1196,7 @@ namespace sub if (bColoursAvailable) { bool colour_plus = 0, colour_minus = 0; - bool colourSecondary_plus = 0, colourSecondary_minus = 0; + bool colourSecondary_plus = 0, colourSecondary_minus = 0, isColour = currentOverlayData.colour > -1; // PRIMARY COLOUR AddNumber(Game::GetGXTEntry("CMOD_COL0_0", "Primary Colour"), currentOverlayData.colour, 0, null, colour_plus, colour_minus); @@ -1200,37 +1205,43 @@ namespace sub if (currentOverlayData.colour < max_colours) { currentOverlayData.colour++; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); + isColour = currentOverlayData.colour > -1; + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); } } if (colour_minus) { - if (currentOverlayData.colour > 0) + if (currentOverlayData.colour > -1) { currentOverlayData.colour--; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); + isColour = currentOverlayData.colour > -1; + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType*isColour, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); } } // SECONDARY COLOUR - AddNumber(Game::GetGXTEntry("CMOD_COL0_1", "Secondary Colour"), currentOverlayData.colourSecondary, 0, null, colourSecondary_plus, colourSecondary_minus); + if(currentOverlayData.colour > -1) + AddNumber(Game::GetGXTEntry("CMOD_COL0_1", "Secondary Colour"), currentOverlayData.colourSecondary, 0, null, colourSecondary_plus, colourSecondary_minus); if (colourSecondary_plus) { if (currentOverlayData.colourSecondary < max_colours) { currentOverlayData.colourSecondary++; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); + isColour = currentOverlayData.colour > -1; + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); } } if (colourSecondary_minus) { - if (currentOverlayData.colourSecondary > 0) + if (currentOverlayData.colourSecondary > -1) { currentOverlayData.colourSecondary--; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); + isColour = currentOverlayData.colour > -1; + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); } } + Game::Print::PrintBottomCentre("overlayIndex = " + std::to_string(overlayIndex) + ", colourType = " + std::to_string(colourType) + ", currentOverlayData.colour = " + std::to_string(currentOverlayData.colour) + ", currentOverlayData.colourSecondary = " + std::to_string(currentOverlayData.colourSecondary)); } } void Sub_FaceFeatures() diff --git a/Solution/source/Submenus/PedComponentChanger.h b/Solution/source/Submenus/PedComponentChanger.h index ab17fe1a..f99040fb 100644 --- a/Solution/source/Submenus/PedComponentChanger.h +++ b/Solution/source/Submenus/PedComponentChanger.h @@ -144,8 +144,8 @@ namespace sub sPedHeadOverlayData() { this->opacity = 1.0f; - this->colour = 0; - this->colourSecondary = 0; + this->colour = -1; + this->colourSecondary = -1; } }; struct sPedHeadFeatures From 7147827eb62b750507b7b8b8c5c2b42ef496bb81 Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Thu, 13 Nov 2025 13:27:55 +0400 Subject: [PATCH 32/49] Fix #281 Refactor SET_PED_HEAD_OVERLAY_TINT into ApplyHeadOverlayTint to allow null value selection and setting. Add value wraparound logic to tint values --- .../source/Submenus/PedComponentChanger.cpp | 59 +++++++++---------- .../source/Submenus/PedComponentChanger.h | 1 + 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index 2ad9d275..35467c95 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -1118,6 +1118,15 @@ namespace sub } } } + + void ApplyHeadOverlayTint(GTAped ped, int overlayIndex, int colourType, int primary, int secondary) + { + if (primary < 0 || colourType == 0) + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, 0, 0); + else + SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, primary, secondary); + } + void Sub_HeadOverlays_InItem() { auto& overlayIndex = Static_12; @@ -1143,35 +1152,27 @@ namespace sub if (currentOverlayValue < max_overlays) { currentOverlayValue++; - SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); - currentOverlayData.colour - 1; - currentOverlayData.colourSecondary = -1; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, 0, 0); } else { currentOverlayValue = currentOverlayValue == 255 ? 0 : 255; - SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); - currentOverlayData.colour - 1; - currentOverlayData.colourSecondary = -1; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, 0, 0); - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, currentOverlayData.colour=0, currentOverlayData.colourSecondary=0); + } + SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour = -1, currentOverlayData.colourSecondary = -1); } if (overlay_minus) { if (currentOverlayValue > 0) { currentOverlayValue = currentOverlayValue > max_overlays ? max_overlays : currentOverlayValue - 1; - SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, currentOverlayData.colour=0, currentOverlayData.colourSecondary=0); } else { currentOverlayValue = 255; - SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, 0, currentOverlayData.colour=0, currentOverlayData.colourSecondary=0); } + SET_PED_HEAD_OVERLAY(ped.Handle(), overlayIndex, currentOverlayValue, currentOverlayData.opacity); + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour = -1, currentOverlayData.colourSecondary = -1); } // OPACITY @@ -1196,27 +1197,27 @@ namespace sub if (bColoursAvailable) { bool colour_plus = 0, colour_minus = 0; - bool colourSecondary_plus = 0, colourSecondary_minus = 0, isColour = currentOverlayData.colour > -1; + bool colourSecondary_plus = 0, colourSecondary_minus = 0; // PRIMARY COLOUR AddNumber(Game::GetGXTEntry("CMOD_COL0_0", "Primary Colour"), currentOverlayData.colour, 0, null, colour_plus, colour_minus); if (colour_plus) { if (currentOverlayData.colour < max_colours) - { currentOverlayData.colour++; - isColour = currentOverlayData.colour > -1; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); - } + else + currentOverlayData.colour = -1; + + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); } if (colour_minus) { if (currentOverlayData.colour > -1) - { currentOverlayData.colour--; - isColour = currentOverlayData.colour > -1; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType*isColour, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); - } + else + currentOverlayData.colour = max_colours; + + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); } // SECONDARY COLOUR @@ -1225,23 +1226,17 @@ namespace sub if (colourSecondary_plus) { if (currentOverlayData.colourSecondary < max_colours) - { currentOverlayData.colourSecondary++; - isColour = currentOverlayData.colour > -1; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); - } + + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); } if (colourSecondary_minus) { if (currentOverlayData.colourSecondary > -1) - { currentOverlayData.colourSecondary--; - isColour = currentOverlayData.colour > -1; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour * isColour, currentOverlayData.colourSecondary * isColour); - } - } - Game::Print::PrintBottomCentre("overlayIndex = " + std::to_string(overlayIndex) + ", colourType = " + std::to_string(colourType) + ", currentOverlayData.colour = " + std::to_string(currentOverlayData.colour) + ", currentOverlayData.colourSecondary = " + std::to_string(currentOverlayData.colourSecondary)); + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); + } } } void Sub_FaceFeatures() diff --git a/Solution/source/Submenus/PedComponentChanger.h b/Solution/source/Submenus/PedComponentChanger.h index f99040fb..85eaf631 100644 --- a/Solution/source/Submenus/PedComponentChanger.h +++ b/Solution/source/Submenus/PedComponentChanger.h @@ -180,6 +180,7 @@ namespace sub void Sub_Main(); void Sub_HeadOverlays(); + void ApplyHeadOverlayTint(GTAped ped, int overlayIndex, int colourType, int primary, int secondary); void Sub_HeadOverlays_InItem(); void Sub_FaceFeatures(); void Sub_SkinTone(); From 85c574e6658eb07d2ca1196d8a9e837c10f34d78 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:33:46 +0400 Subject: [PATCH 33/49] Update macros.h --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 43b1db0c..5c22a466 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b2" +#define MENYOO_CURRENT_VER_ "2.2.0b3" #define GAME_PLAYERCOUNT 30 From c126ac5bc2cc1276964f56e0cecc887e0d2b18da Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Tue, 18 Nov 2025 23:18:26 +0400 Subject: [PATCH 34/49] Add resolution multiplier to Spooner Task Time --- .../Submenus/Spooner/Submenus_TaskSequence.cpp | 17 ++++++++++++----- Solution/source/macros.h | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp index a4221c9c..102aeeb8 100644 --- a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp +++ b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp @@ -1713,9 +1713,13 @@ namespace sub::Spooner } } } + + float durationmult = 1; + void Sub_TaskSequence_InTask() { - auto tskPtr = _selectedSTST; + auto tskPtr = _selectedSTST; + if (tskPtr == nullptr) { Menu::SetSub_previous(); @@ -1726,10 +1730,13 @@ namespace sub::Spooner auto& thisDuration = tskPtr->duration; if (thisDuration >= 0) // -1 for tasks with no settings. -2 for tasks with settings but no duration setting. { - bool bDuration_plus = false, bDuration_minus = false, bDuration_input = false; - AddNumber("Duration (In Seconds)", (float(thisDuration) / 1000), 1, bDuration_input, bDuration_plus, bDuration_minus); - if (bDuration_plus) { if (thisDuration < INT_MAX) thisDuration += 500; } - if (bDuration_minus) { if (thisDuration > 0) thisDuration -= 500; } + bool bDuration_plus = false, bDuration_minus = false, bDuration_input = false, bDurationMult_plus = false, bDurationMult_minus = false; + AddNumber("Duration (In Seconds)", (float(thisDuration) / 1000), 4, bDuration_input, bDuration_plus, bDuration_minus); + AddNumber("Duration Step Multiplier", durationmult, 4, null, bDurationMult_plus, bDurationMult_minus); + if (bDuration_plus) { if (thisDuration <= INT_MAX - 1000 * durationmult) thisDuration += 1000 * durationmult; } + if (bDuration_minus) { if (thisDuration >= 1000 * durationmult) thisDuration -= 1000 * durationmult; } + if (bDurationMult_plus) { if (durationmult < 1000.0f) durationmult = durationmult * 10.0f; } + if (bDurationMult_minus) { if (durationmult > 0.001f) durationmult = durationmult / 10.0f; } if (bDuration_input) { std::string oldDurationPreText = std::to_string(float(thisDuration - (thisDuration % 500)) / 1000); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 5c22a466..43bde7f2 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b3" +#define MENYOO_CURRENT_VER_ "2.2.0b4" #define GAME_PLAYERCOUNT 30 From 742ec44e7382334bd36d22425c2169f093d9621a Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 19 Nov 2025 07:54:45 +0400 Subject: [PATCH 35/49] Remove forced 500ms modulo of duration inputval (#370) * Remove forced 500ms modulo of duration inputval * up version for pre-release --- Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp | 2 +- Solution/source/macros.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp index 102aeeb8..3998a806 100644 --- a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp +++ b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp @@ -1757,7 +1757,7 @@ namespace sub::Spooner { inputVal = thisDuration; } - inputVal -= (inputVal % 500); + //inputVal -= (inputVal % 500); thisDuration = inputVal; } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::ST_Duration, std::string(), 7U, "Enter duration in seconds:", oldDurationPreText); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 43bde7f2..ccd63613 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b4" +#define MENYOO_CURRENT_VER_ "2.2.0b5" #define GAME_PLAYERCOUNT 30 From 347c57f29266730e5c3c487a7ed53bfb2012fe9e Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 20 Nov 2025 08:59:54 +0400 Subject: [PATCH 36/49] Fix minor task duration issues Copy Scroll Sensitivity Logic --- .../Spooner/Submenus_TaskSequence.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp index 3998a806..2520c86f 100644 --- a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp +++ b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp @@ -50,7 +50,7 @@ namespace sub::Spooner STSTask* _selectedSTST = nullptr; namespace Sub_TaskSequence - { + { void Nothing() { } @@ -1714,8 +1714,6 @@ namespace sub::Spooner } } - float durationmult = 1; - void Sub_TaskSequence_InTask() { auto tskPtr = _selectedSTST; @@ -1731,15 +1729,15 @@ namespace sub::Spooner if (thisDuration >= 0) // -1 for tasks with no settings. -2 for tasks with settings but no duration setting. { bool bDuration_plus = false, bDuration_minus = false, bDuration_input = false, bDurationMult_plus = false, bDurationMult_minus = false; - AddNumber("Duration (In Seconds)", (float(thisDuration) / 1000), 4, bDuration_input, bDuration_plus, bDuration_minus); - AddNumber("Duration Step Multiplier", durationmult, 4, null, bDurationMult_plus, bDurationMult_minus); - if (bDuration_plus) { if (thisDuration <= INT_MAX - 1000 * durationmult) thisDuration += 1000 * durationmult; } - if (bDuration_minus) { if (thisDuration >= 1000 * durationmult) thisDuration -= 1000 * durationmult; } - if (bDurationMult_plus) { if (durationmult < 1000.0f) durationmult = durationmult * 10.0f; } - if (bDurationMult_minus) { if (durationmult > 0.001f) durationmult = durationmult / 10.0f; } + AddNumber("Duration (In Seconds)", (float(thisDuration) / 1000), 3, bDuration_input, bDuration_plus, bDuration_minus); + AddNumber("Scroll Sensitivity", (float(_manualPlacementPrecision)), 3, null, prec_minus, prec_plus); + if (bDuration_plus) { if (thisDuration <= INT_MAX-_manualPlacementPrecision) thisDuration += _manualPlacementPrecision; } + if (bDuration_minus) { if (thisDuration > _manualPlacementPrecision) thisDuration -= _manualPlacementPrecision; } + if (prec_plus) { if (_manualPlacementPrecision < 10.0f) _manualPlacementPrecision *= 10; } + if (prec_minus) { if (_manualPlacementPrecision > 0.001f) _manualPlacementPrecision /= 10; } if (bDuration_input) { - std::string oldDurationPreText = std::to_string(float(thisDuration - (thisDuration % 500)) / 1000); + std::string oldDurationPreText = std::to_string(float(thisDuration) / 1000); oldDurationPreText = oldDurationPreText.substr(0, oldDurationPreText.find('.') + 2); std::string inputStr = Game::InputBox("", 7 + 1, "Enter duration in seconds:", oldDurationPreText); if (inputStr.length() > 0) @@ -1757,7 +1755,6 @@ namespace sub::Spooner { inputVal = thisDuration; } - //inputVal -= (inputVal % 500); thisDuration = inputVal; } //OnscreenKeyboard::State::Set(OnscreenKeyboard::Purpose::ST_Duration, std::string(), 7U, "Enter duration in seconds:", oldDurationPreText); From cb8c23e7244f1e19a8302b9f1a9843495a7c98f5 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 20 Nov 2025 09:07:12 +0400 Subject: [PATCH 37/49] Add missing bool declarations --- Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp index 2520c86f..b9f07c88 100644 --- a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp +++ b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp @@ -1728,7 +1728,7 @@ namespace sub::Spooner auto& thisDuration = tskPtr->duration; if (thisDuration >= 0) // -1 for tasks with no settings. -2 for tasks with settings but no duration setting. { - bool bDuration_plus = false, bDuration_minus = false, bDuration_input = false, bDurationMult_plus = false, bDurationMult_minus = false; + bool bDuration_plus = false, bDuration_minus = false, bDuration_input = false, bDurationMult_plus = false, bDurationMult_minus = false, prec_plus = 0, prec_minus = 0; AddNumber("Duration (In Seconds)", (float(thisDuration) / 1000), 3, bDuration_input, bDuration_plus, bDuration_minus); AddNumber("Scroll Sensitivity", (float(_manualPlacementPrecision)), 3, null, prec_minus, prec_plus); if (bDuration_plus) { if (thisDuration <= INT_MAX-_manualPlacementPrecision) thisDuration += _manualPlacementPrecision; } From 876105c5b3b9700ba26a9afbd6700a4dc3ef7398 Mon Sep 17 00:00:00 2001 From: ItsJustCurtis Date: Thu, 20 Nov 2025 20:59:47 +0400 Subject: [PATCH 38/49] Fix duration rounding error --- .../Spooner/Submenus_TaskSequence.cpp | 22 +++++++++++++++---- Solution/source/macros.h | 2 +- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp index b9f07c88..148ce0f8 100644 --- a/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp +++ b/Solution/source/Submenus/Spooner/Submenus_TaskSequence.cpp @@ -1731,10 +1731,24 @@ namespace sub::Spooner bool bDuration_plus = false, bDuration_minus = false, bDuration_input = false, bDurationMult_plus = false, bDurationMult_minus = false, prec_plus = 0, prec_minus = 0; AddNumber("Duration (In Seconds)", (float(thisDuration) / 1000), 3, bDuration_input, bDuration_plus, bDuration_minus); AddNumber("Scroll Sensitivity", (float(_manualPlacementPrecision)), 3, null, prec_minus, prec_plus); - if (bDuration_plus) { if (thisDuration <= INT_MAX-_manualPlacementPrecision) thisDuration += _manualPlacementPrecision; } - if (bDuration_minus) { if (thisDuration > _manualPlacementPrecision) thisDuration -= _manualPlacementPrecision; } - if (prec_plus) { if (_manualPlacementPrecision < 10.0f) _manualPlacementPrecision *= 10; } - if (prec_minus) { if (_manualPlacementPrecision > 0.001f) _manualPlacementPrecision /= 10; } + if (bDuration_plus) { + addlog(ige::LogType::LOG_TRACE, "Increasing duration by " + std::to_string(_manualPlacementPrecision * 1000) + " milliseconds. Target " + std::to_string(thisDuration + _manualPlacementPrecision * 1000), __FILENAME__); + if (thisDuration <= INT_MAX-_manualPlacementPrecision*1000) thisDuration += static_cast(_manualPlacementPrecision*1000); + addlog(ige::LogType::LOG_TRACE, "New duration is " + std::to_string(thisDuration) + " milliseconds.", __FILENAME__); + } + if (bDuration_minus) { + addlog(ige::LogType::LOG_TRACE, "Decreasinc duration by " + std::to_string(_manualPlacementPrecision * 1000) + " milliseconds. Target " + std::to_string(thisDuration - _manualPlacementPrecision * 1000), __FILENAME__); + if (thisDuration > _manualPlacementPrecision*1000) thisDuration -= static_cast(_manualPlacementPrecision*1000); + addlog(ige::LogType::LOG_TRACE, "New duration is " + std::to_string(thisDuration) + " milliseconds.", __FILENAME__); + } + if (prec_plus) { + addlog(ige::LogType::LOG_TRACE, "Increasing duration scroll sensitivity to " + std::to_string(_manualPlacementPrecision * 10) + " seconds.", __FILENAME__); + if (_manualPlacementPrecision < 10.0f) _manualPlacementPrecision *= 10; + } + if (prec_minus) { + addlog(ige::LogType::LOG_TRACE, "Decreasing duration scroll sensitivity to " + std::to_string(_manualPlacementPrecision / 10) + " seconds.", __FILENAME__); + if (_manualPlacementPrecision > 0.001f) _manualPlacementPrecision /= 10; + } if (bDuration_input) { std::string oldDurationPreText = std::to_string(float(thisDuration) / 1000); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index ccd63613..14c39883 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b5" +#define MENYOO_CURRENT_VER_ "2.2.0b6" #define GAME_PLAYERCOUNT 30 From 3f525cf4ea5d0905f571961abbaedad3af32c28e Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sat, 22 Nov 2025 20:17:22 +0400 Subject: [PATCH 39/49] Add function to unlock Head Shape Limits (#373) --- Solution/source/Menu/Routine.cpp | 3 +++ Solution/source/Menu/Routine.h | 3 +++ Solution/source/Submenus/PedComponentChanger.cpp | 9 ++++++++- Solution/source/Submenus/PedComponentChanger.h | 2 +- Solution/source/Submenus/Settings.cpp | 3 ++- Solution/source/macros.h | 2 +- 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index 8665cc88..20aaf50f 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -369,6 +369,9 @@ float g_lastFOVValue = 0.0f; DWORD g_lastHeightLockMessageTime = 0; const char* g_lastHeightLockMessage = nullptr; +bool g_unlockMaxIDs = 0; +UINT8 max_shapeAndSkinIDs = 46; + #pragma endregion #pragma region methods used define // p.s. this ain't it chief diff --git a/Solution/source/Menu/Routine.h b/Solution/source/Menu/Routine.h index 2b7abbf9..1c3f632a 100644 --- a/Solution/source/Menu/Routine.h +++ b/Solution/source/Menu/Routine.h @@ -140,6 +140,9 @@ extern bool bit_grav_gun_disabled; extern float forge_dist, _globalForgeGun_prec, _globalForgeGun_shootForce; extern bool ObjSpawn_forge_assistance; +extern bool g_unlockMaxIDs; +extern UINT8 max_shapeAndSkinIDs; + #pragma endregion #pragma region methods used declare // p.s. this ain't it chief diff --git a/Solution/source/Submenus/PedComponentChanger.cpp b/Solution/source/Submenus/PedComponentChanger.cpp index 35467c95..5c25617f 100644 --- a/Solution/source/Submenus/PedComponentChanger.cpp +++ b/Solution/source/Submenus/PedComponentChanger.cpp @@ -972,7 +972,8 @@ namespace sub }; #pragma endregion - UINT8 max_shapeAndSkinIDs = 46; + //bool unlockMaxIDs = false; + //UINT8 max_shapeAndSkinIDs = 46; UINT8 GetPedHeadOverlayColourType(const PedHeadOverlay& overlayIndex) { switch (overlayIndex) @@ -1281,6 +1282,12 @@ namespace sub float mix_amountToChange = 0.01f; AddTitle("Shape & Skin Tone"); + AddToggle("Unlock ID Limits", g_unlockMaxIDs); + + if (g_unlockMaxIDs) + max_shapeAndSkinIDs = 255; + else + max_shapeAndSkinIDs = 46; // Shape IDs bool shapeFirstID_plus = false, shapeFirstID_minus = false; diff --git a/Solution/source/Submenus/PedComponentChanger.h b/Solution/source/Submenus/PedComponentChanger.h index 85eaf631..729d604a 100644 --- a/Solution/source/Submenus/PedComponentChanger.h +++ b/Solution/source/Submenus/PedComponentChanger.h @@ -173,7 +173,7 @@ namespace sub extern const std::vector>> vCaptions_headOverlays; extern const std::vector vCaptions_facialFeatures; - extern UINT8 max_shapeAndSkinIDs; + //extern UINT8 max_shapeAndSkinIDs; UINT8 GetPedHeadOverlayColourType(const PedHeadOverlay& overlayIndex); bool DoesPedModelSupportHeadFeatures(const GTAmodel::Model& pedModel); void UpdatePedHeadBlendData(GTAped& ped, const PedHeadBlendData& blendData, bool bUnused); diff --git a/Solution/source/Submenus/Settings.cpp b/Solution/source/Submenus/Settings.cpp index d8e24547..484da518 100644 --- a/Solution/source/Submenus/Settings.cpp +++ b/Solution/source/Submenus/Settings.cpp @@ -42,7 +42,8 @@ namespace sub AddOption("Menu Colours", null, nullFunc, SUB::SETTINGS_COLOURS); AddOption("Menu Fonts", null, nullFunc, SUB::SETTINGS_FONTS); AddOption("Menu Position", null, nullFunc, SUB::SETTINGS_MENUPOS); - //AddToggle("Mouse Support (ALPHA)", Menu::bit_mouse); + // + // ("Mouse Support (ALPHA)", Menu::bit_mouse); AddToggle("Gradients", Menu::gradients); AddToggle("Titlebox Globe", Menu::bit_glare_test); AddToggle("Centre Title", Menu::bit_centre_title); diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 14c39883..7244e120 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b6" +#define MENYOO_CURRENT_VER_ "2.2.0b7" #define GAME_PLAYERCOUNT 30 From db4b9f5a01087f4d27d6ee1a4b50cf0cd691e0e6 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:38:29 +0400 Subject: [PATCH 40/49] Display fixes (#375) * Remove unsafe use of INFINITY as initialising value * Additional Logging * Improved Logs * Fix Menu Glitch when selecting Lower Suspension option * Fix List Flickering on Ped Selection Refactor Random Option Add logging * Remove Gen9 On-screen warning. * UpVersion for Pre-release --- Solution/source/Menu/Menu.cpp | 8 ++ Solution/source/Menu/Routine.cpp | 5 +- Solution/source/Submenus/PedModelChanger.cpp | 132 ++++++------------- Solution/source/Submenus/VehicleModShop.cpp | 16 +-- Solution/source/Submenus/VehicleSpawner.cpp | 2 +- Solution/source/macros.h | 3 +- 6 files changed, 64 insertions(+), 102 deletions(-) diff --git a/Solution/source/Menu/Menu.cpp b/Solution/source/Menu/Menu.cpp index ce5c128e..96b6d34c 100644 --- a/Solution/source/Menu/Menu.cpp +++ b/Solution/source/Menu/Menu.cpp @@ -532,13 +532,17 @@ void Menu::while_closed() justopened(); GTAmemory::InitEnhancedPools(); } + else + addlog(ige::LogType::LOG_TRACE, "Menu has been opened before, skipping initialization", __FILENAME__); Game::Sound::PlayFrontend("FocusIn", "HintCamSounds"); currentsub = LOOCsub; + addlog(ige::LogType::LOG_TRACE, "Setting current submenu to LOOCsub: " + std::to_string(LOOCsub), __FILENAME__); if (currentsub == SUB::MAINMENU) { + addlog(ige::LogType::LOG_TRACE, "Current is MainMenu", __FILENAME__); currentop = 1; *currentopATM = 1; } @@ -615,6 +619,7 @@ void Menu::Up(bool playSound) { currentop--; currentop_w_breaks--; + addlog(ige::LogType::LOG_TRACE, "Moved to option " + std::to_string(currentop), __FILENAME__); if (playSound) Game::Sound::PlayFrontend_default("NAV_UP_DOWN"); breakscroll = 1; @@ -623,6 +628,7 @@ void Menu::Down(bool playSound) { currentop++; currentop_w_breaks++; + addlog(ige::LogType::LOG_TRACE, "Moved to option " + std::to_string(currentop), __FILENAME__); if (playSound) Game::Sound::PlayFrontend_default("NAV_UP_DOWN"); breakscroll = 2; @@ -631,6 +637,7 @@ void Menu::Bottom(bool playSound) { currentop = totalop; currentop_w_breaks = totalop; + addlog(ige::LogType::LOG_TRACE, "Moved to option " + std::to_string(currentop), __FILENAME__); if (playSound) Game::Sound::PlayFrontend_default("NAV_UP_DOWN"); breakscroll = 1; @@ -639,6 +646,7 @@ void Menu::Top(bool playSound) { currentop = 1; currentop_w_breaks = 1; + addlog(ige::LogType::LOG_TRACE, "Moved to option " + std::to_string(currentop), __FILENAME__); if (playSound) Game::Sound::PlayFrontend_default("NAV_UP_DOWN"); breakscroll = 2; diff --git a/Solution/source/Menu/Routine.cpp b/Solution/source/Menu/Routine.cpp index 20aaf50f..1bcb5fd3 100644 --- a/Solution/source/Menu/Routine.cpp +++ b/Solution/source/Menu/Routine.cpp @@ -115,7 +115,8 @@ void Menu::justopened() IS_DLC_PRESENT(GET_HASH_KEY("mp2024_02_g9ec")) //this hardcoding needs to get in the bin. ) { - Game::Print::PrintBottomCentre("~r~Warning~s~: 9th Gen content detected, Game may crash. Read Menyoolog for fix instructions."); + //Game::Print::PrintBottomCentre("~r~Warning~s~: 9th Gen content detected, Game may crash. Read Menyoolog for fix instructions."); + //Rockstar seems to have fixed the invalid content crash in legacy, removing the on-screen warning, but will keep the log warning. ige::myLog << ige::LogType::LOG_WARNING << "Gen9 Content found in dlcpacks, this can cause instability when attempted to be loaded by Menyoo." << std::endl << " You can find these in your dlclist.xml by searching for \"g9\" and removing these lines or using a comment." << std::endl << " For example: " << std::endl << std::endl @@ -136,7 +137,7 @@ void Menu::justopened() IS_DLC_PRESENT(GET_HASH_KEY("mp2024_02")) //f*cking rockstar cocked up some clothes, this warning is the only protection. ) { - Game::Print::PrintBottomCentre("~r~Warning~s~: DLCPack mp2024_02 present, Game may crash. Read Menyoolog for fix instructions."); + //Game::Print::PrintBottomCentre("~r~Warning~s~: DLCPack mp2024_02 present, Game may crash. Read Menyoolog for fix instructions."); ige::myLog << ige::LogType::LOG_WARNING << "mp2024_02 found in dlcpacks, certain bugged clothing can cause instability when attempted to be loaded by Menyoo." << std::endl << " You can find this in your dlclist.xml by searching for \"mp2024_02\" and removing these lines or using a comment." << std::endl << " For example: " << std::endl << std::endl diff --git a/Solution/source/Submenus/PedModelChanger.cpp b/Solution/source/Submenus/PedModelChanger.cpp index 13993e0a..2f7a426f 100644 --- a/Solution/source/Submenus/PedModelChanger.cpp +++ b/Solution/source/Submenus/PedModelChanger.cpp @@ -315,6 +315,7 @@ namespace sub { PTFX::trigger_ptfx_1("scr_solomon3", "scr_trev4_747_blood_impact", 0, ped.GetOffsetInWorldCoords(0.37, -0.32f, -1.32f), Vector3(90.0f, 0, 0), 0.7f); ChangeModel_(model); + addlog(ige::LogType::LOG_TRACE, "Changed model to: " + text, __FILENAME__); } } void AddmodelOption_(const std::string& text, const GTAmodel::Model& model, bool* extra_option_code, int tickTrue) @@ -339,6 +340,8 @@ namespace sub } } + std::pair rngped; + void ModelChanger_() { addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger", __FILENAME__); @@ -347,6 +350,7 @@ namespace sub // ModelChangerVariationWarning_ = 0, // ModelChangerSlendy_ = 0, // ModelChanger_Animal = 0; + rngped = { "", "" }; Static_241 = PLAYER_PED_ID(); AddTitle("Model Changer"); @@ -404,16 +408,22 @@ namespace sub } + + + GTAmodel::Model ModelChanger_Random(std::vector> pedModels) + { + addlog(ige::LogType::LOG_TRACE, "Getting Random Ped Model", __FILENAME__); + rngped = pedModels[std::rand() % pedModels.size()]; + addlog(ige::LogType::LOG_TRACE, "Got Random Ped Model: " + rngped.first + ", " + rngped.second, __FILENAME__); + return rngped.first; + } + // I would really like this whole section to be refactored into one function - IJC void ModelChanger_Player() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Player", __FILENAME__); AddTitle("Player"); - std::pair rngped; - do { - rngped = g_pedModels_Player[std::rand() % g_pedModels_Player.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_Player); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_Player) { AddmodelOption_(pmn.second, (pmn.first)); @@ -421,13 +431,9 @@ namespace sub } void ModelChanger_Animal() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Animal", __FILENAME__); AddTitle("Animals"); - std::pair rngped; - do { - rngped = g_pedModels_Animal[std::rand() % g_pedModels_Animal.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_Animal); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_Animal) { AddmodelOption_(pmn.second, (pmn.first)); @@ -435,19 +441,9 @@ namespace sub } void ModelChanger_AmbientFemale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_AmbientFemale", __FILENAME__); AddTitle("Ambient Females"); - addlog(ige::LogType::LOG_TRACE, "Creating rngped variable", __FILENAME__); - std::pair rngped; - addlog(ige::LogType::LOG_TRACE, "Getting Ped Model options", __FILENAME__); - do { - addlog(ige::LogType::LOG_TRACE, "Starting Loop", __FILENAME__); - rngped = g_pedModels_AmbientFemale[std::rand() % g_pedModels_AmbientFemale.size()]; - addlog(ige::LogType::LOG_TRACE, "Got rngped: " + rngped.first + ", " + rngped.second, __FILENAME__); - } while (rngped.first == Game::PlayerPed().Model()); - addlog(ige::LogType::LOG_TRACE, "Creating Random Option", __FILENAME__); - AddmodelOption_("Random", (rngped.first), nullptr, 0); - addlog(ige::LogType::LOG_TRACE, "Creating Ped Model options", __FILENAME__); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_AmbientFemale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_AmbientFemale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -455,13 +451,9 @@ namespace sub } void ModelChanger_AmbientMale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_AmbientMale", __FILENAME__); AddTitle("Ambient Males"); - std::pair rngped; - do { - rngped = g_pedModels_AmbientMale[std::rand() % g_pedModels_AmbientMale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_AmbientMale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_AmbientMale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -469,13 +461,9 @@ namespace sub } void ModelChanger_Cutscene() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Cutscene", __FILENAME__); AddTitle("Cutscene Models"); - std::pair rngped; - do { - rngped = g_pedModels_Cutscene[std::rand() % g_pedModels_Cutscene.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_Cutscene); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_Cutscene) { AddmodelOption_(pmn.second, (pmn.first)); @@ -483,13 +471,9 @@ namespace sub } void ModelChanger_GangFemale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_GangFemale", __FILENAME__); AddTitle("Gang Females"); - std::pair rngped; - do { - rngped = g_pedModels_GangFemale[std::rand() % g_pedModels_GangFemale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_GangFemale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_GangFemale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -497,13 +481,9 @@ namespace sub } void ModelChanger_GangMale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_GangMale", __FILENAME__); AddTitle("Gang Males"); - std::pair rngped; - do { - rngped = g_pedModels_GangMale[std::rand() % g_pedModels_GangMale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_GangMale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_GangMale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -511,13 +491,9 @@ namespace sub } void ModelChanger_Story() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Story", __FILENAME__); AddTitle("Story Models"); - std::pair rngped; - do { - rngped = g_pedModels_Story[std::rand() % g_pedModels_Story.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_Story); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_Story) { AddmodelOption_(pmn.second, (pmn.first)); @@ -525,13 +501,9 @@ namespace sub } void ModelChanger_Multiplayer() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Multiplayer", __FILENAME__); AddTitle("Multiplayer Models"); - std::pair rngped; - do { - rngped = g_pedModels_Multiplayer[std::rand() % g_pedModels_Multiplayer.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_Multiplayer); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_Multiplayer) { AddmodelOption_(pmn.second, (pmn.first)); @@ -539,13 +511,9 @@ namespace sub } void ModelChanger_ScenarioFemale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_ScenarioFemale", __FILENAME__); AddTitle("Scenario Females"); - std::pair rngped; - do { - rngped = g_pedModels_ScenarioFemale[std::rand() % g_pedModels_ScenarioFemale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_ScenarioFemale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_ScenarioFemale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -553,13 +521,9 @@ namespace sub } void ModelChanger_ScenarioMale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_ScenarioMale", __FILENAME__); AddTitle("Scenario Males"); - std::pair rngped; - do { - rngped = g_pedModels_ScenarioMale[std::rand() % g_pedModels_ScenarioMale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_ScenarioMale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_ScenarioMale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -567,13 +531,9 @@ namespace sub } void ModelChanger_Story_ScenarioFemale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Story_ScenarioFemale", __FILENAME__); AddTitle("Story Scenario Females"); - std::pair rngped; - do { - rngped = g_pedModels_StoryScenarioFemale[std::rand() % g_pedModels_StoryScenarioFemale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_StoryScenarioFemale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_StoryScenarioFemale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -581,13 +541,9 @@ namespace sub } void ModelChanger_Story_ScenarioMale() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Story_ScenarioMale", __FILENAME__); AddTitle("Story Scenario Males"); - std::pair rngped; - do { - rngped = g_pedModels_StoryScenarioMale[std::rand() % g_pedModels_StoryScenarioMale.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_StoryScenarioMale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_StoryScenarioMale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -595,13 +551,9 @@ namespace sub } void ModelChanger_Others() { - addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger_Others", __FILENAME__); AddTitle("Others"); - std::pair rngped; - do { - rngped = g_pedModels_Others[std::rand() % g_pedModels_Others.size()]; - } while (rngped.first == Game::PlayerPed().Model()); - AddmodelOption_("Random", (rngped.first), nullptr, 0); + if (rngped.first == Game::PlayerPed().Model() || rngped.first == "") ModelChanger_Random(g_pedModels_Others); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_Others) { AddmodelOption_(pmn.second, (pmn.first)); diff --git a/Solution/source/Submenus/VehicleModShop.cpp b/Solution/source/Submenus/VehicleModShop.cpp index f66eccd3..78cb4bd6 100644 --- a/Solution/source/Submenus/VehicleModShop.cpp +++ b/Solution/source/Submenus/VehicleModShop.cpp @@ -1874,14 +1874,7 @@ namespace sub AddNumber(Game::GetGXTEntry("Roof Livery", "Roof Livery"), ms_livery2, 0, null, ms_livery2_plus, ms_livery2_minus); AddLocal(Game::GetGXTEntry("CMOD_MOD_TUR", "Turbo"), IS_TOGGLE_MOD_ON(Static_12, VehicleMod::Turbo), ms_turbo_toggle, ms_turbo_toggle); // Turbo AddLocal(Game::GetGXTEntry("CMOD_LGT_1", "Xenon Lights"), IS_TOGGLE_MOD_ON(Static_12, VehicleMod::XenonHeadlights), ms_lights_toggle, ms_lights_toggle); // Xenon lights - AddLocal("Lower Suspension", lowersuspension, MSLowerSuspension_, MSLowerSuspension_, true); // Tuners Lower Suspension - - if (MSLowerSuspension_) { - vehicle.RequestControlOnce(); - lowersuspension = !lowersuspension; - SET_REDUCED_SUSPENSION_FORCE(Static_12, lowersuspension); - return; - } + AddLocal("Lower Suspension", lowersuspension, MSLowerSuspension_, MSLowerSuspension_); // Tuners Lower Suspension if (GTAmemory::GetGameVersion() >= eGameVersion::VER_1_0_1604_0_STEAM && vehicle.IsToggleModOn(VehicleMod::XenonHeadlights)) { // Xenon Headlight Colours @@ -2158,6 +2151,13 @@ namespace sub return; } + if (MSLowerSuspension_) { + vehicle.RequestControlOnce(); + lowersuspension = !lowersuspension; + SET_REDUCED_SUSPENSION_FORCE(Static_12, lowersuspension); + return; + } + if (SubMS_Extra) { for (i = 0; i <= 12; i++) if (DOES_EXTRA_EXIST(Static_12, i)) { Menu::SetSub_new(SUB::MSEXTRA); break; } diff --git a/Solution/source/Submenus/VehicleSpawner.cpp b/Solution/source/Submenus/VehicleSpawner.cpp index 0da05266..90cc29a8 100644 --- a/Solution/source/Submenus/VehicleSpawner.cpp +++ b/Solution/source/Submenus/VehicleSpawner.cpp @@ -2330,7 +2330,7 @@ namespace sub {"2019367074", {"pink", 352}}, }; - float minDiff = INFINITY; + float minDiff = static_cast(INT_MAX); std::string nearestColour; std::string nearestAudio; for (const auto& colour : ColourNames) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 7244e120..c3e9ed9c 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,8 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0b7" +#define MENYOO_CURRENT_VER_ "2.2.0rc" + #define GAME_PLAYERCOUNT 30 From 98f8e58e941bd39a54d50f87453ec470283d7737 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sun, 23 Nov 2025 13:46:46 +0400 Subject: [PATCH 41/49] UpVersion for Automatic Pre-release --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index c3e9ed9c..46baaa1e 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0rc" +#define MENYOO_CURRENT_VER_ "2.2.0rc1" #define GAME_PLAYERCOUNT 30 From 2cc9deedd83800d055f9a526439b0d163803926d Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Mon, 24 Nov 2025 11:37:50 +0400 Subject: [PATCH 42/49] Release prep (#376) * Revise README with new images and GTA V version info * Update current version to 2.2.0 --- README.md | 7 ++++--- Solution/source/macros.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8f433ada..b4ae1cf5 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub latest release](https://img.shields.io/github/downloads/itsjustcurtis/MenyooSP/latest/total?label=Latest%20Downloads&logo=GitHub)](https://github.com/itsjustcurtis/MenyooSP/releases/latest) [![GitHub all releases](https://img.shields.io/github/downloads/itsjustcurtis/MenyooSP/total?label=Total%20Downloads&logo=GitHub)](https://github.com/itsjustcurtis/MenyooSP/releases) -![image](https://github.com/itsjustcurtis/MenyooSP/assets/70447190/38f28c30-5585-4f77-b204-6a8c8149defe) +banner_FINALB # Menyoo PC - [DOWNLOAD LATEST RELEASE](https://github.com/itsjustcurtis/MenyooSP/releases/latest/download/MenyooSP.zip) @@ -13,17 +13,18 @@ --- ## Community + - [Discord](https://discord.gg/v29AwqAemT) ## Requirements - [OpenIV and its ASI Loader](https://openiv.com/) - [ScriptHookV by Alexander Blade](http://www.dev-c.com/gtav/scripthookv/) - [Battleye disabled in the Rockstar Launcher Settings](https://staticg.sportskeeda.com/editor/2024/11/bdc35-17305620610616-1920.jpg) -- GTA V Version 3095.0 or newer. +- GTA V Legacy Version 3095.0 or newer OR GTA V Enhanced ## Build Visual Studio 2022 required -- I used v17.0.4 +- I used v17.14.19 ## Install Copy the Menyoo.asi file along with the menyooStuff folder to the Grand Theft Auto V game directory. diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 46baaa1e..eda49a8a 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0rc1" +#define MENYOO_CURRENT_VER_ "2.2.0" #define GAME_PLAYERCOUNT 30 From cf143b271b73f420e10d5825dbd48d3f1d1664c3 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 10 Dec 2025 18:28:39 +0400 Subject: [PATCH 43/49] Update FX_ASI_BUILD version in Menyoo.rc --- Solution/source/Menyoo.rc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Solution/source/Menyoo.rc b/Solution/source/Menyoo.rc index 2bf4b1d0..8b9e9ee6 100644 --- a/Solution/source/Menyoo.rc +++ b/Solution/source/Menyoo.rc @@ -121,4 +121,9 @@ END FX_ASI_BUILD 3586 BEGIN "\0" -END \ No newline at end of file +END + +FX_ASI_BUILD 3717 +BEGIN +"\0" +END From 45cb6c64ee3ac4f80e0b23217b8c5e55d4e89ab3 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 10 Dec 2025 18:30:28 +0400 Subject: [PATCH 44/49] Add new version constants to main.h --- Solution/source/main.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Solution/source/main.h b/Solution/source/main.h index 42ea83d3..f2d9fc2e 100644 --- a/Solution/source/main.h +++ b/Solution/source/main.h @@ -293,6 +293,8 @@ enum eGameVersion : int VER_1_0_3586_0, + VER_1_0_3717_0, + VER_1_0_811_8 = 1001, VER_1_0_812_8 = 1002, @@ -304,6 +306,8 @@ enum eGameVersion : int VER_1_0_889_15 = 1005, VER_1_0_889_19 = 1006, + + VER_1_0_1013_17 = 1007, VER_SIZE, VER_UNK = -1 From d069964b722e509e994883182ff05531b80567e7 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Wed, 10 Dec 2025 18:30:58 +0400 Subject: [PATCH 45/49] Update MENYOO_CURRENT_VER_ to 2.2.1a1 --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index eda49a8a..377f38e1 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.0" +#define MENYOO_CURRENT_VER_ "2.2.1a1" #define GAME_PLAYERCOUNT 30 From 44a35059df58f0762e19a70183ae7bb54ebeefa0 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 11 Dec 2025 21:17:33 +0400 Subject: [PATCH 46/49] Add aged version of Michael to PedList.xml --- Solution/source/_Build/bin/Release/menyooStuff/PedList.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/Solution/source/_Build/bin/Release/menyooStuff/PedList.xml b/Solution/source/_Build/bin/Release/menyooStuff/PedList.xml index de9e6e2d..7cc894da 100644 --- a/Solution/source/_Build/bin/Release/menyooStuff/PedList.xml +++ b/Solution/source/_Build/bin/Release/menyooStuff/PedList.xml @@ -2,6 +2,7 @@ + From 54dd3e975c4504813ea904b720d09372d72d59ff Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 11 Dec 2025 21:18:00 +0400 Subject: [PATCH 47/49] Update MENYOO_CURRENT_VER_ to 2.2.1a2 --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index 377f38e1..c84aa312 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.1a1" +#define MENYOO_CURRENT_VER_ "2.2.1a2" #define GAME_PLAYERCOUNT 30 From f16d7b3a589de58cd3c5060493ae40ea6f2dee24 Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Thu, 18 Dec 2025 20:04:28 +0400 Subject: [PATCH 48/49] Fix LSC Crash (#398) * Remove unnecessary patch that causes random crashes near LSC (#397) * Remove unnecessary patches that cause the game to crash on version 1.0.3717.0 / 1.0.1013.17 or newer * Reverted the first patch, as only the second causes crashes. * Update MENYOO_CURRENT_VER_ to version 2.2.1a3 --------- Co-authored-by: Chiheb --- Solution/source/Memory/GTAmemory.cpp | 13 ------------- Solution/source/macros.h | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Solution/source/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index 0e093337..1cc2eed3 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -1492,8 +1492,6 @@ void GTAmemory::Init() _gamePlayCameraAddr = reinterpret_cast(*reinterpret_cast(address + 3) + address + 7); } - - // Bypass model requests block if (g_isEnhanced) { address = MemryScan::PatternScanner::FindPattern("44 0f b6 b4 24 ? ? ? ? 41 20 f6"); @@ -1505,17 +1503,6 @@ void GTAmemory::Init() if (address) memset(reinterpret_cast(address - 24), 0x90, 24); } - // Bypass is player model allowed to spawn checks - if (g_isEnhanced) { - address = MemryScan::PatternScanner::FindPattern("74 ? e8 ? ? ? ? 48 8b b0"); - if (address) memset(reinterpret_cast(address + 28), 0x90, 6); - } - else { - // new pattern that lands outside of the patched bytes, to ensure compatibility with other mods that patch them. - address = MemryScan::PatternScanner::FindPattern("40 53 48 83 ec ? e8 ? ? ? ? 48 8b d8 48 85 c0 74 ? 48 8b 10 48 8b c8 ff 52"); - if (address) memset(reinterpret_cast(address + 28), 0x90, 4); - } - //GetModelInfo if (g_isEnhanced) { diff --git a/Solution/source/macros.h b/Solution/source/macros.h index c84aa312..f902aa4b 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.1a2" +#define MENYOO_CURRENT_VER_ "2.2.1a3" #define GAME_PLAYERCOUNT 30 From fb88f397f881f88ffcd2d6e0e1faf450ea2e313a Mon Sep 17 00:00:00 2001 From: itsjustcurtis <70447190+itsjustcurtis@users.noreply.github.com> Date: Sat, 20 Dec 2025 10:00:07 +0400 Subject: [PATCH 49/49] Update MENYOO_CURRENT_VER_ to version 2.2.1 --- Solution/source/macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Solution/source/macros.h b/Solution/source/macros.h index f902aa4b..4fe389b4 100644 --- a/Solution/source/macros.h +++ b/Solution/source/macros.h @@ -16,7 +16,7 @@ #define _CRT_SECURE_NO_WARNINGS -#define MENYOO_CURRENT_VER_ "2.2.1a3" +#define MENYOO_CURRENT_VER_ "2.2.1" #define GAME_PLAYERCOUNT 30