diff --git a/Project Reboot 3.0/NetDriver.cpp b/Project Reboot 3.0/NetDriver.cpp index 0c8bbeb..2373c19 100644 --- a/Project Reboot 3.0/NetDriver.cpp +++ b/Project Reboot 3.0/NetDriver.cpp @@ -17,6 +17,11 @@ FNetworkObjectList& UNetDriver::GetNetworkObjectList() return *(*(TSharedPtr*)(__int64(this) + Offsets::NetworkObjectList)); } +bool ShouldUseNetworkObjectList() +{ + return Fortnite_Version < 20; +} + void UNetDriver::RemoveNetworkActor(AActor* Actor) { GetNetworkObjectList().Remove(Actor); @@ -35,7 +40,8 @@ void UNetDriver::TickFlushHook(UNetDriver* NetDriver) { static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver", false); - if (ReplicationDriverOffset == -1) + // if (ReplicationDriverOffset == -1) + if (ReplicationDriverOffset == -1 || Fortnite_Version >= 20) { NetDriver->ServerReplicateActors(); } @@ -149,98 +155,148 @@ void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector ActorsToRemove; - auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects; - - auto World = GetWorld(); - - for (const TSharedPtr& ActorInfo : ActiveObjects) + if (ShouldUseNetworkObjectList()) { - if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime) + auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects; + + auto World = GetWorld(); + + for (const TSharedPtr& ActorInfo : ActiveObjects) { - continue; - } - - auto Actor = ActorInfo->Actor; - - if (!Actor) - continue; - - if (Actor->IsPendingKillPending()) - // if (Actor->IsPendingKill()) - { - ActorsToRemove.push_back(Actor); - continue; - } - - static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole"); - - if (Actor->Get(RemoteRoleOffset) == ENetRole::ROLE_None) - { - ActorsToRemove.push_back(Actor); - continue; - } - - // We should add a NetDriverName check but I don't believe it is needed. - - // We should check if the actor is initialized here. - - // We should check the level stuff here. - - static auto NetDormancyOffset = Actor->GetOffset("NetDormancy"); - - if (Actor->Get(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor()) // IsDormInitialStartupActor - { - continue; - } - - // We should check NeedsLoadForClient here. - // We should make sure the actor is in the same world here but I don't believe it is needed. - - if (ActorInfo->LastNetReplicateTime == 0) - { - ActorInfo->LastNetReplicateTime = UGameplayStatics::GetTimeSeconds(World); - ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency(); - } - - const float ScaleDownStartTime = 2.0f; - const float ScaleDownTimeRange = 5.0f; - - const float LastReplicateDelta = UGameplayStatics::GetTimeSeconds(World) - ActorInfo->LastNetReplicateTime; - - if (LastReplicateDelta > ScaleDownStartTime) - { - static auto MinNetUpdateFrequencyOffset = Actor->GetOffset("MinNetUpdateFrequency"); - - if (Actor->Get(MinNetUpdateFrequencyOffset) == 0.0f) + if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime) { - Actor->Get(MinNetUpdateFrequencyOffset) = 2.0f; + continue; } - const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency - const float MaxOptimalDelta = max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower) + auto Actor = ActorInfo->Actor; - const float Alpha = std::clamp((LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f); // should we use fmath? - ActorInfo->OptimalNetUpdateDelta = std::lerp(MinOptimalDelta, MaxOptimalDelta, Alpha); // should we use fmath? + if (!Actor) + continue; + + if (Actor->IsPendingKillPending()) + // if (Actor->IsPendingKill()) + { + ActorsToRemove.push_back(Actor); + continue; + } + + static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole"); + + if (Actor->Get(RemoteRoleOffset) == ENetRole::ROLE_None) + { + ActorsToRemove.push_back(Actor); + continue; + } + + // We should add a NetDriverName check but I don't believe it is needed. + + // We should check if the actor is initialized here. + + // We should check the level stuff here. + + static auto NetDormancyOffset = Actor->GetOffset("NetDormancy"); + + if (Actor->Get(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor()) // IsDormInitialStartupActor + { + continue; + } + + // We should check NeedsLoadForClient here. + // We should make sure the actor is in the same world here but I don't believe it is needed. + + if (ActorInfo->LastNetReplicateTime == 0) + { + ActorInfo->LastNetReplicateTime = UGameplayStatics::GetTimeSeconds(World); + ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency(); + } + + const float ScaleDownStartTime = 2.0f; + const float ScaleDownTimeRange = 5.0f; + + const float LastReplicateDelta = UGameplayStatics::GetTimeSeconds(World) - ActorInfo->LastNetReplicateTime; + + if (LastReplicateDelta > ScaleDownStartTime) + { + static auto MinNetUpdateFrequencyOffset = Actor->GetOffset("MinNetUpdateFrequency"); + + if (Actor->Get(MinNetUpdateFrequencyOffset) == 0.0f) + { + Actor->Get(MinNetUpdateFrequencyOffset) = 2.0f; + } + + const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency + const float MaxOptimalDelta = max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower) + + const float Alpha = std::clamp((LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f); // should we use fmath? + ActorInfo->OptimalNetUpdateDelta = std::lerp(MinOptimalDelta, MaxOptimalDelta, Alpha); // should we use fmath? + } + + if (!ActorInfo->bPendingNetUpdate) + { + constexpr bool bUseAdapativeNetFrequency = false; + const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency(); + + // then set the next update time + float ServerTickTime = 1.f / 30; + ActorInfo->NextUpdateTime = UGameplayStatics::GetTimeSeconds(World) + FRand() * ServerTickTime + NextUpdateDelta; + static auto TimeOffset = GetOffset("Time"); + ActorInfo->LastNetUpdateTime = Get(TimeOffset); + } + + ActorInfo->bPendingNetUpdate = false; + + OutConsiderList.push_back(ActorInfo.Get()); + + static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication); + CallPreReplication(Actor, this); } + } + else + { + auto Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass()); - if (!ActorInfo->bPendingNetUpdate) + for (int i = 0; i < Actors.Num(); ++i) { - constexpr bool bUseAdapativeNetFrequency = false; - const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency(); + auto Actor = Actors.at(i); - // then set the next update time - float ServerTickTime = 1.f / 30; - ActorInfo->NextUpdateTime = UGameplayStatics::GetTimeSeconds(World) + FRand() * ServerTickTime + NextUpdateDelta; - static auto TimeOffset = GetOffset("Time"); - ActorInfo->LastNetUpdateTime = Get(TimeOffset); + if (Actor->IsPendingKillPending()) + // if (Actor->IsPendingKill()) + { + ActorsToRemove.push_back(Actor); + continue; + } + + static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole"); + + if (Actor->Get(RemoteRoleOffset) == ENetRole::ROLE_None) + { + ActorsToRemove.push_back(Actor); + continue; + } + + // We should add a NetDriverName check but I don't believe it is needed. + + // We should check if the actor is initialized here. + + // We should check the level stuff here. + + static auto NetDormancyOffset = Actor->GetOffset("NetDormancy"); + + if (Actor->Get(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor()) // IsDormInitialStartupActor + { + continue; + } + + auto ActorInfo = new FNetworkObjectInfo; + ActorInfo->Actor = Actor; + + OutConsiderList.push_back(ActorInfo); + + static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication); + CallPreReplication(Actor, this); } - ActorInfo->bPendingNetUpdate = false; - - OutConsiderList.push_back(ActorInfo.Get()); - - static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication); - CallPreReplication(Actor, this); + Actors.Free(); } for (auto Actor : ActorsToRemove) @@ -401,7 +457,9 @@ int32 UNetDriver::ServerReplicateActors() } std::vector ConsiderList; - ConsiderList.reserve(GetNetworkObjectList().ActiveNetworkObjects.Num()); + + if (ShouldUseNetworkObjectList()) + ConsiderList.reserve(GetNetworkObjectList().ActiveNetworkObjects.Num()); // std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n'; @@ -424,10 +482,13 @@ int32 UNetDriver::ServerReplicateActors() if (!Connection->GetViewTarget()) continue; - if (Connection->GetPlayerController()) + if (Addresses::SendClientAdjustment) { - static void (*SendClientAdjustment)(APlayerController*) = decltype(SendClientAdjustment)(Addresses::SendClientAdjustment); - SendClientAdjustment(Connection->GetPlayerController()); + if (Connection->GetPlayerController()) + { + static void (*SendClientAdjustment)(APlayerController*) = decltype(SendClientAdjustment)(Addresses::SendClientAdjustment); + SendClientAdjustment(Connection->GetPlayerController()); + } } // Make weak ptr once for IsActorDormant call @@ -513,8 +574,15 @@ int32 UNetDriver::ServerReplicateActors() } } + enum class EChannelCreateFlags : uint32_t + { + None = (1 << 0), + OpenedLocally = (1 << 1) + }; + static UChannel* (*CreateChannel)(UNetConnection*, int, bool, int32_t) = decltype(CreateChannel)(Addresses::CreateChannel); static __int64 (*ReplicateActor)(UActorChannel*) = decltype(ReplicateActor)(Addresses::ReplicateActor); + static UObject* (*CreateChannelByName)(UNetConnection* Connection, FName* ChName, EChannelCreateFlags CreateFlags, int32_t ChannelIndex) = decltype(CreateChannelByName)(Addresses::CreateChannel); static __int64 (*SetChannelActor)(UActorChannel*, AActor*) = decltype(SetChannelActor)(Addresses::SetChannelActor); if (!Channel) @@ -524,7 +592,18 @@ int32 UNetDriver::ServerReplicateActors() if (bLevelInitializedForActor) { - Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1); + if (Engine_Version >= 422) + { + FString ActorStr = L"Actor"; + FName ActorName = UKismetStringLibrary::Conv_StringToName(ActorStr); + + int ChannelIndex = -1; // 4294967295 + Channel = (UActorChannel*)CreateChannelByName(Connection, &ActorName, EChannelCreateFlags::OpenedLocally, ChannelIndex); + } + else + { + Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1); + } if (Channel) { diff --git a/Project Reboot 3.0/NetDriver.h b/Project Reboot 3.0/NetDriver.h index 477738e..a92e4d3 100644 --- a/Project Reboot 3.0/NetDriver.h +++ b/Project Reboot 3.0/NetDriver.h @@ -130,6 +130,18 @@ public: static void TickFlushHook(UNetDriver* NetDriver); + int& GetMaxInternetClientRate() + { + static auto MaxInternetClientRateOffset = GetOffset("MaxInternetClientRate"); + return Get(MaxInternetClientRateOffset); + } + + int& GetMaxClientRate() + { + static auto MaxClientRateOffset = GetOffset("MaxClientRate"); + return Get(MaxClientRateOffset); + } + FNetGUIDCache* GetGuidCache() { static auto GuidCacheOffset = GetOffset("WorldPackage") + 8; // checked for 1.11 diff --git a/Project Reboot 3.0/Rotator.h b/Project Reboot 3.0/Rotator.h index 0d04158..73242f5 100644 --- a/Project Reboot 3.0/Rotator.h +++ b/Project Reboot 3.0/Rotator.h @@ -7,9 +7,15 @@ struct FRotator { +#ifdef ABOVE_S20 + double Pitch; + double Yaw; + double Roll; +#else float Pitch; float Yaw; float Roll; +#endif FQuat Quaternion(); diff --git a/Project Reboot 3.0/Vector.h b/Project Reboot 3.0/Vector.h index 563b86a..d3b5d17 100644 --- a/Project Reboot 3.0/Vector.h +++ b/Project Reboot 3.0/Vector.h @@ -1,11 +1,19 @@ #pragma once +#include "inc.h" + struct FVector { public: - float X; - float Y; - float Z; +#ifdef ABOVE_S20 + using VectorDataType = double; +#else + using VectorDataType = float; +#endif + + VectorDataType X; + VectorDataType Y; + VectorDataType Z; bool CompareVectors(const FVector& A) { @@ -13,7 +21,7 @@ public: } FVector() : X(0), Y(0), Z(0) {} - FVector(float x, float y, float z) : X(x), Y(y), Z(z) {} + FVector(VectorDataType x, VectorDataType y, VectorDataType z) : X(x), Y(y), Z(z) {} FVector operator+(const FVector& A) { @@ -25,17 +33,17 @@ public: return FVector{ this->X - A.X, this->Y - A.Y, this->Z - A.Z }; } - FORCEINLINE float SizeSquared() const + FORCEINLINE VectorDataType SizeSquared() const { return X * X + Y * Y + Z * Z; } - FORCEINLINE float operator|(const FVector& V) const + FORCEINLINE VectorDataType operator|(const FVector& V) const { return X * V.X + Y * V.Y + Z * V.Z; } - FVector operator*(const float A) + FVector operator*(const VectorDataType A) { return FVector{ this->X * A, this->Y * A, this->Z * A }; } diff --git a/Project Reboot 3.0/World.cpp b/Project Reboot 3.0/World.cpp index 49c2e4c..3ce6b0d 100644 --- a/Project Reboot 3.0/World.cpp +++ b/Project Reboot 3.0/World.cpp @@ -66,14 +66,6 @@ void UWorld::Listen() FURL URL = FURL(); URL.Port = Port - (Engine_Version >= 426); - FString Error; - - if (!NewNetDriver->InitListen(GetWorld(), URL, false, Error)) - { - LOG_ERROR(LogNet, "Failed to init listen!"); - return; - } - NewNetDriver->SetWorld(GetWorld()); // LEVEL COLLECTIONS @@ -85,6 +77,21 @@ void UWorld::Listen() *(UNetDriver**)(__int64(LevelCollections.AtPtr(0, LevelCollectionSize)) + 0x10) = NewNetDriver; *(UNetDriver**)(__int64(LevelCollections.AtPtr(1, LevelCollectionSize)) + 0x10) = NewNetDriver; + FString Error; + + if (!NewNetDriver->InitListen(GetWorld(), URL, false, Error)) + { + LOG_ERROR(LogNet, "Failed to init listen!"); + return; + } + + const bool bLanSpeed = false; + + if (!bLanSpeed && (NewNetDriver->GetMaxInternetClientRate() < NewNetDriver->GetMaxClientRate()) && (NewNetDriver->GetMaxInternetClientRate() > 2500)) + { + NewNetDriver->GetMaxClientRate() = NewNetDriver->GetMaxInternetClientRate(); + } + LOG_INFO(LogNet, "Listening on port {}!", Port + Globals::AmountOfListens - 1); } diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 1a83a93..14c50ce 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -467,6 +467,10 @@ void Offsets::FindAll() Offsets::NetworkObjectList = 0x490; Offsets::ReplicationFrame = 0x2C8; } + if (Fortnite_Version >= 20 && Fortnite_Version < 22) + { + Offsets::ReplicationFrame = 0x3D8; + } Offsets::IsNetRelevantFor = FindIsNetRelevantForOffset(); Offsets::Script = Offsets::Children + 8 + 4 + 4; diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 0737772..55a3bd1 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -256,6 +256,8 @@ void ChangeLevels() constexpr bool bUseSwitchLevel = false; constexpr bool bShouldRemoveLocalPlayer = true; + LOG_INFO(LogDev, "FindGIsClient(): 0x{:x}", FindGIsClient() - __int64(GetModuleHandleW(0))); + FString LevelB = Engine_Version < 424 ? L"open Athena_Terrain" : Engine_Version >= 500 ? Engine_Version >= 501 ? L"open Asteria_Terrain" @@ -371,7 +373,8 @@ DWORD WINAPI Main(LPVOID) Addresses::Print(); LOG_INFO(LogDev, "Fortnite_CL: {}", Fortnite_CL); - LOG_INFO(LogDev, "Version: {}", Fortnite_Version); + LOG_INFO(LogDev, "Fortnite_Version: {}", Fortnite_Version); + LOG_INFO(LogDev, "Engine_Version: {}", Engine_Version); CreateThread(0, 0, GuiThread, 0, 0, 0); @@ -434,8 +437,6 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook((PVOID)Addresses::KickPlayer, (PVOID)AGameSession::KickPlayerHook, (PVOID*)&AGameSession::KickPlayerOriginal); LOG_INFO(LogDev, "Built on {} {}", __DATE__, __TIME__); - LOG_INFO(LogDev, "[bNoMCP] {}", Globals::bNoMCP); - LOG_INFO(LogDev, "[bGoingToPlayEvent] {}", Globals::bGoingToPlayEvent); LOG_INFO(LogDev, "Size: 0x{:x}", sizeof(TMap)); Hooking::MinHook::Hook((PVOID)Addresses::ActorGetNetMode, (PVOID)GetNetModeHook2, nullptr); @@ -525,6 +526,8 @@ DWORD WINAPI Main(LPVOID) ChangeLevels(); + LOG_INFO(LogDev, "Switch levels."); + auto AddressesToNull = Addresses::GetFunctionsToNull(); auto ServerCheatAllIndex = GetFunctionIdxOrPtr(FindObject(L"/Script/FortniteGame.FortPlayerController.ServerCheatAll")); @@ -794,6 +797,7 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"), AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false); + Hooking::MinHook::Hook((PVOID)GetFunctionIdxOrPtr(FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerOnExitVehicle"), true), AFortPlayerPawn::ServerOnExitVehicleHook, (PVOID*)&AFortPlayerPawn::ServerOnExitVehicleOriginal); if (Fortnite_Version == 1.11 || Fortnite_Version > 1.8) @@ -994,6 +998,7 @@ DWORD WINAPI Main(LPVOID) uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0; // if (Engine_Version >= 419) + if (Fortnite_Version < 20) { std::vector ServerRemoveInventoryItemCallFunctionStarts = Engine_Version == 416 ? std::vector{ 0x44, 0x88, 0x4C } diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 77ecfa0..277d256 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -65,8 +65,17 @@ static inline uintptr_t FindBytes(Memcury::Scanner& Scanner, const std::vector= 427) // ok so like the func is split up in ida idfk what to do about it { @@ -608,6 +617,8 @@ static inline uint64 FindSetWorld() SetWorldIndex = 0x73; else if (Fortnite_Season >= 19 && Fortnite_Season < 21) SetWorldIndex = 0x7A; + if (Fortnite_Version == 20.40) + SetWorldIndex = 0x7B; // static auto DefaultNetDriver = FindObject("/Script/Engine.Default__NetDriver"); return SetWorldIndex; @@ -1447,7 +1458,12 @@ static inline uint64 FindChangeGameSessionId() static inline uint64 FindDispatchRequest() { - auto Addrr = Memcury::Scanner::FindStringRef(L"MCP-Profile: Dispatching request to %s", true, 0, Fortnite_Version >= 19).Get(); + auto Addrr = Memcury::Scanner::FindStringRef(L"MCP-Profile: Dispatching request to %s", false, 0, Fortnite_Version >= 19).Get(); + + if (!Addrr) + { + return 0; + } for (int i = 0; i < 1000; i++) { @@ -1477,6 +1493,9 @@ static inline uint64 FindMcpIsDedicatedServerOffset() static inline uint64 FindGIsClient() { + if (Fortnite_Version >= 20) + return 0; + // if (Fortnite_Version == 2.5) // return __int64(GetModuleHandleW(0)) + 0x46AD734; /* if (Fortnite_Version == 1.72) @@ -1821,9 +1840,12 @@ static inline uint64 FindCantBuild() if (!add) add = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 56 41 57 48 83 EC 60 49 8B E9 4D 8B F8 48 8B DA 48 8B F9 BE ? ? ? ? 48").Get(); // 5.00 + if (!add) + add = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 56 41 57 48 83 EC 70 49 8B E9 4D 8B F8 48 8B DA 48 8B F9").Get(); // 20.00 + return add; - auto CreateBuildingActorAddr = Memcury::Scanner(GetFunctionIdxOrPtr(FindObject("/Script/FortniteGame.FortAIController.CreateBuildingActor"))); + auto CreateBuildingActorAddr = Memcury::Scanner(GetFunctionIdxOrPtr(FindObject(L"/Script/FortniteGame.FortAIController.CreateBuildingActor"))); auto LikeHuh = Memcury::Scanner(FindBytes(CreateBuildingActorAddr, { 0x40, 0x88 }, 3000)); auto callaa = Memcury::Scanner(FindBytes(LikeHuh, { 0xE8 })); @@ -1848,6 +1870,8 @@ static inline uint64 FindSendClientAdjustment() { if (Fortnite_Version <= 3.2) return Memcury::Scanner::FindPattern("40 53 48 83 EC 20 48 8B 99 ? ? ? ? 48 39 99 ? ? ? ? 74 0A 48 83 B9").Get(); + if (Fortnite_Version >= 20) + return Memcury::Scanner::FindPattern("40 53 48 83 EC 20 48 8B 99 ? ? ? ? 48 39 99 ? ? ? ? 74 0A 48 83 B9").Get(); return 0; } @@ -1866,6 +1890,9 @@ static inline uint64 FindReplicateActor() return addr; } + if (Fortnite_Version >= 20) + return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8D 69 68").Get(); + return 0; } @@ -1873,6 +1900,8 @@ static inline uint64 FindCreateChannel() { if (Fortnite_Version <= 3.2) return Memcury::Scanner::FindPattern("40 56 57 41 54 41 55 41 57 48 83 EC 60 48 8B 01 41 8B F9 45 0F B6 E0").Get(); + if (Fortnite_Version >= 20) + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 44 89 4C 24 ? 55 57 41 54 41 56 41 57 48 8B EC 48 83 EC 50 45 33 E4 48 8D 05 ? ? ? ? 44 38 25").Get(); return 0; } @@ -1890,6 +1919,8 @@ static inline uint64 FindSetChannelActor() return aa; } + if (Fortnite_Version >= 20) + return Memcury::Scanner::FindPattern("40 55 53 56 57 41 54 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 45 33 E4 48 8D 3D ? ? ? ? 44 89 A5").Get(); return 0; } @@ -1902,6 +1933,8 @@ static inline uint64 FindCallPreReplication() return Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 48 8B C4 55 57 41 54 48 8D 68 A1 48 81 EC ? ? ? ? 48 89 58 08 4C").Get(); if (Fortnite_Version >= 2.5 && Fortnite_Version <= 3.2) return Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 56 41 56 48 83 EC 38 4C 8B F2").Get(); + if (Fortnite_Version >= 20) + return Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 56 41 57 48 83 EC 40 F6 41 58 30 48 8B EA 48 8B D9 40 B6 01").Get(); return 0; } diff --git a/Project Reboot 3.0/gui.h b/Project Reboot 3.0/gui.h index f480e56..66bafa3 100644 --- a/Project Reboot 3.0/gui.h +++ b/Project Reboot 3.0/gui.h @@ -263,9 +263,15 @@ static inline bool ButtonCentered(const std::string& text, bool bNewLine = true) static inline void InputVector(const std::string& baseText, FVector* vec) { +#ifdef ABOVE_S20 + ImGui::InputDouble((baseText + " X").c_str(), &vec->X); + ImGui::InputDouble((baseText + " Y").c_str(), &vec->Y); + ImGui::InputDouble((baseText + " Z").c_str(), &vec->Z); +#else ImGui::InputFloat((baseText + " X").c_str(), &vec->X); ImGui::InputFloat((baseText + " Y").c_str(), &vec->Y); ImGui::InputFloat((baseText + " Z").c_str(), &vec->Z); +#endif } static int Width = 640; diff --git a/Project Reboot 3.0/inc.h b/Project Reboot 3.0/inc.h index 23900f7..75d0c38 100644 --- a/Project Reboot 3.0/inc.h +++ b/Project Reboot 3.0/inc.h @@ -59,6 +59,8 @@ inline bool IsRestartingSupported() return Engine_Version >= 419 && Engine_Version < 424; } +// #define ABOVE_S20 + /* enum class AllocatorType