diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..d9446e56 --- /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://paypal.me/curtisre # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 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. diff --git a/.github/workflows/master_build.yml b/.github/workflows/master_build.yml index 207a24a9..69ad6c86 100644 --- a/.github/workflows/master_build.yml +++ b/.github/workflows/master_build.yml @@ -108,11 +108,9 @@ jobs: - name: Set output id: set_output - if: env.CANCELJOB != 'true' 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 @@ -152,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" @@ -196,4 +195,3 @@ jobs: prerelease: ${{ github.ref_name != 'main' }} title: ${{ steps.version.outputs.version}} files: MenyooSP.zip - dry-run: true 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/Memory/GTAmemory.cpp b/Solution/source/Memory/GTAmemory.cpp index 132fa7d7..0e093337 100644 --- a/Solution/source/Memory/GTAmemory.cpp +++ b/Solution/source/Memory/GTAmemory.cpp @@ -46,25 +46,47 @@ 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_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_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. +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 InitVehicleArchetypeEnhanced 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_InitVehicleArchetype = 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() { @@ -72,6 +94,10 @@ void removeHooks() { delete g_InitVehicleArchetype; g_InitVehicleArchetype = nullptr; } + if (g_InitVehicleArchetypeEnhanced) { + delete g_InitVehicleArchetypeEnhanced; + g_InitVehicleArchetypeEnhanced = nullptr; + } } template R GetMultilayerPointer(void* base, const std::vector& offsets) { @@ -159,6 +185,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 +194,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 +234,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 +317,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 +527,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 +595,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 +663,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 +714,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 false; + } + for (int hash : _modelHashes) { - return true; + if (*reinterpret_cast(v5 + 24) == hash) + { + return true; + } } + return false; } - return false; } return true; @@ -608,27 +753,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++) { - UINT64 address = vehiclePool->getAddress(i); - if (address && CheckEntity(address)) + //if (entityPoolEnhanced->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)); + } + } + } + } + else { + VehiclePool* vehiclePool = *reinterpret_cast(*GTAmemory::_vehiclePoolAddress); + + for (UINT32 i = 0; i < vehiclePool->size; i++) + { + //if (entityPool->Full()) break; + if (vehiclePool->isValid(i)) + { + UINT64 address = vehiclePool->getAddress(i); + if (address && CheckEntity(address)) + { + _handles.push_back(GTAmemory::_addEntityToPoolFunc(address)); + } } } } @@ -636,39 +818,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 +901,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,161 +973,769 @@ 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); + } + + 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); + } + + + + // 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); } - UINT64 GetResult() - { - return _res; + // 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); } -private: - func _toRun; - UINT64 _arg; - UINT64 _res; -}; + //GetModelInfo -void GTAmemory::Init() -{ - UINT64 address; + if (g_isEnhanced) { + address = MemryScan::PatternScanner::FindPattern("45 85 d2 74 ? 49 89 d0 4c 8b 1d"); - // 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 (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\x8D\x05\x00\x00\x00\x00\x0F\xB7\xC1", "xxx????xxx"); - if (address) _blipList = 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); + } - 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; + _SpSnow = SpSnow(); + addlog(ige::LogType::LOG_INIT, "GTAMemory Init Done", __FILENAME__); +} - 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); +void GTAmemory::InitEnhancedPools() { + if (g_isEnhanced) { - 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); + // 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. - 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); - } - - 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); + 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; + } - // Bypass model requests block - address = MemryScan::PatternScanner::FindPattern("48 85 C0 0F 84 ? ? ? ? 8B 48 50"); - if (address) memset(reinterpret_cast(address), 0x90, 24); + } - // 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); + 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; + } + } - //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__); + 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; + } } - } - 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("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; - } - GetModelInfo = (GetModelInfo_t)(address); - - _SpSnow = SpSnow(); + addlog(ige::LogType::LOG_TRACE, "Found Pattern: " + std::to_string(address), __FILENAME__); + GetModelInfo = (GetModelInfo_t)(address); + + _SpSnow = SpSnow(); + } } + + Vector3 GTAmemory::ReadVector3(UINT64 address) { const float* data = (float*)address; @@ -896,52 +1758,85 @@ struct HashNode }; void GTAmemory::GenerateVehicleModelList() { + addlog(ige::LogType::LOG_DEBUG, "Generating Vehicle Model List. isEnhanced = " + std::to_string(g_isEnhanced), __FILENAME__); + + int classOffset; + uintptr_t address; + HashNode** HashMap; //Zorg - uintptr_t address = FindPattern("\x66\x81\xF9\x00\x00\x74\x10\x4D\x85\xC0", "xxx??xxxxx"); - if (address) + 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"); + 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) { + 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; + //int classOffset = *reinterpret_cast(address + 0x10); + 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); + } + } + + 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++) { - 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); - //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); } } } } } } + addlog(ige::LogType::LOG_TRACE, "Exiting GenerateVehicleModelList()", __FILENAME__); } + bool GTAmemory::IsModelAPed(unsigned int modelHash) { HashNode** HashMap = reinterpret_cast(modelHashTable); @@ -989,20 +1884,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 +1927,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 +1946,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 +1996,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 +2051,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 +2209,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 +2269,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 +2287,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 +2324,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 +2336,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 +2380,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 +2457,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 +2499,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 +2620,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 +2713,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 +2764,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,50 +2778,49 @@ 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})); - } - return 1.0f; + if (baddr) return *(GetMultilayerPointer(baddr, std::vector{0x8, 0x88})); } void GeneralGlobalHax::SetPlayerHeight(float value) { 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}. + 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 +2839,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 +2880,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,19 +2913,24 @@ 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; } 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/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/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/Menu/Menu.cpp b/Solution/source/Menu/Menu.cpp index d57ac70b..96b6d34c 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,13 +526,23 @@ void Menu::while_closed() { if (isBinds()) { - if (g_menuNotOpenedYet) + + addlog(ige::LogType::LOG_TRACE, "Binds Pressed, opening Menyoo", __FILENAME__); + if (g_menuNotOpenedYet) { 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; } @@ -547,7 +557,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 +580,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 +590,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 +600,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,14 +610,16 @@ 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) { 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; @@ -610,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; @@ -618,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; @@ -626,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; @@ -640,7 +661,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 +868,28 @@ void Menu::draw_IB() void Menu::sub_handler() { + static bool firstRun = true, isClosed = true; + if(firstRun) + { + addlog(ige::LogType::LOG_TRACE, "First Run sub_handler", __FILENAME__);; + } if (currentsub == SUB::CLOSED) { + if (!isClosed) + { + addlog(ige::LogType::LOG_TRACE, "Sub Closed", __FILENAME__);; + isClosed = true; + } while_closed(); } else { + 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); } @@ -877,7 +913,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 a8796eeb..ca67d6b1 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); @@ -54,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__); } } @@ -307,6 +323,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 +583,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..1bcb5fd3 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 * @@ -99,50 +99,52 @@ 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."); + //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 + << " 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 +153,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 +185,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 +265,7 @@ void TickRainbowFader() colour.R++; colour.B--; } + firstTick = false; g_FaderTick = GetTickCount(); } @@ -321,6 +362,17 @@ 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; + +bool g_unlockMaxIDs = 0; +UINT8 max_shapeAndSkinIDs = 46; + #pragma endregion #pragma region methods used define // p.s. this ain't it chief @@ -374,13 +426,11 @@ 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); - /*INT i, offsettedID, count = 80; Ped *peds = new Ped[count * 2 + 2]; @@ -415,7 +465,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++) @@ -438,7 +488,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++) @@ -1254,7 +1304,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) { @@ -1514,6 +1564,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 +1652,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 +1701,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 +1856,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 +2435,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 { @@ -2646,11 +2836,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())) { @@ -2704,6 +2894,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) @@ -2736,7 +2928,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); @@ -2756,7 +2948,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); } @@ -2830,11 +3022,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(); @@ -2928,7 +3121,7 @@ void Menu::loops() if (_JumpAroundMode_::bEnabled) _JumpAroundMode_::Tick(); } - + if (loop_player_Walkunderwater) Set_Walkunderwater(PLAYER_PED_ID()); @@ -3130,7 +3323,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/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/Menyoo.rc b/Solution/source/Menyoo.rc index d3c848fe..2bf4b1d0 100644 --- a/Solution/source/Menyoo.rc +++ b/Solution/source/Menyoo.rc @@ -108,7 +108,17 @@ BEGIN "\0" END +FX_ASI_BUILD 3521 +BEGIN +"\0" +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 71617a9c..a7d12d0d 100644 --- a/Solution/source/Menyoo.vcxproj +++ b/Solution/source/Menyoo.vcxproj @@ -247,7 +247,7 @@ DynamicLibrary true - v141 + v143 Unicode @@ -328,4 +328,4 @@ - \ No newline at end of file + 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/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 d680f90a..5cf68e15 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; @@ -120,7 +121,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) @@ -159,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(); @@ -188,6 +221,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 @@ -200,26 +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; for (int d = 0x0; d < 0x20; d++) { for (auto& dd : hashes[d]) { + 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 (!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); } @@ -286,9 +330,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/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" }, diff --git a/Solution/source/Scripting/World.cpp b/Solution/source/Scripting/World.cpp index 5b388003..c5ef4550 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; @@ -646,12 +646,14 @@ namespace World { PCHAR dict = 0; PCHAR name = 0; + float zOffset = 0.0f; + if (type == 1 || type == 43) zOffset = -0.7f; 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) @@ -687,7 +689,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 +763,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 +821,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 +867,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/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..5c25617f 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: @@ -282,10 +305,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) @@ -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); } } } @@ -931,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) @@ -1077,6 +1119,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; @@ -1102,30 +1153,27 @@ namespace sub if (currentOverlayValue < max_overlays) { 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); } else { currentOverlayValue = currentOverlayValue == 255 ? 0 : 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); } 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 @@ -1157,39 +1205,39 @@ namespace sub if (colour_plus) { if (currentOverlayData.colour < max_colours) - { currentOverlayData.colour++; - SET_PED_HEAD_OVERLAY_TINT(ped.Handle(), overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); - } + else + currentOverlayData.colour = -1; + + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); } 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); - } + else + currentOverlayData.colour = max_colours; + + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); } // 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); - } + + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); } 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); - } - } + ApplyHeadOverlayTint(ped, overlayIndex, colourType, currentOverlayData.colour, currentOverlayData.colourSecondary); + } } } void Sub_FaceFeatures() @@ -1234,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; @@ -1468,7 +1522,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) @@ -1650,7 +1711,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 +1735,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 +1814,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/PedComponentChanger.h b/Solution/source/Submenus/PedComponentChanger.h index ab17fe1a..729d604a 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 @@ -173,13 +173,14 @@ 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); 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(); diff --git a/Solution/source/Submenus/PedModelChanger.cpp b/Solution/source/Submenus/PedModelChanger.cpp index 37e5acad..2f7a426f 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" @@ -170,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):"); } @@ -314,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) @@ -338,13 +340,17 @@ namespace sub } } + std::pair rngped; + void ModelChanger_() { + addlog(ige::LogType::LOG_TRACE, "Entering ModelChanger", __FILENAME__); bool ModelChangerRandomPedVariation_ = 0, ModelChangerInput_ = 0; // ModelChangerVariationWarning_ = 0, // ModelChangerSlendy_ = 0, // ModelChanger_Animal = 0; + rngped = { "", "" }; Static_241 = PLAYER_PED_ID(); AddTitle("Model Changer"); @@ -366,8 +372,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; @@ -381,7 +388,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):"); @@ -401,15 +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() { 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)); @@ -418,11 +432,8 @@ namespace sub void ModelChanger_Animal() { 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)); @@ -431,11 +442,8 @@ namespace sub void ModelChanger_AmbientFemale() { AddTitle("Ambient Females"); - std::pair rngped; - do { - rngped = g_pedModels_AmbientFemale[std::rand() % g_pedModels_AmbientFemale.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_AmbientFemale); + AddmodelOption_("Random", rngped.first, nullptr, 0); for (auto& pmn : g_pedModels_AmbientFemale) { AddmodelOption_(pmn.second, (pmn.first)); @@ -444,11 +452,8 @@ namespace sub void ModelChanger_AmbientMale() { 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)); @@ -457,11 +462,8 @@ namespace sub void ModelChanger_Cutscene() { 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)); @@ -470,11 +472,8 @@ namespace sub void ModelChanger_GangFemale() { 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)); @@ -483,11 +482,8 @@ namespace sub void ModelChanger_GangMale() { 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)); @@ -496,11 +492,8 @@ namespace sub void ModelChanger_Story() { 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)); @@ -509,11 +502,8 @@ namespace sub void ModelChanger_Multiplayer() { 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)); @@ -522,11 +512,8 @@ namespace sub void ModelChanger_ScenarioFemale() { 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)); @@ -535,11 +522,8 @@ namespace sub void ModelChanger_ScenarioMale() { 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)); @@ -548,11 +532,8 @@ namespace sub void ModelChanger_Story_ScenarioFemale() { 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)); @@ -561,11 +542,8 @@ namespace sub void ModelChanger_Story_ScenarioMale() { 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)); @@ -574,11 +552,8 @@ namespace sub void ModelChanger_Others() { 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/PlayerOptions.cpp b/Solution/source/Submenus/PlayerOptions.cpp index 73ad3656..eb58e8f2 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; @@ -139,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); @@ -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; @@ -352,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..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); @@ -160,8 +161,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 +236,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/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); 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..148ce0f8 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() { } @@ -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); @@ -1713,9 +1713,11 @@ namespace sub::Spooner } } } + void Sub_TaskSequence_InTask() { - auto tskPtr = _selectedSTST; + auto tskPtr = _selectedSTST; + if (tskPtr == nullptr) { Menu::SetSub_previous(); @@ -1726,13 +1728,30 @@ 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, 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) { + 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 - (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) @@ -1750,7 +1769,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); 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 2fdeb5be..78cb4bd6 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; @@ -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); @@ -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; @@ -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); @@ -1870,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 @@ -2154,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; } @@ -2191,7 +2195,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 +2222,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2275,7 +2279,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2332,7 +2336,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2389,7 +2393,7 @@ namespace sub } catch (...) { - Game::Print::PrintError_InvalidInput(); + Game::Print::PrintError_InvalidInput(inputStr); } } return; @@ -2626,42 +2630,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 +2704,7 @@ namespace sub //ms_wheel_windice_pressed = true; } } + addlog(ige::LogType::LOG_TRACE, "Looping Addoption", __FILENAME__); } } @@ -2929,15 +2942,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 +2959,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 +2968,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 +3411,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..90cc29a8 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(); @@ -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) @@ -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/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/_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 diff --git a/Solution/source/macros.h b/Solution/source/macros.h index ed5448de..eda49a8a 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.1.4a1" +#define MENYOO_CURRENT_VER_ "2.2.0" + #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 192032fe..42ea83d3 100644 --- a/Solution/source/main.h +++ b/Solution/source/main.h @@ -287,7 +287,23 @@ enum eGameVersion : int VER_1_0_3504_0, + 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