From 20e9fb87dffff118541956102df6eb27bd812b66 Mon Sep 17 00:00:00 2001 From: Milxnor Date: Sun, 2 Apr 2023 11:58:32 -0400 Subject: [PATCH] fix 16.50, fix failing abilities s16+, ammo in bottom right --- Project Reboot 3.0/FortInventory.cpp | 6 +++ Project Reboot 3.0/FortPawn.cpp | 19 +++++++++ Project Reboot 3.0/FortPawn.h | 2 + Project Reboot 3.0/FortPlayerController.cpp | 6 +-- Project Reboot 3.0/FortWeapon.cpp | 20 +++++----- Project Reboot 3.0/FortWeapon.h | 2 + .../Project Reboot 3.0.vcxproj.filters | 6 +-- Project Reboot 3.0/dllmain.cpp | 26 ++++++++++++ Project Reboot 3.0/finder.h | 40 ++++++++++++++++--- 9 files changed, 106 insertions(+), 21 deletions(-) diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index f8f1807..492b885 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -189,6 +189,12 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int if (!ItemDefinition) return false; + if (Count < 0) + { + Count = 0; + bForceRemoval = true; + } + auto NewCount = ReplicatedEntry->GetCount() - Count; if (NewCount > 0 || (ItemDefinition->ShouldPersistWhenFinalStackEmpty() && !bForceRemoval)) diff --git a/Project Reboot 3.0/FortPawn.cpp b/Project Reboot 3.0/FortPawn.cpp index 8ab2fdb..b133d37 100644 --- a/Project Reboot 3.0/FortPawn.cpp +++ b/Project Reboot 3.0/FortPawn.cpp @@ -1,6 +1,7 @@ #include "FortPawn.h" #include "reboot.h" +#include "FortPlayerControllerAthena.h" AFortWeapon* AFortPawn::EquipWeaponDefinition(UFortWeaponItemDefinition* WeaponData, const FGuid& ItemEntryGuid) { @@ -56,6 +57,24 @@ void AFortPawn::SetShield(float NewShield) this->ProcessEvent(SetShieldFn, &NewShield); } +void AFortPawn::NetMulticast_Athena_BatchedDamageCuesHook(UObject* Context, FFrame* Stack, void* Ret) +{ + auto Pawn = (AFortPawn*)Context; + auto Controller = Cast(Pawn->GetController()); + auto CurrentWeapon = Pawn->GetCurrentWeapon(); + auto WorldInventory = Controller ? Controller->GetWorldInventory() : nullptr; + + if (!WorldInventory || !CurrentWeapon) + return NetMulticast_Athena_BatchedDamageCuesOriginal(Context, Stack, Ret); + + static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount"); + auto AmmoCount = CurrentWeapon->Get(AmmoCountOffset); + + WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount); + + return NetMulticast_Athena_BatchedDamageCuesOriginal(Context, Stack, Ret); +} + UClass* AFortPawn::StaticClass() { static auto Class = FindObject("/Script/FortniteGame.FortPawn"); diff --git a/Project Reboot 3.0/FortPawn.h b/Project Reboot 3.0/FortPawn.h index 3f49553..ba9ad80 100644 --- a/Project Reboot 3.0/FortPawn.h +++ b/Project Reboot 3.0/FortPawn.h @@ -7,6 +7,7 @@ class AFortPawn : public APawn { public: + static inline void (*NetMulticast_Athena_BatchedDamageCuesOriginal)(UObject* Context, FFrame* Stack, void* Ret); AFortWeapon* EquipWeaponDefinition(UFortWeaponItemDefinition* WeaponData, const FGuid& ItemEntryGuid); bool PickUpActor(AActor* PickupTarget, UFortDecoItemDefinition* PlacementDecoItemDefinition); @@ -26,6 +27,7 @@ public: void SetHealth(float NewHealth); void SetShield(float NewShield); + static void NetMulticast_Athena_BatchedDamageCuesHook(UObject* Context, FFrame* Stack, void* Ret); static UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index ce415b0..d15b1bc 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -640,10 +640,10 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe FGameplayAbilitySpec* Spec = MakeNewSpec((UClass*)AbilityToUse, EmoteAsset, true); - static unsigned int* (*GiveAbilityAndActivateOnce)(UAbilitySystemComponent* ASC, int* outHandle, __int64 Spec, FGameplayEventData* TriggerEventData) - = decltype(GiveAbilityAndActivateOnce)(Addresses::GiveAbilityAndActivateOnce); // EventData is only on ue500? + static unsigned int* (*GiveAbilityAndActivateOnce)(UAbilitySystemComponent* ASC, int* outHandle, __int64 Spec, FGameplayEventData* TriggerEventData) = decltype(GiveAbilityAndActivateOnce)(Addresses::GiveAbilityAndActivateOnce); // EventData is only on ue500? - GiveAbilityAndActivateOnce(PlayerState->GetAbilitySystemComponent(), &outHandle, __int64(Spec), nullptr); + if (GiveAbilityAndActivateOnce) + GiveAbilityAndActivateOnce(PlayerState->GetAbilitySystemComponent(), &outHandle, __int64(Spec), nullptr); } uint8 ToDeathCause(const FGameplayTagContainer& TagContainer, bool bWasDBNO = false) diff --git a/Project Reboot 3.0/FortWeapon.cpp b/Project Reboot 3.0/FortWeapon.cpp index 7cd82c4..36ca07b 100644 --- a/Project Reboot 3.0/FortWeapon.cpp +++ b/Project Reboot 3.0/FortWeapon.cpp @@ -4,30 +4,32 @@ #include "reboot.h" #include "FortPlayerController.h" -void AFortWeapon::ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret) +void AFortWeapon::OnPlayImpactFXHook(AFortWeapon* Weapon, __int64 HitResult, uint8_t ImpactPhysicalSurface, UObject* SpawnedPSC) { - // I don't know where to put this.. - - auto Weapon = (AFortWeapon*)Context; - auto Pawn = Cast(Weapon->GetOwner()); + // grappler - // LOG_INFO(LogDev, "Owner: {}", Weapon->GetOwner() ? Weapon->GetOwner()->GetFullName() : "InvalidObject"); + auto Pawn = Cast(Weapon->GetOwner()); if (!Pawn) - return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret); + return OnPlayImpactFXOriginal(Weapon, HitResult, ImpactPhysicalSurface, SpawnedPSC); auto Controller = Cast(Pawn->GetController()); - auto CurrentWeapon = Weapon; // Pawn->GetCurrentWeapon(); + auto CurrentWeapon = Pawn->GetCurrentWeapon(); auto WorldInventory = Controller ? Controller->GetWorldInventory() : nullptr; if (!WorldInventory || !CurrentWeapon) - return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret); + return OnPlayImpactFXOriginal(Weapon, HitResult, ImpactPhysicalSurface, SpawnedPSC); static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount"); auto AmmoCount = CurrentWeapon->Get(AmmoCountOffset); WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount); + return OnPlayImpactFXOriginal(Weapon, HitResult, ImpactPhysicalSurface, SpawnedPSC); +} + +void AFortWeapon::ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret) +{ return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret); } diff --git a/Project Reboot 3.0/FortWeapon.h b/Project Reboot 3.0/FortWeapon.h index b5b5164..0b95193 100644 --- a/Project Reboot 3.0/FortWeapon.h +++ b/Project Reboot 3.0/FortWeapon.h @@ -8,6 +8,7 @@ class AFortWeapon : public AActor { public: static inline void (*ServerReleaseWeaponAbilityOriginal)(UObject* Context, FFrame* Stack, void* Ret); + static inline void (*OnPlayImpactFXOriginal)(AFortWeapon* Weapon, __int64 HitResult, uint8_t ImpactPhysicalSurface, UObject* SpawnedPSC); template T* GetWeaponData() @@ -22,6 +23,7 @@ public: return Get(ItemEntryGuidOffset); } + static void OnPlayImpactFXHook(AFortWeapon* Weapon, __int64 HitResult, uint8_t ImpactPhysicalSurface, UObject* SpawnedPSC); static void ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret); static UClass* StaticClass(); diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters index 6a50e5c..4edd6fd 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -431,9 +431,6 @@ FortniteGame\Source\FortniteGame\Public - - Reboot\Public - FortniteGame\Source\FortniteGame\Public\Items @@ -479,6 +476,9 @@ Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Public + + Reboot\Public + diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 7b8a7bf..16cdf6d 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -271,6 +271,28 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(FortWeaponDefault, FindObject(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"), AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true); + auto OnPlayImpactFXFunctionPtr = Memcury::Scanner::FindStringRef(L"OnPlayImpactFX", true, 0).ScanFor({ 0x48, 0x8D, 0x0D }).RelativeOffset(3).GetAs(); + auto OnPlayImpactFXPtrRef = Memcury::Scanner::FindPointerRef(OnPlayImpactFXFunctionPtr).Get(); + __int64 OnPlayImpactFXAddr = 0; + + for (int i = 0; i < 2000; i++) + { + if (*(uint8_t*)(uint8_t*)(OnPlayImpactFXPtrRef - i) == 0x48 && *(uint8_t*)(uint8_t*)(OnPlayImpactFXPtrRef - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(OnPlayImpactFXPtrRef - i + 2) == 0x5C) + { + OnPlayImpactFXAddr = OnPlayImpactFXPtrRef - i; + break; + } + + if (*(uint8_t*)(uint8_t*)(OnPlayImpactFXPtrRef - i) == 0x4C && *(uint8_t*)(uint8_t*)(OnPlayImpactFXPtrRef - i + 1) == 0x8B) + { + OnPlayImpactFXAddr = OnPlayImpactFXPtrRef - i; + break; + } + } + + LOG_INFO(LogDev, "OnPlayImpactFX: 0x{:x}", OnPlayImpactFXAddr - __int64(GetModuleHandleW(0))); + Hooking::MinHook::Hook((PVOID)OnPlayImpactFXAddr, AFortWeapon::OnPlayImpactFXHook, (PVOID*)&AFortWeapon::OnPlayImpactFXOriginal); + Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerDropAllItems"), AFortPlayerController::ServerDropAllItemsHook, nullptr, false); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerAttemptInventoryDrop"), @@ -301,6 +323,10 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(FortPlayerStateAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerStateAthena.ServerSetInAircraft"), AFortPlayerStateAthena::ServerSetInAircraftHook, (PVOID*)&AFortPlayerStateAthena::ServerSetInAircraftOriginal, false, true); // We could use second method but eh + static auto NetMulticast_Athena_BatchedDamageCuesFn = FindObject(L"/Script/FortniteGame.FortPawn.NetMulticast_Athena_BatchedDamageCues") ? FindObject(L"/Script/FortniteGame.FortPawn.NetMulticast_Athena_BatchedDamageCues") : FindObject(L"/Script/FortniteGame.FortPlayerPawnAthena.NetMulticast_Athena_BatchedDamageCues"); + + Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, NetMulticast_Athena_BatchedDamageCuesFn, + AFortPawn::NetMulticast_Athena_BatchedDamageCuesHook, (PVOID*)&AFortPawn::NetMulticast_Athena_BatchedDamageCuesOriginal, false, true); Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"), AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index b56e451..bff49b6 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -71,7 +71,12 @@ static inline uint64 FindStaticFindObject(int StringSkip = 1) if (Engine_Version >= 427) // ok so like the func is split up in ida idfk what to do about it { if (Fortnite_Version < 18) + { + if (Fortnite_Version == 16.50) + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 60 45 33 ED 45 8A F9 44 38 2D ? ? ? ? 49 8B F8 48 8B F2 4C 8B E1").Get(); + return Memcury::Scanner::FindPattern("40 55 53 57 41 54 41 55 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85").Get(); + } else return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 60 45 33 ED 45 8A F9 44 38 2D ? ? ? ? 49 8B F8 48 8B").Get(); } @@ -521,7 +526,10 @@ static inline uint64 FindCompletePickupAnimation() auto sig = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 48 89 68 10 48 89 70 18 48 89 78 20 41 54 41 56 41 57 48 83 EC 20 48 8B B1 ? ? ? ? 48 8B D9 48 85 F6", false).Get(); // 17.30 if (!sig) - sig = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 54 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 48 8B B9 ? ? ? ? 48 8B D9 48 85 FF 74 16 48 89").Get(); // 18.40 + sig = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 54 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 48 8B B9 ? ? ? ? 48 8B D9 48 85 FF 74 16 48 89", false).Get(); // 18.40 + + if (!sig) + sig = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 68 18 57 48 83 EC 20 48 8B D9 48 8B 89 ? ? ? ? 48 85").Get(); // 16.50 return sig; } @@ -698,11 +706,14 @@ static inline uint64 FindTickFlush() if (Engine_Version == 427) { - auto addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 8A").Get(); + auto addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 8A", false).Get(); if (!addr) // s18 - addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 44 0F").Get(); + addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 44 0F", false).Get(); + if (!addr) + addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 48 8B F9 48 89 4D 38 48 8D 4D 40").Get(); // 16.50 + return addr; } @@ -1104,7 +1115,7 @@ static inline uint64 FindPickTeam() static inline uint64 FindInternalTryActivateAbility() { - auto Addrr = Memcury::Scanner::FindStringRef(L"InternalTryActivateAbility called with invalid Handle! ASC: %s. AvatarActor: %s", true, 0, Fortnite_Version >= 17).Get(); + auto Addrr = Memcury::Scanner::FindStringRef(L"InternalTryActivateAbility called with invalid Handle! ASC: %s. AvatarActor: %s", true, 0, Fortnite_Version >= 16.50).Get(); for (int i = 0; i < 1000; i++) { @@ -1140,8 +1151,25 @@ static inline uint64 FindCanActivateAbility() if (Engine_Version == 421 || Engine_Version == 422) return Memcury::Scanner::FindPattern("4C 89 4C 24 20 55 56 57 41 56 48 8D 6C 24 D1").Get(); - auto Addr = Memcury::Scanner::FindStringRef(L"CanActivateAbility %s failed, blueprint refused", true, 0, Engine_Version >= 500); - return FindBytes(Addr, { 0x48, 0x89, 0x5C }, 2000, 0, true); + auto Addrr = Memcury::Scanner::FindStringRef(L"CanActivateAbility %s failed, blueprint refused", true, 0, Engine_Version >= 500).Get(); + + for (int i = 0; i < 2000; i++) + { + if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0x5C) + { + return Addrr - i; + } + + if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x8B && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0xC4) + { + return Addrr - i; + } + } + + return 0; + + // auto Addr = Memcury::Scanner::FindStringRef(L"CanActivateAbility %s failed, blueprint refused", true, 0, Engine_Version >= 500); + // return FindBytes(Addr, { 0x48, 0x89, 0x5C }, 2000, 0, true); } static inline uint64 FindGiveAbilityAndActivateOnce()