This commit is contained in:
Gray
2025-07-18 18:40:13 -04:00
parent 8f0ce8919e
commit 62ffdccd42
15 changed files with 292 additions and 82 deletions

View File

@@ -187,6 +187,15 @@ bool AActor::IsNetStartup()
return ReadBitfieldValue(bNetStartupOffset, bNetStartupFieldMask);
}
bool AActor::DoesReplicate()
{
static auto bReplicatesOffset = GetOffset("bReplicates");
static auto bReplicatesFieldMask = GetFieldMask(GetProperty("bReplicates"));
return ReadBitfieldValue(bReplicatesOffset, bReplicatesFieldMask);
}
void AActor::SetOwner(AActor* Owner)
{
static auto SetOwnerFn = FindObject<UFunction>(L"/Script/Engine.Actor.SetOwner");
@@ -201,7 +210,8 @@ void AActor::ForceNetUpdate()
bool AActor::IsNetStartupActor()
{
return IsNetStartup(); // The implementation on this function depends on the version.
// bNetStartup || (!bActorInitialized && !bActorSeamlessTraveled && bNetLoadOnClient && GetLevel() && !GetLevel()->bAlreadyInitializedNetworkActors);
return IsNetStartup(); // ^^ The implementation on this function depends on the version.
}
bool AActor::IsPendingKillPending()

View File

@@ -36,6 +36,7 @@ public:
float GetDistanceTo(AActor* OtherActor);
struct FRotator GetActorRotation();
void FlushNetDormancy();
bool DoesReplicate();
bool TeleportTo(const FVector& DestLocation, const FRotator& DestRotation);
bool IsActorBeingDestroyed();
bool IsNetStartup();

View File

@@ -21,18 +21,12 @@ struct UFieldPadding : UObject
template <typename PropertyType = void>
static inline PropertyType* GetNext(void* Field)
{
return Fortnite_Version >= 12.10 ? *(PropertyType**)(__int64(Field) + 0x20) : ((UField*)Field)->Next;
return *(PropertyType**)(__int64(Field) + Offsets::Next);
}
static inline FName* GetFNameOfProp(void* Property)
{
FName* NamePrivate = nullptr;
if (Fortnite_Version >= 12.10)
NamePrivate = (FName*)(__int64(Property) + 0x28);
else
NamePrivate = &((UField*)Property)->NamePrivate;
FName* NamePrivate = (FName*)(__int64(Property) + Offsets::PropName);
return NamePrivate;
}

View File

@@ -184,7 +184,7 @@ void AFortGameModeAthena::StartAircraftPhase()
if (Addresses::StartAircraftPhase)
{
static void (*StartAircraftPhaseOriginal)(AFortGameModeAthena*, bool bDoNotSpawnAircraft) = decltype(StartAircraftPhaseOriginal)(Addresses::StartAircraftPhase);
StartAircraftPhaseOriginal(this, false); // love the double negative fortnite
StartAircraftPhaseOriginal(this, false); // love the double negative Fortnite
}
else
{
@@ -1471,6 +1471,29 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
SpawnIsland_FloorLoot_Actors.Free();
BRIsland_FloorLoot_Actors.Free();
#if 0
if (Fortnite_Version >= 23) // Partitioning real
{
auto& StreamingLevels = GetWorld()->GetStreamingLevels();
for (int i = 0; i < StreamingLevels.Num(); ++i)
{
auto StreamingLevel = StreamingLevels.At(i);
static auto SetIsRequestingUnloadAndRemovalFn = FindObject<UFunction>(L"/Script/Engine.LevelStreaming.SetIsRequestingUnloadAndRemoval");
static auto SetShouldBeLoadedFn = FindObject<UFunction>(L"/Script/Engine.LevelStreaming.SetShouldBeLoaded");
static auto SetShouldBeVisibleFn = FindObject<UFunction>(L"/Script/Engine.LevelStreaming.SetShouldBeVisible");
bool bTrue = true;
bool bFalse = false;
StreamingLevel->ProcessEvent(SetShouldBeLoadedFn, &bTrue);
StreamingLevel->ProcessEvent(SetShouldBeVisibleFn, &bTrue);
StreamingLevel->ProcessEvent(SetIsRequestingUnloadAndRemovalFn, &bFalse);
}
}
#endif
LOG_INFO(LogDev, "Spawned loot!");
#endif
}

View File

@@ -1332,7 +1332,17 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
*(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bDBNO) = DeadPawn->IsDBNO();
*(uint8*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathCause) = DeathCause;
*(AActor**)(__int64(DeathInfo) + MemberOffsets::DeathInfo::FinisherOrDowner) = KillerPlayerState ? KillerPlayerState : DeadPlayerState;
auto FinisherOrDowner = KillerPlayerState ? KillerPlayerState : DeadPlayerState;;
if (MemberOffsets::DeathInfo::bIsWeakFinisherOrDowner)
{
TWeakObjectPtr<AActor> WeakFinisherOrDowner{};
WeakFinisherOrDowner.ObjectIndex = FinisherOrDowner->InternalIndex;
WeakFinisherOrDowner.ObjectSerialNumber = GetItemByIndex(FinisherOrDowner->InternalIndex)->SerialNumber;
}
else
*(AActor**)(__int64(DeathInfo) + MemberOffsets::DeathInfo::FinisherOrDowner) = FinisherOrDowner;
if (MemberOffsets::DeathInfo::DeathLocation != -1)
*(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) = DeathLocation;

View File

@@ -12,6 +12,17 @@
#include "bots.h"
#include "gui.h"
enum class EChannelCloseReason : uint8
{
Destroyed,
Dormancy,
LevelUnloaded,
Relevancy,
TearOff,
/* reserved */
MAX = 15 // this value is used for serialization, modifying it may require a network version change
};
FNetworkObjectList& UNetDriver::GetNetworkObjectList()
{
return *(*(TSharedPtr<FNetworkObjectList>*)(__int64(this) + Offsets::NetworkObjectList));
@@ -288,6 +299,9 @@ void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObj
{
auto Actor = Actors.at(i);
if (!Actor->DoesReplicate())
continue;
if (Actor->IsPendingKillPending())
// if (Actor->IsPendingKill())
{
@@ -581,7 +595,7 @@ int32 UNetDriver::ServerReplicateActors()
++(*(int*)(__int64(this) + Offsets::ReplicationFrame));
const int32 NumClientsToTick = ServerReplicateActors_PrepConnections(this);
// LOG_INFO(LogDev, "NumClientsToTick: {}", NumClientsToTick);
if (NumClientsToTick == 0)
{
// No connections are ready this frame
@@ -613,7 +627,7 @@ int32 UNetDriver::ServerReplicateActors()
ServerReplicateActors_BuildConsiderList(ConsiderList, ServerTickTime);
// LOG_INFO(LogReplication, "Considering {} actors.", ConsiderList.size());
LOG_INFO(LogReplication, "Considering {} actors.", ConsiderList.size());
static UChannel* (*CreateChannel)(UNetConnection*, int, bool, int32_t) = decltype(CreateChannel)(Addresses::CreateChannel);
static __int64 (*ReplicateActor)(UActorChannel*) = decltype(ReplicateActor)(Addresses::ReplicateActor);
@@ -782,30 +796,44 @@ int32 UNetDriver::ServerReplicateActors()
if (Addresses::ActorChannelClose && Offsets::IsNetRelevantFor)
{
static void (*ActorChannelClose)(UActorChannel*) = decltype(ActorChannelClose)(Addresses::ActorChannelClose);
static void (*ActorChannelCloseParams)(UActorChannel*, EChannelCloseReason) = decltype(ActorChannelCloseParams)(Addresses::ActorChannelClose);
if (!Actor->IsAlwaysRelevant() && !Actor->UsesOwnerRelevancy() && !Actor->IsOnlyRelevantToOwner())
if (!Actor->IsAlwaysRelevant())
{
if (Connection && Connection->GetViewTarget())
if (!Actor->UsesOwnerRelevancy() && !Actor->IsOnlyRelevantToOwner())
{
auto Viewer = Connection->GetViewTarget();
auto Loc = Viewer->GetActorLocation();
if (!IsActorRelevantToConnection(Actor, ConnectionViewers))
if (auto Viewer = Connection->GetViewTarget())
{
// LOG_INFO(LogReplication, "Actor is not relevant!");
auto Loc = Viewer->GetActorLocation();
if (Channel)
ActorChannelClose(Channel);
if (!IsActorRelevantToConnection(Actor, ConnectionViewers))
{
// LOG_INFO(LogReplication, "Actor is not relevant!");
continue;
if (Channel)
{
// can we just call yes
if (Fortnite_Version > 20)
ActorChannelCloseParams(Channel, EChannelCloseReason::Relevancy);
else
ActorChannelClose(Channel);
}
continue;
}
}
}
else
{
// TODO ?
}
}
}
if (!Channel)
{
if (Actor->IsA(APlayerController::StaticClass()) && Actor != Connection->GetPlayerController()) // isnetrelevantfor should handle this iirc
if (!Offsets::IsNetRelevantFor
&& Actor->IsA(APlayerController::StaticClass()) && Actor != Connection->GetPlayerController()) // isnetrelevantfor should handle this iirc
continue;
if (bLevelInitializedForActor)

View File

@@ -6,6 +6,7 @@
#include "Rotator.h"
#include "Actor.h"
#include "GameInstance.h"
#include "Array.h"
struct FNetworkNotify
{
@@ -222,6 +223,12 @@ public:
return this->Get<class AGameState*>(GameStateOffset);
}
TArray<class ULevelStreaming*>& GetStreamingLevels()
{
static auto StreamingLevelsOffset = GetOffset("StreamingLevels");
return this->Get<TArray<class ULevelStreaming*>>(StreamingLevelsOffset);
}
class UNetDriver*& GetNetDriver()
{
static auto NetDriverOffset = GetOffset("NetDriver");

View File

@@ -258,9 +258,6 @@ void Addresses::FindAll()
LOG_INFO(LogDev, "Finding StepExplicitProperty");
Addresses::FrameStepExplicitProperty = FindStepExplicitProperty();
LOG_INFO(LogDev, "Finding Free");
Addresses::Free = FindFree();
LOG_INFO(LogDev, "Finding ClearAbility");
Addresses::ClearAbility = FindClearAbility();
@@ -386,7 +383,6 @@ void Addresses::Print()
LOG_INFO(LogDev, "RemoveFromAlivePlayers: 0x{:x}", RemoveFromAlivePlayers - Base);
LOG_INFO(LogDev, "ActorChannelClose: 0x{:x}", ActorChannelClose - Base);
LOG_INFO(LogDev, "FrameStepExplicitProperty: 0x{:x}", FrameStepExplicitProperty - Base);
LOG_INFO(LogDev, "Free: 0x{:x}", Free - Base);
LOG_INFO(LogDev, "ClearAbility: 0x{:x}", ClearAbility - Base);
LOG_INFO(LogDev, "ApplyGadgetData: 0x{:x}", ApplyGadgetData - Base);
LOG_INFO(LogDev, "RemoveGadgetData: 0x{:x}", RemoveGadgetData - Base);
@@ -412,7 +408,8 @@ void Addresses::Print()
void Offsets::FindAll()
{
Offsets::Offset_Internal = Fortnite_Version >= 12.10 && std::floor(Fortnite_Version) < 20 ? 0x4C : 0x44;
Offsets::Offset_Internal = Fortnite_Version >= 24 ? 0x3C
: Fortnite_Version >= 12.10 && std::floor(Fortnite_Version) < 20 ? 0x4C : 0x44;
Offsets::SuperStruct = Engine_Version >= 422 ? 0x40 : 0x30;
Offsets::Children = Fortnite_Version >= 12.10 ? 0x50 : Offsets::SuperStruct + 8;
Offsets::PropertiesSize = Offsets::Children + 8;
@@ -520,11 +517,18 @@ void Offsets::FindAll()
}
if (Fortnite_Version >= 23)
{
Offsets::ReplicationFrame = 0x440; // checked only on 23.40
Offsets::ReplicationFrame = 0x440; // checked on 23.40 & 23.50
}
Offsets::IsNetRelevantFor = FindIsNetRelevantForOffset();
Offsets::Script = Offsets::Children + 8 + 4 + 4;
Offsets::PropName = Fortnite_Version >= 12.10
? Fortnite_Version >= 24 ? 0x20
: 0x28 : 0x18;
Offsets::Next = Fortnite_Version >= 12.10
? Fortnite_Version >= 24 ? 0x18
: 0x20 : 0x28;
}
void Offsets::Print()

View File

@@ -89,6 +89,8 @@ namespace Addresses
namespace Offsets
{
extern inline uint64 PropName = 0;
extern inline uint64 Next = 0;
extern inline uint64 Func = 0;
extern inline uint64 PropertiesSize = 0;
extern inline uint64 Children = 0;

View File

@@ -665,6 +665,15 @@ UObject* GetAIDirectorHook()
return GameMode->Get(AIDirectorOffset);
}
DWORD WINAPI ClientThread(LPVOID)
{
while (true)
{
return 0;
}
}
void ChangeLevels()
{
constexpr bool bUseRemovePlayer = false;
@@ -782,13 +791,40 @@ void ChangeLevels()
static inline char (*oFunc)(__int64) = nullptr;
static inline __int64 (*func2)(__int64) = nullptr;
static inline int persi = 0x0;
char Func(__int64 a1)
{
if (auto r = func2(a1))
__int64 r = 0;
if (Fortnite_Version >= 24)
{
if (a1)
{
auto v1 = a1;
while ((*(uint8_t*)(__int64(v1) + 8) & 0x30) == 0)
{
v1 = *(__int64*)(v1 + 32);
if (!v1)
goto LABEL_4;
}
r = 0LL;
}
else
{
LABEL_4:
r = *(__int64*)(a1 + 32);
}
}
else
{
r = func2(a1);
}
if (r)
{
if (auto v5 = *(__int64*)(__int64(r) + 0x38))
{
auto persisntelevle = *(__int64*)(__int64(v5) + 0x98);
auto persisntelevle = *(__int64*)(__int64(v5) + persi);
if (!persisntelevle)
{
LOG_INFO(LogDev, "tralaleo trallala");
@@ -804,8 +840,21 @@ void ApplyNullAndRetTrues()
{
if (Fortnite_Version >= 23)
{
auto sig = Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B D9 E8 ? ? ? ? 48 8B F8 48 8B 83 ? ? ? ? 48 85 C0").Get(); // 23.40
func2 = decltype(func2)(Memcury::Scanner::FindPattern("48 83 EC 28 BA ? ? ? ? 4C 8B C1 E8 ? ? ? ? 84 C0 74 04 33 C0 EB 04 49 8B 40 20").Get());
persi = 0x98;
__int64 sig = 0;
if (Fortnite_Version >= 24)
{
persi = 0xA0;
sig = Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B C1 48 85 C9 74 0F F6 40 08 30 75 61 48 8B 40 20 48 85 C0 75 F1 48 8B 59 20 48 8B 81").Get(); // 24.40
}
else
{
func2 = decltype(func2)(Memcury::Scanner::FindPattern("48 83 EC 28 BA ? ? ? ? 4C 8B C1 E8 ? ? ? ? 84 C0 74 04 33 C0 EB 04 49 8B 40 20").Get());
sig = Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B D9 E8 ? ? ? ? 48 8B F8 48 8B 83 ? ? ? ? 48 85 C0").Get(); // 23.40
}
Hooking::MinHook::Hook((PVOID)sig, Func, (void**)&oFunc);
}
@@ -847,6 +896,13 @@ void ApplyNullAndRetTrues()
}
}
bool (*ReplicateActorOriginal)(UActorChannel* Channel) = nullptr;
bool ReplicateActorHook(UActorChannel* Channel)
{
LOG_INFO(LogDev, "[ReplicateActorHook] Replicating: {}", Channel->GetActor()->GetFullName());
return ReplicateActorOriginal(Channel);
}
DWORD WINAPI Main(LPVOID)
{
InitLogger();
@@ -947,6 +1003,20 @@ DWORD WINAPI Main(LPVOID)
if (Fortnite_Version >= 20 || Fortnite_Version == 12.00)
ApplyNullAndRetTrues();
auto ObjectNum = ChunkedObjects ? ChunkedObjects->Num() : UnchunkedObjects ? UnchunkedObjects->Num() : 0;
std::ofstream obj("ObjectsDump.txt");
for (int i = 0; i < ObjectNum; ++i)
{
auto CurrentObject = GetObjectByIndex(i);
if (!CurrentObject)
continue;
obj << CurrentObject->GetFullName() << '\n';
}
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogNetPackageMap VeryVerbose", nullptr);
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogNetTraffic VeryVerbose", nullptr);
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogNet VeryVerbose", nullptr);
@@ -977,6 +1047,8 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr);
Hooking::MinHook::Hook((PVOID)Addresses::DispatchRequest, (PVOID)DispatchRequestHook, (PVOID*)&DispatchRequestOriginal);
Hooking::MinHook::Hook((PVOID)Addresses::ReplicateActor, (PVOID)ReplicateActorHook, (PVOID*)&ReplicateActorOriginal);
GSRandSeed = FGenericPlatformTime::Cycles();
ReplicationRandStream = FRandomStream(FGenericPlatformTime::Cycles());
@@ -1196,6 +1268,9 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook((PVOID)ApplyHomebaseEffectsOnPlayerSetupAddr, ApplyHomebaseEffectsOnPlayerSetupHook, (PVOID*)&ApplyHomebaseEffectsOnPlayerSetupOriginal);
}
Hooking::MinHook::Hook(FindObject(L"/Script/FortniteGame.Default__FortAthenaVehicleSpawner"), FindObject<UFunction>(L"/Script/FortniteGame.FortAthenaVehicleSpawner.SpawnVehicle"),
AFortAthenaVehicleSpawner::SpawnVehicleHook, nullptr, false);
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameMode.ReadyToStartMatch"), AFortGameModeAthena::Athena_ReadyToStartMatchHook,
(PVOID*)&AFortGameModeAthena::Athena_ReadyToStartMatchOriginal, false, false, true);
@@ -1554,9 +1629,6 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.InventoryManagementLibrary.SwapItems"),
UInventoryManagementLibrary::SwapItemsHook, (PVOID*)&UInventoryManagementLibrary::SwapItemsOriginal, false, true);
Hooking::MinHook::Hook(FindObject(L"/Script/FortniteGame.Default__FortAthenaVehicleSpawner"), FindObject<UFunction>(L"/Script/FortniteGame.FortAthenaVehicleSpawner.SpawnVehicle"),
AFortAthenaVehicleSpawner::SpawnVehicleHook, nullptr, false);
static auto ServerHandlePickupInfoFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerHandlePickupInfo");
if (ServerHandlePickupInfoFn)
@@ -1574,6 +1646,7 @@ DWORD WINAPI Main(LPVOID)
static auto PredictionKeyStruct = FindObject<UStruct>(L"/Script/GameplayAbilities.PredictionKey");
static auto PredictionKeySize = PredictionKeyStruct->GetPropertiesSize();
if (Addresses::InternalTryActivateAbility)
{
int InternalServerTryActivateAbilityIndex = 0;
@@ -1714,6 +1787,7 @@ DWORD WINAPI Main(LPVOID)
MemberOffsets::DeathInfo::Distance = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "Distance", false);
MemberOffsets::DeathInfo::DeathTags = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathTags", false);
MemberOffsets::DeathInfo::DeathLocation = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathLocation", false);
MemberOffsets::DeathInfo::bIsWeakFinisherOrDowner = false;
MemberOffsets::DeathReport::Tags = FindOffsetStruct("/Script/FortniteGame.FortPlayerDeathReport", "Tags");
MemberOffsets::DeathReport::KillerPawn = FindOffsetStruct("/Script/FortniteGame.FortPlayerDeathReport", "KillerPawn");

View File

@@ -48,15 +48,22 @@ uint64 FindGIsClient()
{
// if (Fortnite_Version >= 19) return 0;
auto Addr = Memcury::Scanner::FindStringRef(L"AllowCommandletRendering");
auto Addr = Memcury::Scanner::FindStringRef(L"AllowCommandletRendering", false);
if (!Addr.Get()) // pretty sure only 22+ since the string is split (we could maybe try just searching without the A?)
{
// Looking for commandlet class
if (Fortnite_Version == 22.3)
{
// return __int64(GetModuleHandleW(0)) + 0xDCE9DFA;
}
if (Fortnite_Version == 23.5)
{
// return __int64(GetModuleHandleW(0)) + 0xEBD8A4C;
}
LOG_ERROR(LogDev, "[FindGIsClient] Failed to find AllowCommandletRendering! Returning 0");
return 0;
}
@@ -190,7 +197,7 @@ uint64 FindGetPlayerViewpoint()
uint64 FailedToSpawnPawnAddr = 0;
auto FailedToSpawnPawnStrRefAddr = Memcury::Scanner::FindStringRef(L"%s failed to spawn a pawn", true, 0, Fortnite_Version >= 19).Get();
auto FailedToSpawnPawnStrRefAddr = Memcury::Scanner::FindStringRef(L"%s failed to spawn a pawn", true, 0, Fortnite_Version >= 19 && Fortnite_Version < 24).Get();
if (!FailedToSpawnPawnStrRefAddr)
{

View File

@@ -134,7 +134,7 @@ static inline uint64 FindProcessEvent()
return FindBytes(Addr, { 0x40, 0x55 }, 2000); // Addr.ScanFor({ 0x40, 0x55 }).Get();
}
auto Addr = Memcury::Scanner::FindStringRef(L"UMeshNetworkComponent::ProcessEvent: Invalid mesh network node type: %s", true, 0, Engine_Version >= 500);
auto Addr = Memcury::Scanner::FindStringRef(L"UMeshNetworkComponent::ProcessEvent: Invalid mesh network node type: %s", true, 0, Engine_Version >= 500 && Fortnite_Version < 24);
return Memcury::Scanner(FindBytes(Addr, { 0xE8 }, 2000, 0, false, Engine_Version < 500 ? 1 : 3)).RelativeOffset(1).Get(); // Addr.ScanFor({ 0x40, 0x55 }).Get();
}
@@ -318,6 +318,16 @@ static inline uint64 FindKickPlayer()
return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 48 89 70 10 48 89 78 18 4C 89 60 20 55 41 56 41 57 48 8B EC 48 83 EC 60 48 83 65 ? ? 4C 8B F2 83 65 E8 00 4C 8B E1 83 65 EC").Get();
if (std::floor(Fortnite_Version) == 19)
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 48 8B EC 48 83 EC 60 48 8B FA 48 8B F1 E8").Get();
if (Fortnite_Version >= 23)
{
// User is validated as player, but marked as a spectator. kicking %s
auto addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 08 45 33 FF 48 8B FA 41 8B", false).Get(); // 23.50
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 10 45 33 ED 48 8B FA 41 8B DD 4C 8B F9 89 5D 80 E8 ? ? ? ? 48 8B D0 48 89 44 24").Get(); // 24.40
return addr;
}
if (Engine_Version >= 423 || Engine_Version <= 425) // && instead of || ??
return Memcury::Scanner::FindPattern("48 89 5C 24 08 48 89 74 24 10 57 48 83 EC ? 49 8B F0 48 8B DA 48 85 D2").Get();
@@ -405,7 +415,14 @@ static inline uint64 FindPickSupplyDropLocation()
static inline uint64 FindPauseBeaconRequests()
{
if (Engine_Version == 500)
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 33 ED 48 8B F1 84 D2 74 27 80 3D").Get();
{
auto ref = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 33 ED 48 8B F1 84 D2 74 27 80 3D", false).Get();
if (!ref) // just 27 -> 35 but im too scared to change
ref = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 33 ED 48 8B F1 84 D2 74 35 80 3D ? ? ? ? ? 72 13 48 8D 15").Get(); // 24.40
return ref;
}
if (Engine_Version == 427)
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 30 33 F6 48 8B F9 84 D2 74").Get();
@@ -528,20 +545,6 @@ uint64 FindGetSessionInterface();
uint64 FindGetPlayerViewpoint();
uint64 ApplyGameSessionPatch();
static inline uint64 FindFree()
{
uint64 addr = 0;
if (Engine_Version <= 420) // 3.3, 4.1, 4.5
addr = Memcury::Scanner::FindPattern("48 85 C9 74 1D 4C 8B 05 ? ? ? ? 4D 85 C0 0F 84").Get();
else if (Engine_Version >= 421 && Engine_Version <= 426)
addr = Memcury::Scanner::FindPattern("48 85 C9 74 2E 53 48 83 EC 20 48 8B D9").Get();
else if (Engine_Version >= 427)
addr = Memcury::Scanner::FindPattern("48 85 C9 0F 84 ? ? ? ? 53 48 83 EC 20 48 89 7C 24 ? 48 8B D9 48 8B 3D").Get();
return addr;
}
static inline uint64 FindStepExplicitProperty()
{
return Memcury::Scanner::FindPattern("41 8B 40 ? 4D 8B C8").Get();
@@ -559,8 +562,10 @@ static inline uint64 FindIsNetRelevantForOffset()
return 0x4D0 / 8; // checked 21.00
if (std::floor(Fortnite_Version) == 22)
return 0x4D8 / 8; // checked 22.30
if (Fortnite_Version >= 23)
if (std::floor(Fortnite_Version) == 23)
return 0x4E0 / 8; // checked 23.40
if (Fortnite_Version >= 24)
return 0x500 / 8; // checked 24.40
return 0;
}
@@ -571,10 +576,13 @@ static inline uint64 FindActorChannelClose()
if (!StringRef.Get()) // 22.30 atleast (it just changed but also functionized im too lazy rn)
{
auto addr = Memcury::Scanner::FindPattern("40 55 53 56 57 41 56 48 8B EC 48 83 EC 40 4C 8B 41 68 40 8A F2 48 8B 51 28 48 8B D9 48 8D 4D 48 E8 ? ? ? ? 80").Get(); // 20.40
auto addr = Memcury::Scanner::FindPattern("40 55 53 56 57 41 56 48 8B EC 48 83 EC 40 4C 8B 41 68 40 8A F2 48 8B 51 28 48 8B D9 48 8D 4D 48 E8 ? ? ? ? 80", false).Get(); // 20.40
if (!addr) // TODO: Check 48 89 5C 24 ? 55 56 57 48 83 EC ? 4C 8B 41 ? 40 8A F2 48 8B 51 ? 48 8B
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 48 83 EC ? 4C 8B 41 ? 40 8A F2 48 8B 51 ? 48 8B ? 48 8D 4C 24 ? E8").Get(); // 22.30 + 23.40
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 48 83 EC ? 4C 8B 41 ? 40 8A F2 48 8B 51 ? 48 8B ? 48 8D 4C 24 ? E8", false).Get(); // 22.30 + 23.40
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 48 89 7C 24 ? 55 41 56 41 57 48 8B EC 48 83 EC 40 4C 8B 41 68 44 8A FA 48 8B").Get(); // 24.40
return addr;
}
@@ -626,6 +634,8 @@ static inline uint64 FindSetWorld()
SetWorldIndex = 0x7C; // 21.00
if (Fortnite_Season == 22 || Fortnite_Season == 23)
SetWorldIndex = 0x7B; // 22.30 & 23.50
if (Fortnite_Season == 24)
SetWorldIndex = 0x7D; // 24.40
if (!SetWorldIndex)
{
@@ -639,7 +649,14 @@ static inline uint64 FindSetWorld()
static inline uint64 FindInitListen()
{
if (Engine_Version == 500)
return Memcury::Scanner::FindPattern("4C 8B DC 49 89 5B 10 49 89 73 18 57 48 83 EC 50 48 8B BC 24 ?? ?? ?? ?? 49 8B F0 48 8B").Get();
{
auto addr = Memcury::Scanner::FindPattern("4C 8B DC 49 89 5B 10 49 89 73 18 57 48 83 EC 50 48 8B BC 24 ?? ?? ?? ?? 49 8B F0 48 8B", false).Get();
if (!addr)
addr = Memcury::Scanner::FindPattern("4C 8B DC 49 89 5B 08 49 89 73 10 57 48 83 EC 40 48 8B 7C 24 ? 49 8B F0 48 8B 01 48 8B D9 49 89 7B E0 45").Get(); // 24.40
return addr;
}
if (Engine_Version >= 427)
return Memcury::Scanner::FindPattern("4C 8B DC 49 89 5B 08 49 89 73 10 57 48 83 EC 50 48 8B BC 24 ? ? ? ? 49 8B F0 48 8B 01 48 8B").Get();
@@ -650,14 +667,9 @@ static inline uint64 FindInitListen()
static inline uint64 FindOnDamageServer()
{
if (Fortnite_Version >= 20) // 8B 15 on name ref???
if (Fortnite_Version >= 20) // pawn has one too gg
{
auto addr = Memcury::Scanner::FindPattern("E8 ? ? ? ? 41 39 B4 24").RelativeOffset(1).Get(); // 20.40 (not 21.00)
if (!addr)
addr = Memcury::Scanner::FindPattern("E8 ? ? ? ? 4C 8D 96 ? ? ? ? 49 8B CA E8 ? ? ? ? 45 33 E4").RelativeOffset(1).Get(); // 22.3
return addr;
return 0;
}
auto Addr = FindFunctionCall(L"OnDamageServer",
@@ -1025,7 +1037,7 @@ static inline uint64 FindSetTimer()
static inline uint64 FindEnterAircraft()
{
auto Addr = Memcury::Scanner::FindStringRef(L"EnterAircraft: [%s] is attempting to enter aircraft after having already exited.", true, 0, Engine_Version >= 500).Get();
auto Addr = Memcury::Scanner::FindStringRef(L"EnterAircraft: [%s] is attempting to enter aircraft after having already exited.", true, 0, Engine_Version >= 500 && Fortnite_Version < 24).Get();
for (int i = 0; i < 1000; i++)
{
@@ -1235,7 +1247,7 @@ static inline uint64 FindRemoveFromAlivePlayers()
Addrr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena: Player [%s] removed from alive players list (Team [%d]). Player count is now [%d]. PlayerBots count is now [%d]. Team count is now [%d].", false).Get();
if (!Addrr)
Addrr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena::RemoveFromAlivePlayers: Player [%s] PC [%s] removed from alive players list (Team [%d]). Player count is now [%d]. PlayerBots count is now [%d]. Team count is now [%d].", true, 0, Fortnite_Version >= 16).Get(); // checked on 16.40
Addrr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena::RemoveFromAlivePlayers: Player [%s] PC [%s] removed from alive players list (Team [%d]). Player count is now [%d]. PlayerBots count is now [%d]. Team count is now [%d].", true, 0, Fortnite_Version >= 16 && Fortnite_Version < 24).Get(); // checked on 16.40
for (int i = 0; i < 2000; i++)
{
@@ -1677,7 +1689,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 >= 16).Get(); // checked 16.40
auto Addrr = Memcury::Scanner::FindStringRef(L"InternalTryActivateAbility called with invalid Handle! ASC: %s. AvatarActor: %s", true, 0, Fortnite_Version >= 16 && Fortnite_Version < 24).Get(); // checked 16.40
for (int i = 0; i < 1000; i++)
{
@@ -1686,7 +1698,7 @@ static inline uint64 FindInternalTryActivateAbility()
return Addrr - i;
}
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x4C && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0x4C)
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x4C && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0x4C) // checked on 24.40
{
return Addrr - i;
}
@@ -1715,6 +1727,11 @@ static inline uint64 FindCanActivateAbility()
auto Addrr = Memcury::Scanner::FindStringRef(L"CanActivateAbility %s failed, blueprint refused", true, 0, Engine_Version >= 500).Get();
if (!Addrr)
{
return 0;
}
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)
@@ -1748,6 +1765,11 @@ static inline uint64 FindGiveAbilityAndActivateOnce()
auto Addrr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500).Get();
if (!Addrr)
{
return 0;
}
for (int i = 0; i < 1000; i++)
{
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55)
@@ -1788,6 +1810,9 @@ static inline uint64 FindGiveAbility()
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 56 41 57 48 8B EC 48 83 EC ? 49 8B 40").Get(); // 22.3
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 56 48 83 EC 30 49 8B 40 10 45 33 F6 49 8B E8 48 8B F2 48 8B").Get(); // 24.40
return addr;
}
@@ -1841,6 +1866,7 @@ static inline uint64 FindReplaceBuildingActor()
return FindBytes(StringRef, BytesToFind, 1000, 0, true);
}
// UNetworkPredictionInterface
static inline uint64 FindSendClientAdjustment()
{
auto addr = Memcury::Scanner::FindPattern("40 53 48 83 EC 20 48 8B 99 ? ? ? ? 48 39 99 ? ? ? ? 74 0A 48 83 B9", false).Get();
@@ -1849,7 +1875,10 @@ static inline uint64 FindSendClientAdjustment()
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC ? 8B 91 ? ? ? ? 48 8B D9 83 FA", false).Get(); // 22.3 (this was painful to find)
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 83 3D ? ? ? ? ? 48 8B D9 75 57 8B 91").Get();
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 83 3D ? ? ? ? ? 48 8B D9 75 57 8B 91", false).Get();
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 83 3D ? ? ? ? ? 48 8B D9 75 5A 8B 91 ? ? ? ? 83 FA FF 74 46 3B 91").Get(); // 24.40
return addr;
}
@@ -1875,10 +1904,10 @@ static inline uint64 FindReplicateActor()
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();
if (Fortnite_Version >= 21)
{
auto addr = 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 ? ? ? ? 45 33 FF 4C 8D 69 68 44 38 3D", false).Get();
auto strRef = Memcury::Scanner::FindStringRef(L"STAT_NetReplicateActorTime");
return strRef.ScanFor({ 0x48, 0x8B, 0xC4 }, false).Get();
if (!addr)
addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 ? 48 89 70 ? 48 89 78 ? 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 45 33 FF 4C 8D 61 ? 44 38 3D ? ? ? ? 48 8D 05 ? ? ? ? 48 8B", false).Get(); // 22.30
auto addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 ? 48 89 70 ? 48 89 78 ? 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 45 33 FF 4C 8D ? ? 44 38 3D", false).Get(); // 22.3
if (!addr)
addr = Memcury::Scanner::FindPattern("40 55 41 54 41 55 41 56 41 57 48 81 EC ? ? ? ? 48 8D 6C 24 ? 48 89 9D ? ? ? ? 48 89 B5 ? ? ? ? 48 89 BD ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C5 48 89 85 ? ? ? ? 45 33 E4 4C 8D 69 68 44 38 25 ? ? ? ? 48 8D 05 ? ? ? ? 48 8B F9 49 8B 4D").Get(); // 23.40
@@ -1894,7 +1923,14 @@ static inline uint64 FindCreateChannel()
if (Fortnite_Version <= 3.3)
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) // 21.00
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();
{
auto addr = 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", false).Get();
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 30 45 33 E4 48 8D 05 ? ? ? ? 44 38 25 ? ? ? ? 41 8B").Get();
return addr;
}
return 0;
}
@@ -1924,7 +1960,10 @@ static inline uint64 FindSetChannelActor()
auto addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 33 FF 4C 8D 35 ? ? ? ? 89 BD", false).Get();
if (!addr)
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 45 33 F6 48 8D").Get(); // 22.30 & 23.40
addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 55 56 57 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 45 33 F6 48 8D", false).Get(); // 22.30 & 23.40
if (!addr)
addr = 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 ? ? ? ? 45 33 ED 48 8D 35 ? ? ? ? 44 89 AD ? ? ? ? 48 8B D9 48 8B 41 28 45 8B E0 48 8B FA 45 8B").Get(); // 24.40
return addr;
}

View File

@@ -152,7 +152,7 @@ inline __int64 GetFunctionIdxOrPtr(UFunction* Function, bool bBreakWhenHitRet =
auto NativeAddr = __int64(Function->GetFunc());
LOG_INFO(LogDev, "Getting name!")
LOG_INFO(LogDev, "[GetFunctionIdxOrPtr] Getting name!")
auto FuncName = Function->GetName();

View File

@@ -66,8 +66,9 @@ template <typename T = UObject>
static inline T* FindObject(const std::string& NameStr, UClass* Class = nullptr, UObject* Outer = nullptr)
{
std::string name = NameStr;
auto NameCWSTR = std::wstring(name.begin(), name.end()).c_str();
return StaticFindObject<T>(Class, Outer, NameCWSTR);
auto NameWStr = std::wstring(name.begin(), name.end());
auto NameCWStr = NameWStr.c_str();
return StaticFindObject<T>(Class, Outer, NameCWStr);
}
static inline UEngine* GetEngine()
@@ -78,7 +79,7 @@ static inline UEngine* GetEngine()
{
__int64 starting = 2147482000;
for (__int64 i = starting; i < (starting + 1000); i++)
for (__int64 i = starting; i < (starting + 1000); ++i)
{
if (Engine = FindObject<UEngine>("/Engine/Transient.FortEngine_" + std::to_string(i)))
break;
@@ -162,6 +163,8 @@ inline uint8_t GetFieldMask(void* Property, int additional = 0)
// 3 = sizeof(FieldSize) + sizeof(ByteOffset) + sizeof(ByteMask)
if (Fortnite_Version >= 24)
return *(uint8_t*)(__int64(Property) + (0x6B + additional));
if (Engine_Version <= 424 || Fortnite_Version >= 20)
return *(uint8_t*)(__int64(Property) + (112 + 3 + additional));
else if (Engine_Version >= 425)
@@ -292,7 +295,7 @@ inline void* FindPropertyStruct(const std::string& StructName, const std::string
return Property;
}
Property = Engine_Version >= 425 ? *(void**)(__int64(Property) + 0x20) : ((UField*)Property)->Next;
Property = GetNext(Property);
PropName = Property ? GetFNameOfProp(Property)->ToString() : "";
}
}
@@ -413,6 +416,7 @@ namespace MemberOffsets
namespace DeathInfo
{
extern inline int bDBNO = 0, Downer = 0, FinisherOrDowner = 0, DeathCause = 0, Distance = 0, DeathLocation = 0, bInitialized = 0, DeathTags = 0;
extern inline bool bIsWeakFinisherOrDowner = false;
}
}

7
vendor/memcury.h vendored
View File

@@ -853,6 +853,13 @@
if (rdataSection.isInSection(stringAdd))
{
auto strBytes = stringAdd.GetAs<std::uint8_t*>();
auto pointerToRef = *(LPVOID*)strBytes;
if (rdataSection.isInSection(pointerToRef)) // Credit: Ender
{
strBytes = (std::uint8_t*)pointerToRef;
stringAdd = PE::Address(pointerToRef);
}
// Check if the first char is printable
if (ASM::byteIsAscii(strBytes[0]))