From bd4a8da94f27a12bd7cd585492c12f33ce3ae71d Mon Sep 17 00:00:00 2001 From: Milxnor Date: Mon, 3 Apr 2023 21:13:34 -0400 Subject: [PATCH] make commands actually reply to console --- Project Reboot 3.0/EngineTypes.cpp | 14 ++++ Project Reboot 3.0/EngineTypes.h | 6 ++ Project Reboot 3.0/FortGameModeAthena.cpp | 2 +- Project Reboot 3.0/FortPlayerPawnAthena.cpp | 76 +++++++++++++++++++ Project Reboot 3.0/FortPlayerPawnAthena.h | 11 +++ Project Reboot 3.0/NetDriver.cpp | 2 +- Project Reboot 3.0/Project Reboot 3.0.vcxproj | 3 + .../Project Reboot 3.0.vcxproj.filters | 9 +++ Project Reboot 3.0/Stack.h | 24 ++++-- Project Reboot 3.0/addresses.cpp | 17 ++++- Project Reboot 3.0/addresses.h | 2 + Project Reboot 3.0/commands.h | 16 +++- Project Reboot 3.0/dllmain.cpp | 6 ++ Project Reboot 3.0/finder.h | 5 ++ 14 files changed, 182 insertions(+), 11 deletions(-) create mode 100644 Project Reboot 3.0/EngineTypes.cpp create mode 100644 Project Reboot 3.0/FortPlayerPawnAthena.cpp create mode 100644 Project Reboot 3.0/FortPlayerPawnAthena.h diff --git a/Project Reboot 3.0/EngineTypes.cpp b/Project Reboot 3.0/EngineTypes.cpp new file mode 100644 index 0000000..dda784f --- /dev/null +++ b/Project Reboot 3.0/EngineTypes.cpp @@ -0,0 +1,14 @@ +#include "EngineTypes.h" + +#include "reboot.h" + +UStruct* FHitResult::GetStruct() +{ + static auto Struct = FindObject("/Script/Engine.HitResult"); + return Struct; +} + +int FHitResult::GetStructSize() +{ + return GetStruct()->GetPropertiesSize(); +} \ No newline at end of file diff --git a/Project Reboot 3.0/EngineTypes.h b/Project Reboot 3.0/EngineTypes.h index f574f4f..eed5c0d 100644 --- a/Project Reboot 3.0/EngineTypes.h +++ b/Project Reboot 3.0/EngineTypes.h @@ -9,4 +9,10 @@ enum class ESpawnActorCollisionHandlingMethod : uint8 AdjustIfPossibleButAlwaysSpawn, AdjustIfPossibleButDontSpawnIfColliding, DontSpawnIfColliding +}; + +struct FHitResult +{ + static class UStruct* GetStruct(); + static int GetStructSize(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index e121209..01c2d59 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -693,7 +693,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena bool bPrintWarmup = false; - if (false) + if (Engine_Version != 419) { for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++) { diff --git a/Project Reboot 3.0/FortPlayerPawnAthena.cpp b/Project Reboot 3.0/FortPlayerPawnAthena.cpp new file mode 100644 index 0000000..e3f176c --- /dev/null +++ b/Project Reboot 3.0/FortPlayerPawnAthena.cpp @@ -0,0 +1,76 @@ +#include "FortPlayerPawnAthena.h" +#include "FortInventory.h" +#include "FortPlayerControllerAthena.h" + +void AFortPlayerPawnAthena::OnCapsuleBeginOverlapHook(UObject* Context, FFrame* Stack, void* Ret) +{ + using UPrimitiveComponent = UObject; + + auto Pawn = (AFortPlayerPawnAthena*)Context; + UPrimitiveComponent* OverlappedComp; + AActor* OtherActor; + UPrimitiveComponent* OtherComp; + int OtherBodyIndex; + bool bFromSweep; + FHitResult SweepResult = *Alloc(FHitResult::GetStructSize()); + + LOG_INFO(LogDev, "OnCapsuleBeginOverlapHook!"); + + Stack->StepCompiledIn(&OverlappedComp); + Stack->StepCompiledIn(&OtherActor); + Stack->StepCompiledIn(&OtherComp); + Stack->StepCompiledIn(&OtherBodyIndex); + Stack->StepCompiledIn(&bFromSweep); + Stack->StepCompiledIn(&SweepResult); + + if (auto Pickup = Cast(OtherActor)) + { + static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup"); + + if (Pickup->Get(PawnWhoDroppedPickupOffset) != Pawn) + { + auto ItemDefinition = Pickup->GetPrimaryPickupItemEntry()->GetItemDefinition(); + + auto PlayerController = Cast(Pawn->GetController(), false); + auto& ItemInstances = PlayerController->GetWorldInventory()->GetItemList().GetItemInstances(); + + bool ItemDefGoingInPrimary = IsPrimaryQuickbar(ItemDefinition); + int PrimarySlotsFilled = 0; + bool bCanStack = false; + bool bFoundStack = false; + + for (int i = 0; i < ItemInstances.Num(); i++) + { + auto ItemInstance = ItemInstances.at(i); + auto CurrentItemDefinition = ItemInstance->GetItemEntry()->GetItemDefinition(); + + if (ItemDefGoingInPrimary && IsPrimaryQuickbar(CurrentItemDefinition)) + PrimarySlotsFilled++; + + bool bIsInventoryFull = (PrimarySlotsFilled /* - 6 */) >= 5; + + if (CurrentItemDefinition == ItemDefinition) + { + bFoundStack = true; + + if (ItemInstance->GetItemEntry()->GetCount() < ItemDefinition->GetMaxStackSize()) + { + bCanStack = true; + break; + } + } + + if (bIsInventoryFull) + return OnCapsuleBeginOverlapOriginal(Context, Stack, Ret); + } + + // std::cout << "bCanStack: " << bCanStack << '\n'; + // std::cout << "bFoundStack: " << bFoundStack << '\n'; + + if (!bCanStack ? (!bFoundStack ? true : ItemDefinition->DoesAllowMultipleStacks()) : true) + ServerHandlePickupHook(Pawn, Pickup, 0.4, FVector(), true); + } + } + + return OnCapsuleBeginOverlapOriginal(Context, Stack, Ret); +} \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerPawnAthena.h b/Project Reboot 3.0/FortPlayerPawnAthena.h new file mode 100644 index 0000000..37c591c --- /dev/null +++ b/Project Reboot 3.0/FortPlayerPawnAthena.h @@ -0,0 +1,11 @@ +#pragma once + +#include "FortPlayerPawn.h" + +class AFortPlayerPawnAthena : public AFortPlayerPawn +{ +public: + static inline void (*OnCapsuleBeginOverlapOriginal)(UObject* Context, FFrame* Stack, void* Ret); + + static void OnCapsuleBeginOverlapHook(UObject* Context, FFrame* Stack, void* Ret); +}; \ No newline at end of file diff --git a/Project Reboot 3.0/NetDriver.cpp b/Project Reboot 3.0/NetDriver.cpp index 46c4dd9..36e6900 100644 --- a/Project Reboot 3.0/NetDriver.cpp +++ b/Project Reboot 3.0/NetDriver.cpp @@ -10,7 +10,7 @@ FNetworkObjectList& UNetDriver::GetNetworkObjectList() { - return *(*(TSharedPtr*)(__int64(this) + 0x490)); + return *(*(TSharedPtr*)(__int64(this) + Offsets::NetworkObjectList)); } void UNetDriver::RemoveNetworkActor(AActor* Actor) diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj b/Project Reboot 3.0/Project Reboot 3.0.vcxproj index 467f334..8a5737f 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -177,6 +177,7 @@ + @@ -198,6 +199,7 @@ + @@ -271,6 +273,7 @@ + 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 ea2cbe4..5e25c34 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -173,6 +173,12 @@ Engine\Source\Runtime\Engine\Private + + FortniteGame\Source\FortniteGame\Private\Pawns + + + Engine\Source\Runtime\Engine\Private + @@ -497,6 +503,9 @@ Engine\Source\Runtime\Engine\Classes\Engine + + FortniteGame\Source\FortniteGame\Public\Pawns + diff --git a/Project Reboot 3.0/Stack.h b/Project Reboot 3.0/Stack.h index 54a8e81..e30c9c6 100644 --- a/Project Reboot 3.0/Stack.h +++ b/Project Reboot 3.0/Stack.h @@ -18,16 +18,26 @@ public: // MORE STUFF HERE - void* MostRecentProperty; - uint8_t* MostRecentPropertyAddress; + void* MostRecentProperty; // 48 + uint8_t* MostRecentPropertyAddress; // 56 + + void*& GetPropertyChainForCompiledIn() + { + static auto PropertyChainForCompiledInOffset = 0x80; + return *(void**)(__int64(this) + PropertyChainForCompiledInOffset); + } uint8_t*& GetMostRecentPropertyAddress() { auto off = (void*)(&((struct FFrame*)NULL)->MostRecentPropertyAddress); LOG_INFO(LogDev, "{}", off); return MostRecentPropertyAddress; - static auto MostRecentPropertyAddressOffset = 56; - return *(uint8_t**)(__int64(this) + MostRecentPropertyAddressOffset); + } + + void StepExplicitProperty(void* const Result, void* Property) + { + static void (*StepExplicitPropertyOriginal)(__int64 frame, void* const Result, void* Property) = decltype(StepExplicitPropertyOriginal)(Addresses::FrameStepExplicitProperty); + StepExplicitPropertyOriginal(__int64(this), Result, Property); } void Step(UObject* Context, RESULT_DECL) @@ -39,7 +49,7 @@ public: // (GNatives[B])(Context, *this, RESULT_PARAM); } - __forceinline void StepCompiledIn(void* Result/*, const FFieldClass* ExpectedPropertyType*/) // https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Source/Runtime/CoreUObject/Public/UObject/Stack.h#L444 + __forceinline void StepCompiledIn(void* const Result/*, const FFieldClass* ExpectedPropertyType*/) // https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Source/Runtime/CoreUObject/Public/UObject/Stack.h#L444 { if (Code) { @@ -53,6 +63,10 @@ public: FProperty* Property = (FProperty*)PropertyChainForCompiledIn; PropertyChainForCompiledIn = Property->Next; StepExplicitProperty(Result, Property); */ + + auto& Property = GetPropertyChainForCompiledIn(); + GetPropertyChainForCompiledIn() = Engine_Version >= 425 ? *(void**)(__int64(Property) + 0x20) : ((UField*)Property)->Next; + StepExplicitProperty(Result, Property); } } diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 62d15ce..d95fe8e 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -239,6 +239,9 @@ void Addresses::FindAll() LOG_INFO(LogDev, "Finding ActorChannelClose"); Addresses::ActorChannelClose = FindActorChannelClose(); + LOG_INFO(LogDev, "Finding StepExplicitProperty"); + Addresses::FrameStepExplicitProperty = FindStepExplicitProperty(); + LOG_INFO(LogDev, "Finished finding!"); } @@ -291,6 +294,7 @@ void Addresses::Print() LOG_INFO(LogDev, "GetMaxTickRate: 0x{:x}", GetMaxTickRate - Base); LOG_INFO(LogDev, "RemoveFromAlivePlayers: 0x{:x}", RemoveFromAlivePlayers - Base); LOG_INFO(LogDev, "ActorChannelClose: 0x{:x}", ActorChannelClose - Base); + LOG_INFO(LogDev, "FrameStepExplicitProperty: 0x{:x}", FrameStepExplicitProperty - Base); } void Offsets::FindAll() @@ -332,13 +336,24 @@ void Offsets::FindAll() Offsets::ServerReplicateActors = 0x67; // checked onb 22.30 if (Engine_Version == 416) // checked on 1.7.2 & 1.8 + { + Offsets::NetworkObjectList = 0x3F8; Offsets::ReplicationFrame = 0x288; + } if (Fortnite_Version == 2.42) + { Offsets::ReplicationFrame = 0x2C8; + } if (Fortnite_Version == 2.5) + { + Offsets::NetworkObjectList = 0x4F0; Offsets::ReplicationFrame = 0x328; - if (Fortnite_Version == 1.11) + } + if (Engine_Version == 419) // checked 2.4.2 & 1.11 + { + Offsets::NetworkObjectList = 0x490; Offsets::ReplicationFrame = 0x2C8; + } Offsets::IsNetRelevantFor = FindIsNetRelevantForOffset(); } diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index bf6a19e..992226b 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -53,6 +53,7 @@ namespace Addresses extern inline uint64 OnRep_ZiplineState = 0; extern inline uint64 RemoveFromAlivePlayers = 0; extern inline uint64 ActorChannelClose = 0; + extern inline uint64 FrameStepExplicitProperty = 0; void SetupVersion(); // Finds Engine Version void FindAll(); @@ -72,6 +73,7 @@ namespace Offsets extern inline uint64 ServerReplicateActors = 0; extern inline uint64 ReplicationFrame = 0; extern inline uint64 IsNetRelevantFor = 0; + extern inline uint64 NetworkObjectList = 0; void FindAll(); void Print(); diff --git a/Project Reboot 3.0/commands.h b/Project Reboot 3.0/commands.h index d6edb77..7e58104 100644 --- a/Project Reboot 3.0/commands.h +++ b/Project Reboot 3.0/commands.h @@ -24,9 +24,18 @@ inline void SendMessageToConsole(AFortPlayerController* PlayerController, const float MsgLifetime = 1; // unused by ue FName TypeName = FName(); // auto set to "Event" - // PlayerController->ClientMessage(Msg, TypeName, MsgLifetime); - auto brah = Msg.ToString(); - LOG_INFO(LogDev, "{}", brah); + static auto ClientMessageFn = FindObject("/Script/Engine.PlayerController.ClientMessage"); + struct + { + FString S; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + FName Type; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + float MsgLifeTime; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + } APlayerController_ClientMessage_Params{Msg, TypeName, MsgLifetime}; + + PlayerController->ProcessEvent(ClientMessageFn, &APlayerController_ClientMessage_Params); + + // auto brah = Msg.ToString(); + // LOG_INFO(LogDev, "{}", brah); } void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) @@ -435,6 +444,7 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) } Pawn->TeleportTo(FVector(X, Y, Z), Pawn->GetActorRotation()); + SendMessageToConsole(PlayerController, L"Teleported!"); } } } \ No newline at end of file diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index a39f44e..448649a 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -25,6 +25,7 @@ #include "KismetSystemLibrary.h" #include "die.h" #include "InventoryManagementLibrary.h" +#include "FortPlayerPawnAthena.h" enum ENetMode { @@ -330,6 +331,9 @@ DWORD WINAPI Main(LPVOID) } } + auto off = (void*)(&((struct FFrame*)NULL)->MostRecentPropertyAddress); + LOG_INFO(LogDev, "{}", off); + LOG_INFO(LogDev, "OnPlayImpactFX: 0x{:x}", OnPlayImpactFXAddr - __int64(GetModuleHandleW(0))); Hooking::MinHook::Hook((PVOID)OnPlayImpactFXAddr, AFortWeapon::OnPlayImpactFXHook, (PVOID*)&AFortWeapon::OnPlayImpactFXOriginal); @@ -370,6 +374,8 @@ DWORD WINAPI Main(LPVOID) 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); + /* Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawnAthena.OnCapsuleBeginOverlap") ? FindObject(L"/Script/FortniteGame.FortPlayerPawnAthena.OnCapsuleBeginOverlap") : FindObject(L"/Script/FortniteGame.FortPlayerPawn.OnCapsuleBeginOverlap"), + AFortPlayerPawnAthena::OnCapsuleBeginOverlapHook, (PVOID*)&AFortPlayerPawnAthena::OnCapsuleBeginOverlapOriginal, false, true); */ if (Addresses::FrameStep) // put all non rpc exec hooks in this scope { diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 8899951..5a17c60 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -363,6 +363,11 @@ static inline uint64 FindGetPlayerViewpoint() return 0; } +static inline uint64 FindStepExplicitProperty() +{ + return Memcury::Scanner::FindPattern("41 8B 40 ? 4D 8B C8").Get(); +} + static inline uint64 FindIsNetRelevantForOffset() { if (Engine_Version == 416) // checked on 1.7.2 & 1.8