From 5e2a74764a547748631ac8a0ab4f5c795213d02d Mon Sep 17 00:00:00 2001 From: Milxnor Date: Wed, 21 Jun 2023 10:51:24 -0400 Subject: [PATCH] disable rebooting again fixed looting bug, fixed parachute not auto deploying on some builds --- Project Reboot 3.0/AthenaMarkerComponent.cpp | 29 +-- Project Reboot 3.0/AthenaMarkerComponent.h | 2 +- Project Reboot 3.0/AthenaPlayerMatchReport.h | 55 ++++++ Project Reboot 3.0/FortGameModeAthena.cpp | 19 +- .../FortGameSessionDedicatedAthena.cpp | 25 ++- .../FortGameSessionDedicatedAthena.h | 2 +- Project Reboot 3.0/FortGameStateAthena.cpp | 4 +- Project Reboot 3.0/FortLootPackage.cpp | 2 +- Project Reboot 3.0/FortPlayerController.cpp | 43 ++++- .../FortPlayerControllerAthena.h | 20 ++ Project Reboot 3.0/OnlineReplStructs.h | 30 +-- Project Reboot 3.0/Player.h | 6 + Project Reboot 3.0/PlayerController.h | 6 + Project Reboot 3.0/Project Reboot 3.0.vcxproj | 2 + .../Project Reboot 3.0.vcxproj.filters | 9 + Project Reboot 3.0/addresses.cpp | 1 + Project Reboot 3.0/addresses.h | 1 + Project Reboot 3.0/die.h | 49 ++--- Project Reboot 3.0/dllmain.cpp | 2 +- Project Reboot 3.0/finder.h | 2 +- Project Reboot 3.0/gui.h | 69 ++++++- Project Reboot 3.0/log.h | 1 + Project Reboot 3.0/objectviewer.cpp | 175 ++++++++++++++++++ Project Reboot 3.0/objectviewer.h | 24 +++ 24 files changed, 479 insertions(+), 99 deletions(-) create mode 100644 Project Reboot 3.0/AthenaPlayerMatchReport.h create mode 100644 Project Reboot 3.0/objectviewer.cpp diff --git a/Project Reboot 3.0/AthenaMarkerComponent.cpp b/Project Reboot 3.0/AthenaMarkerComponent.cpp index c50f2e4..9a6c52d 100644 --- a/Project Reboot 3.0/AthenaMarkerComponent.cpp +++ b/Project Reboot 3.0/AthenaMarkerComponent.cpp @@ -35,6 +35,7 @@ void UAthenaMarkerComponent::ServerAddMapMarkerHook(UAthenaMarkerComponent* Mark MarkerData->GetMarkerType() = MarkerRequestPtr->GetMarkerType(); MarkerData->GetOwner() = PlayerState; MarkerData->GetWorldNormal() = MarkerRequestPtr->GetWorldNormal(); + if (WorldPositionOffset != -1) MarkerData->GetWorldPosition() = MarkerRequestPtr->GetWorldPosition(); if (WorldPositionOffset != -1) @@ -54,30 +55,6 @@ void UAthenaMarkerComponent::ServerAddMapMarkerHook(UAthenaMarkerComponent* Mark ((TSoftObjectPtr*)(__int64(MarkerData->GetCustomDisplayInfo()) + IconOffset))->SoftObjectPtr.WeakPtr.ObjectSerialNumber = 0; *(FText*)(__int64(MarkerData->GetCustomDisplayInfo()) + DisplayNameOffset) = UKismetTextLibrary::Conv_StringToText(L""); - /* if (MarkerRequest.MarkedActor) - { - MarkerData.MarkedActor.WeakPtr.ObjectIndex = MarkerRequest.MarkedActor->InternalIndex; - MarkerData.MarkedActor.WeakPtr.ObjectSerialNumber = 0; - - MarkerData.MarkedActorClass.WeakPtr.ObjectIndex = MarkerRequest.MarkedActor->Class->InternalIndex; - MarkerData.MarkedActorClass.WeakPtr.ObjectSerialNumber = 0; - - char (*WtfSkidda)(UAthenaMarkerComponent * a1, AActor * a2, FFortWorldMarkerData & MarkerData) = decltype(WtfSkidda)(__int64(GetModuleHandleW(0)) + 0x1297E00); - (int)WtfSkidda(PlayerController->MarkerComponent, MarkerRequest.MarkedActor, MarkerData); - // std::cout << "WtfSkidda: " << (int)WtfSkidda(PlayerController->MarkerComponent, MarkerRequest.MarkedActor, MarkerData) << '\n'; - } - - if (MarkerData.MarkerType == EFortWorldMarkerType::Item) - { - if (auto Pickup = Cast(MarkerRequest.MarkedActor)) - { - MarkerData.ItemDefinition = Pickup->PrimaryPickupItemEntry.ItemDefinition; - MarkerData.ItemCount = Pickup->PrimaryPickupItemEntry.Count; - } - } */ - - // static void (*Idk)(UAthenaMarkerComponent* MarkerComponent, FFortWorldMarkerData MarkerData) = decltype(Idk)(__int64(GetModuleHandleW(0)) + 0x12A8990); - static auto PlayerTeamOffset = PlayerState->GetOffset("PlayerTeam"); auto PlayerTeam = PlayerState->Get(PlayerTeamOffset); @@ -124,8 +101,8 @@ void UAthenaMarkerComponent::ServerAddMapMarkerHook(UAthenaMarkerComponent* Mark ((FFastArraySerializerItem*)MarkerData)->ReplicationID = -1; ((FFastArraySerializerItem*)MarkerData)->ReplicationKey = -1; - auto& Markers = *(TArray*)(__int64(MarkerStream) + MarkersOffset); - Markers.AddPtr(MarkerData, FFortWorldMarkerData::GetStructSize()); + auto Markers = (TArray*)(__int64(MarkerStream) + MarkersOffset); + Markers->AddPtr(MarkerData, FFortWorldMarkerData::GetStructSize()); MarkerStream->MarkArrayDirty(); } } diff --git a/Project Reboot 3.0/AthenaMarkerComponent.h b/Project Reboot 3.0/AthenaMarkerComponent.h index c120b7f..0cae453 100644 --- a/Project Reboot 3.0/AthenaMarkerComponent.h +++ b/Project Reboot 3.0/AthenaMarkerComponent.h @@ -60,7 +60,7 @@ struct FFortWorldMarkerData { static UStruct* GetStruct() { - static auto Struct = FindObject("/Script/FortniteGame.FortWorldMarkerData"); + static auto Struct = FindObject(L"/Script/FortniteGame.FortWorldMarkerData"); return Struct; } diff --git a/Project Reboot 3.0/AthenaPlayerMatchReport.h b/Project Reboot 3.0/AthenaPlayerMatchReport.h new file mode 100644 index 0000000..037ae10 --- /dev/null +++ b/Project Reboot 3.0/AthenaPlayerMatchReport.h @@ -0,0 +1,55 @@ +#pragma once + +#include "reboot.h" + +struct FAthenaMatchTeamStats +{ + static UStruct* GetStruct() + { + static auto Struct = FindObject(L"/Script/FortniteGame.AthenaMatchTeamStats"); + return Struct; + } + + static auto GetStructSize() { return GetStruct()->GetPropertiesSize(); } + + int Place; // 0x0000(0x0004) (Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int TotalPlayers; // 0x0004(0x0004) (Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + + int& GetPlace() + { + return Place; + } + + int& GetTotalPlayers() + { + return TotalPlayers; + } +}; + +class UAthenaPlayerMatchReport : public UObject +{ +public: + bool& HasTeamStats() + { + static auto bHasTeamStatsOffset = GetOffset("bHasTeamStats"); + return Get(bHasTeamStatsOffset); + } + + bool& HasMatchStats() + { + static auto bHasMatchStatsOffset = GetOffset("bHasMatchStats"); + return Get(bHasMatchStatsOffset); + } + + FAthenaMatchTeamStats* GetTeamStats() + { + static auto TeamStatsOffset = GetOffset("TeamStats"); + return GetPtr(TeamStatsOffset); + } + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.AthenaPlayerMatchReport"); + return Class; + } +}; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 259cdc0..2f910ca 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -538,10 +538,18 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game } static auto bWorldIsReadyOffset = GameMode->GetOffset("bWorldIsReady"); - SetBitfield(GameMode->GetPtr(bWorldIsReadyOffset), 1, true); // idk when we actually set this (probably after we listen) + SetBitfield(GameMode->GetPtr(bWorldIsReadyOffset), 1, true); // idk when we actually set this // Calendar::SetSnow(1000); + static auto DefaultRebootMachineHotfixOffset = GameState->GetOffset("DefaultRebootMachineHotfix", false); + + if (DefaultRebootMachineHotfixOffset != -1) + { + LOG_INFO(LogDev, "before: {}", GameState->Get(DefaultRebootMachineHotfixOffset)); + GameState->Get(DefaultRebootMachineHotfixOffset) = 1; // idk i dont think we need to set + } + Globals::bInitializedPlaylist = true; } @@ -790,12 +798,9 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game AllRebootVans.Free(); - static auto DefaultRebootMachineHotfixOffset = GameState->GetOffset("DefaultRebootMachineHotfix", false); - - if (DefaultRebootMachineHotfixOffset != -1) + if (Engine_Version >= 500) { - // LOG_INFO(LogDev, "Beraau: {}", GameState->Get(DefaultRebootMachineHotfixOffset)); - GameState->Get(DefaultRebootMachineHotfixOffset) = 1; // idk i dont think we need to set + GameState->Get("DefaultParachuteDeployTraceForGroundDistance") = 10000; } if (AmountOfBotsToSpawn != 0) @@ -1294,6 +1299,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena } } + NewPlayer->GetMatchReport() = (UAthenaPlayerMatchReport*)UGameplayStatics::SpawnObject(UAthenaPlayerMatchReport::StaticClass(), NewPlayer); // idk when to do this + static auto SquadIdOffset = PlayerStateAthena->GetOffset("SquadId", false); if (SquadIdOffset != -1) diff --git a/Project Reboot 3.0/FortGameSessionDedicatedAthena.cpp b/Project Reboot 3.0/FortGameSessionDedicatedAthena.cpp index 9a047b7..4fb4c0b 100644 --- a/Project Reboot 3.0/FortGameSessionDedicatedAthena.cpp +++ b/Project Reboot 3.0/FortGameSessionDedicatedAthena.cpp @@ -6,12 +6,25 @@ #include "OnlineReplStructs.h" #include "gui.h" -uint8 AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, __int64 UniqueId) +uint8 AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, void* UniqueId) { LOG_INFO(LogDev, "GetSquadIdForCurrentPlayerHook!"); TArray CONTRTOLLERS = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFortPlayerControllerAthena::StaticClass()); + auto OwnerUniqueId = (FUniqueNetIdRepl*)UniqueId; + + LOG_INFO(LogDev, "OwnerUniqueId->GetReplicationBytes().Num(): {}", OwnerUniqueId->GetReplicationBytes().Num()); + + /* + + for (int i = 0; i < OwnerUniqueId->GetReplicationBytes().Num(); i++) + { + LOG_INFO(LogDev, "[{}] Byte: 0x{:x}", i, OwnerUniqueId->GetReplicationBytes().at(i)); + } + + */ + for (int i = 0; i < CONTRTOLLERS.Num(); i++) { auto Controller = (AFortPlayerControllerAthena*)CONTRTOLLERS.at(i); @@ -24,12 +37,14 @@ uint8 AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook(AFortGameS static auto UniqueIdOffset = PlayerState->GetOffset("UniqueId"); - if (IsBadReadPtr(PlayerState->GetPtr(UniqueIdOffset))) - continue; + // if (IsBadReadPtr(PlayerState->GetPtr(UniqueIdOffset))) + // continue; - if (PlayerState->GetPtr(UniqueIdOffset)->IsIdentical((FUniqueNetIdRepl*)&UniqueId)) + LOG_INFO(LogDev, "PS PlayerState->GetPtr(UniqueIdOffset)->GetReplicationBytes().Num(): {}", PlayerState->GetPtr(UniqueIdOffset)->GetReplicationBytes().Num()); + + if (PlayerState->GetPtr(UniqueIdOffset)->IsIdentical(OwnerUniqueId)) { - LOG_INFO(LogDev, "Found!"); + LOG_INFO(LogDev, "Found {}!", PlayerState->GetPlayerName().ToString()); return PlayerState->GetTeamIndex() - NumToSubtractFromSquadId; } } diff --git a/Project Reboot 3.0/FortGameSessionDedicatedAthena.h b/Project Reboot 3.0/FortGameSessionDedicatedAthena.h index 09de8cf..88dcda8 100644 --- a/Project Reboot 3.0/FortGameSessionDedicatedAthena.h +++ b/Project Reboot 3.0/FortGameSessionDedicatedAthena.h @@ -5,5 +5,5 @@ class AFortGameSessionDedicatedAthena : public AActor { public: - static uint8 GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, __int64 UniqueId); + static uint8 GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, void* UniqueId); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameStateAthena.cpp b/Project Reboot 3.0/FortGameStateAthena.cpp index 5d11db0..2095548 100644 --- a/Project Reboot 3.0/FortGameStateAthena.cpp +++ b/Project Reboot 3.0/FortGameStateAthena.cpp @@ -294,8 +294,8 @@ void AFortGameStateAthena::OnRep_PlayersLeft() TeamsArrayContainer* AFortGameStateAthena::GetTeamsArrayContainer() { - // if (!bEnableRebooting) // todo (milxnor) remove when safer - // return nullptr; + if (true) + return nullptr; if (Fortnite_Version < 8.0) // I'm pretty sure it got added on 7.40 but idk if it is structured differently. return nullptr; diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index 1e1e475..9812742 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -154,7 +154,7 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina FFortLootTierData* PickLootTierData(const std::vector& LTDTables, FName LootTierGroup, int ForcedLootTier = -1, FName* OutRowName = nullptr) // Fortnite returns the row name and then finds the tier data again, but I really don't see the point of this. { float LootTier = ForcedLootTier; - float IdkForcedWeightorsomething = 1; + float IdkForcedWeightorsomething = -1; if (LootTier == -1) { diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 4601456..6529837 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -1436,27 +1436,60 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo UFortWeaponItemDefinition* KillerWeaponDef = nullptr; static auto FortProjectileBaseClass = FindObject(L"/Script/FortniteGame.FortProjectileBase"); - LOG_INFO(LogDev, "FortProjectileBaseClass: {}", __int64(FortProjectileBaseClass)); if (DamageCauser) { if (DamageCauser->IsA(FortProjectileBaseClass)) { - // LOG_INFO(LogDev, "From a projectile!"); auto Owner = Cast(DamageCauser->GetOwner()); KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys? } if (auto Weapon = Cast(DamageCauser)) { - // LOG_INFO(LogDev, "From a weapon!"); KillerWeaponDef = Weapon->GetWeaponData(); } } - // LOG_INFO(LogDev, "KillerWeaponDef: {}", KillerWeaponDef ? KillerWeaponDef->GetFullName() : "InvalidObject"); - RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0); + /* + + STATS: + + Note: This isn't the exact order relative to other functions. + + ClientSendMatchStatsForPlayer + ClientSendTeamStatsForPlayer + ClientSendEndBattleRoyaleMatchForPlayer + + */ + + // FAthenaMatchStats.Stats[ERewardSource] // hmm + + /* + + // We need to check if their entire team is dead then I think we send it???? + + auto DeadControllerAthena = Cast(PlayerController); + + if (DeadControllerAthena && FAthenaMatchTeamStats::GetStruct()) + { + auto MatchReport = DeadControllerAthena->GetMatchReport(); + + LOG_INFO(LogDev, "MatchReport: {}", __int64(MatchReport)); + + if (MatchReport) + { + MatchReport->GetTeamStats()->GetPlace() = DeadPlayerState->GetPlace(); + MatchReport->GetTeamStats()->GetTotalPlayers() = AmountOfPlayersWhenBusStart; // hmm + MatchReport->HasTeamStats() = true; + + DeadControllerAthena->ClientSendTeamStatsForPlayer(MatchReport->GetTeamStats()); + } + } + + */ + LOG_INFO(LogDev, "Removed!"); if (Fortnite_Version < 6) // Spectating diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.h b/Project Reboot 3.0/FortPlayerControllerAthena.h index 3f8433d..871696b 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.h +++ b/Project Reboot 3.0/FortPlayerControllerAthena.h @@ -7,6 +7,7 @@ #include "FortKismetLibrary.h" #include "AthenaMarkerComponent.h" #include "FortVolume.h" +#include "AthenaPlayerMatchReport.h" static void ApplyHID(AFortPlayerPawn* Pawn, UObject* HeroDefinition, bool bUseServerChoosePart = false) { @@ -191,6 +192,25 @@ public: this->ProcessEvent(ClientClearDeathNotificationFn); } + UAthenaPlayerMatchReport*& GetMatchReport() + { + static auto MatchReportOffset = GetOffset("MatchReport"); + return Get(MatchReportOffset); + } + + void ClientSendTeamStatsForPlayer(FAthenaMatchTeamStats* TeamStats) + { + static auto ClientSendTeamStatsForPlayerFn = FindObject("/Script/FortniteGame.FortPlayerControllerAthena.ClientSendTeamStatsForPlayer"); + static auto ParamSize = ClientSendTeamStatsForPlayerFn->GetPropertiesSize(); + auto Params = malloc(ParamSize); + + memcpy_s(Params, ParamSize, TeamStats, TeamStats->GetStructSize()); + + this->ProcessEvent(ClientSendTeamStatsForPlayerFn, Params); + + free(Params); + } + void RespawnPlayerAfterDeath(bool bEnterSkydiving) { static auto RespawnPlayerAfterDeathFn = FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.RespawnPlayerAfterDeath"); diff --git a/Project Reboot 3.0/OnlineReplStructs.h b/Project Reboot 3.0/OnlineReplStructs.h index 7f8d0f6..0665abc 100644 --- a/Project Reboot 3.0/OnlineReplStructs.h +++ b/Project Reboot 3.0/OnlineReplStructs.h @@ -24,31 +24,13 @@ struct FUniqueNetIdRepl // : public FUniqueNetIdWrapper return *(TArray*)(__int64(this) + ReplicationBytesOffset); } - bool IsIdentical(FUniqueNetIdRepl* OtherUniqueId) + FORCEINLINE int GetSize() { return GetReplicationBytes().Num(); } // LITERLALY IDK IF THIS IS RIGHT CUZ I CANT FIND IMPL + FORCEINLINE uint8* GetBytes() { return GetReplicationBytes().Data; } // ^^^ + + FORCENOINLINE bool IsIdentical(FUniqueNetIdRepl* OtherUniqueId) { - // idk if this is right but whatever - - bool bTest = true; - - if (this->GetReplicationBytes().Num() >= OtherUniqueId->GetReplicationBytes().Num()) - { - for (int i = 0; i < this->GetReplicationBytes().Num(); i++) - { - if (this->GetReplicationBytes().at(i) != OtherUniqueId->GetReplicationBytes().at(i)) - { - bTest = false; - break; - } - } - } - else - { - bTest = false; - } - - // LOG_INFO(LogDev, "btest: {}", bTest); - - return bTest; + return (GetSize() == OtherUniqueId->GetSize()) && + (memcmp(GetBytes(), OtherUniqueId->GetBytes(), GetSize()) == 0); } void CopyFromAnotherUniqueId(FUniqueNetIdRepl* OtherUniqueId) diff --git a/Project Reboot 3.0/Player.h b/Project Reboot 3.0/Player.h index 0c23047..6f7e918 100644 --- a/Project Reboot 3.0/Player.h +++ b/Project Reboot 3.0/Player.h @@ -11,4 +11,10 @@ public: static auto PlayerControllerOffset = GetOffset("PlayerController"); return Get(PlayerControllerOffset); } + + int& GetCurrentNetSpeed() + { + static auto CurrentNetSpeedOffset = GetOffset("CurrentNetSpeed"); + return Get(CurrentNetSpeedOffset); + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/PlayerController.h b/Project Reboot 3.0/PlayerController.h index 73dbf03..7625905 100644 --- a/Project Reboot 3.0/PlayerController.h +++ b/Project Reboot 3.0/PlayerController.h @@ -16,6 +16,12 @@ public: return this->Get(CheatManagerOffset); } + class UNetConnection*& GetNetConnection() + { + static auto NetConnectionOffset = GetOffset("NetConnection"); + return Get(NetConnectionOffset); + } + void SetPlayerIsWaiting(bool NewValue); void ServerChangeName(FString& S); UCheatManager*& SpawnCheatManager(UClass* CheatManagerClass); diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj b/Project Reboot 3.0/Project Reboot 3.0.vcxproj index 74ee8f1..608a689 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -253,6 +253,7 @@ + @@ -279,6 +280,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 0a0e272..5f83562 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -295,6 +295,9 @@ Reboot\Private + + Reboot\Private + @@ -945,6 +948,9 @@ Reboot\Public + + FortniteGame\Source\FortniteGame\Public\Stats + @@ -1211,6 +1217,9 @@ {702a4ab1-e5e1-46e1-b8cd-2fab1c4fb48c} + + {3c8e3f87-8a4c-4220-b952-39b0e0315e85} + diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index e505a04..f63e505 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -489,6 +489,7 @@ void Offsets::Print() LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors); LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame); LOG_INFO(LogDev, "Script: 0x{:x}", Script); + LOG_INFO(LogDev, "PropertyClass: 0x{:x}", PropertyClass); } void Addresses::Init() diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index fc7bdec..001ddf3 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -97,6 +97,7 @@ namespace Offsets extern inline uint64 NetworkObjectList = 0; extern inline uint64 ClientWorldPackageName = 0; extern inline uint64 Script = 0; + extern inline uint64 PropertyClass = 0; void FindAll(); void Print(); diff --git a/Project Reboot 3.0/die.h b/Project Reboot 3.0/die.h index 1bca3cf..cf5f451 100644 --- a/Project Reboot 3.0/die.h +++ b/Project Reboot 3.0/die.h @@ -16,41 +16,42 @@ static inline void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int O : std::floor(Fortnite_Version) >= 18 ? 0x248 : 0x1F8; // S13-S14 - LOG_INFO(LogDev, "SetZoneToIndexHook!"); + static auto GameMode_SafeZonePhaseOffset = GameModeAthena->GetOffset("SafeZonePhase"); + LOG_INFO(LogDev, "Old SafeZonePhase: {}", GameModeAthena->Get(GameMode_SafeZonePhaseOffset)); auto GameState = Cast(GameModeAthena->GetGameState()); + if (!GameState) + return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); + LOG_INFO(LogDev, "GamePhaseStep: {}", (int)GameState->GetGamePhaseStep()); - if (Globals::bLateGame) + if (false) { - static auto GameMode_SafeZonePhaseOffset = GameModeAthena->GetOffset("SafeZonePhase"); - static auto GameState_SafeZonePhaseOffset = GameState->GetOffset("SafeZonePhase"); - - static int ahaaSafeZonePhase = 4; - int NewSafeZonePhase = ahaaSafeZonePhase; // GameModeAthena->Get(GameMode_SafeZonePhaseOffset); - - const int OriginalOldSafeZonePhase = GameModeAthena->Get(GameMode_SafeZonePhaseOffset); - - if (NewSafeZonePhase < 4) + if (Globals::bLateGame) { - NewSafeZonePhase = 4; + static auto GameMode_SafeZonePhaseOffset = GameModeAthena->GetOffset("SafeZonePhase"); + static auto GameState_SafeZonePhaseOffset = GameState->GetOffset("SafeZonePhase"); + + static int ahaaSafeZonePhase = 4; + int NewSafeZonePhase = ahaaSafeZonePhase; // GameModeAthena->Get(GameMode_SafeZonePhaseOffset); + + const int OriginalOldSafeZonePhase = GameModeAthena->Get(GameMode_SafeZonePhaseOffset); + + if (NewSafeZonePhase < 4) + { + NewSafeZonePhase = 4; + } + + LOG_INFO(LogDev, "Setting zone to: {} ({})", NewSafeZonePhase, OriginalOldSafeZonePhase); + + GameModeAthena->Get(GameMode_SafeZonePhaseOffset) = NewSafeZonePhase; + GameState->Get(GameState_SafeZonePhaseOffset) = NewSafeZonePhase; + ahaaSafeZonePhase++; } - - LOG_INFO(LogDev, "Setting zone to: {} ({})", NewSafeZonePhase, OriginalOldSafeZonePhase); - - GameModeAthena->Get(GameMode_SafeZonePhaseOffset) = NewSafeZonePhase; - GameState->Get(GameState_SafeZonePhaseOffset) = NewSafeZonePhase; - ahaaSafeZonePhase++; } if (Fortnite_Version < 13) - { - SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); - return; - } - - if (!GameState) return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); static auto SafeZoneIndicatorOffset = GameModeAthena->GetOffset("SafeZoneIndicator"); diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index fc2e49a..5319b57 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -378,7 +378,7 @@ DWORD WINAPI Main(LPVOID) Addresses::Init(); Addresses::Print(); - bEnableRebooting = Addresses::RebootingDelegate && Addresses::FinishResurrection; + bEnableRebooting = Addresses::RebootingDelegate && Addresses::FinishResurrection && Addresses::GetSquadIdForCurrentPlayer && false; LOG_INFO(LogDev, "Fortnite_CL: {}", Fortnite_CL); LOG_INFO(LogDev, "Fortnite_Version: {}", Fortnite_Version); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index b38819c..ebe9a70 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -199,7 +199,7 @@ static inline uint64 FindFinishResurrection() static inline uint64 FindGetSquadIdForCurrentPlayer() { - auto Addrr = Memcury::Scanner::FindStringRef(L"GetSquadIdForCurrentPlayer failed to find a squad id for player %s").Get(); + auto Addrr = Memcury::Scanner::FindStringRef(L"GetSquadIdForCurrentPlayer failed to find a squad id for player %s", true, 0, Fortnite_Version >= 19).Get(); if (!Addrr) return 0; diff --git a/Project Reboot 3.0/gui.h b/Project Reboot 3.0/gui.h index 18d5438..0c98762 100644 --- a/Project Reboot 3.0/gui.h +++ b/Project Reboot 3.0/gui.h @@ -22,6 +22,7 @@ #include #include +#include "objectviewer.h" #include "FortAthenaMutator_Disco.h" #include "globals.h" #include "Fonts/ruda-bold.h" @@ -62,6 +63,7 @@ #define LOADOUT_PLAYERTAB 4 #define FUN_PLAYERTAB 5 +extern inline int AmountOfPlayersWhenBusStart = 0; extern inline bool bHandleDeath = true; extern inline bool bUseCustomMap = false; extern inline std::string CustomMapName = ""; @@ -514,6 +516,23 @@ static inline void MainUI() UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), cmd, nullptr); } + auto GameState = Cast(GetWorld()->GetGameState()); + + if (GameState) + { + static auto DefaultGliderRedeployCanRedeployOffset = FindOffsetStruct("/Script/FortniteGame.FortGameStateAthena", "DefaultGliderRedeployCanRedeploy"); + + if (DefaultGliderRedeployCanRedeployOffset != -1) + { + bool EnableGliderRedeploy = (bool)GameState->Get(DefaultGliderRedeployCanRedeployOffset); + + if (ImGui::Checkbox("Enable Glider Redeploy", &EnableGliderRedeploy)) + { + GameState->Get(DefaultGliderRedeployCanRedeployOffset) = EnableGliderRedeploy; + } + } + } + /* if (ImGui::Button("Spawn BGAs")) { SpawnBGAs(); @@ -615,7 +634,9 @@ static inline void MainUI() bStartedBus = true; auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode(); - auto GameState = GameMode->GetGameState(); + auto GameState = Cast(GameMode->GetGameState()); + + AmountOfPlayersWhenBusStart = GameState->GetPlayersLeft(); UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"startaircraft", nullptr); @@ -846,7 +867,9 @@ static inline void MainUI() bStartedBus = true; auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode(); - auto GameState = GameMode->GetGameState(); + auto GameState = Cast(GameMode->GetGameState()); + + AmountOfPlayersWhenBusStart = GameState->GetPlayersLeft(); // scuffed!!!! if (Fortnite_Version == 1.11) { @@ -1159,14 +1182,20 @@ static inline void MainUI() { static std::string ClassNameToDump; static std::string FunctionNameToDump; + static std::string ObjectToDump; + static std::string FileNameToSaveTo; + static bool bExcludeUnhandled = true; ImGui::Checkbox("Handle Death", &bHandleDeath); ImGui::Checkbox("Fill Vending Machines", &Globals::bFillVendingMachines); ImGui::Checkbox("Enable Bot Tick", &bEnableBotTick); ImGui::Checkbox("Enable Rebooting", &bEnableRebooting); ImGui::Checkbox("Enable Combine Pickup", &bEnableCombinePickup); + ImGui::Checkbox("Exclude unhandled", &bExcludeUnhandled); ImGui::InputInt("Amount To Subtract Index", &AmountToSubtractIndex); ImGui::InputText("Class Name to mess with", &ClassNameToDump); + ImGui::InputText("Object to dump", &ObjectToDump); + ImGui::InputText("File to save to", &FileNameToSaveTo); ImGui::InputText("Function Name to mess with", &FunctionNameToDump); @@ -1180,6 +1209,42 @@ static inline void MainUI() } } + if (ImGui::Button("Dump Object Info")) + { + ObjectViewer::DumpContentsToFile(ObjectToDump, FileNameToSaveTo, bExcludeUnhandled); + } + + if (ImGui::Button("Print all instances of class")) + { + auto ClassToScuff = FindObject(ClassNameToDump); + + if (ClassToScuff) + { + auto ObjectNum = ChunkedObjects ? ChunkedObjects->Num() : UnchunkedObjects ? UnchunkedObjects->Num() : 0; + + for (int i = 0; i < ObjectNum; i++) + { + auto CurrentObject = GetObjectByIndex(i); + + if (!CurrentObject) + continue; + + if (!CurrentObject->IsA(ClassToScuff)) + continue; + + LOG_INFO(LogDev, "Object Name: {}", CurrentObject->GetPathName()); + } + } + } + + if (ImGui::Button("Load BGA Class")) + { + static auto BlueprintGeneratedClassClass = FindObject(L"/Script/Engine.BlueprintGeneratedClass"); + auto Class = LoadObject(ClassNameToDump, BlueprintGeneratedClassClass); + + LOG_INFO(LogDev, "New Class: {}", __int64(Class)); + } + if (ImGui::Button("Find all classes that inherit")) { auto ClassToScuff = FindObject(ClassNameToDump); diff --git a/Project Reboot 3.0/log.h b/Project Reboot 3.0/log.h index 6e4290c..dcb26a0 100644 --- a/Project Reboot 3.0/log.h +++ b/Project Reboot 3.0/log.h @@ -86,6 +86,7 @@ inline void InitLogger() MakeLogger("LogCosmetics"); MakeLogger("LogMatchmaker"); MakeLogger("LogRebooting"); + MakeLogger("LogObjectViewer"); } #define LOG_DEBUG(loggerName, ...) \ diff --git a/Project Reboot 3.0/objectviewer.cpp b/Project Reboot 3.0/objectviewer.cpp new file mode 100644 index 0000000..6f5d029 --- /dev/null +++ b/Project Reboot 3.0/objectviewer.cpp @@ -0,0 +1,175 @@ +#include "objectviewer.h" + +void ObjectViewer::DumpContentsToFile(UObject* Object, const std::string& FileName, bool bExcludeUnhandled) +{ + if (!Object->IsValidLowLevel()) + { + LOG_ERROR(LogObjectViewer, "Invalid object passed into DumpContentsToFile!"); + return; + } + + static auto ClassClass = FindObject(L"/Script/CoreUObject.Class"); + + if (Object->IsA(ClassClass)) + { + LOG_ERROR(LogObjectViewer, "Object passed into DumpContentsToFile was a class!"); + return; + } + + static auto BytePropertyClass = FindObject(L"/Script/CoreUObject.ByteProperty"); + static auto ObjectPropertyClass = FindObject(L"/Script/CoreUObject.ObjectProperty"); + static auto ClassPropertyClass = FindObject(L"/Script/CoreUObject.ClassProperty"); + static auto DoublePropertyClass = FindObject(L"/Script/CoreUObject.DoubleProperty"); + static auto FloatPropertyClass = FindObject(L"/Script/CoreUObject.FloatProperty"); + static auto Int8PropertyClass = FindObject(L"/Script/CoreUObject.Int8Property"); + static auto EnumPropertyClass = FindObject(L"/Script/CoreUObject.EnumProperty"); + static auto ArrayPropertyClass = FindObject(L"/Script/CoreUObject.ArrayProperty"); + static auto Int64PropertyClass = FindObject(L"/Script/CoreUObject.Int64Property"); + static auto UInt16PropertyClass = FindObject(L"/Script/CoreUObject.UInt16Property"); + static auto BoolPropertyClass = FindObject(L"/Script/CoreUObject.BoolProperty"); + static auto NamePropertyClass = FindObject(L"/Script/CoreUObject.NameProperty"); + static auto UInt32PropertyClass = FindObject(L"/Script/CoreUObject.UInt32Property"); + static auto FunctionClass = FindObject(L"/Script/CoreUObject.Function"); + static auto IntPropertyClass = FindObject(L"/Script/CoreUObject.IntProperty"); + static auto UInt64PropertyClass = FindObject(L"/Script/CoreUObject.UInt64Property"); + static auto StrPropertyClass = FindObject(L"/Script/CoreUObject.StrProperty"); + static auto SoftObjectPropertyClass = FindObject(L"/Script/CoreUObject.SoftObjectProperty"); + + std::ofstream Stream(FileName); + + if (!FileName.empty() && !Stream.is_open()) + { + LOG_ERROR(LogObjectViewer, "Failed to open file {}!", FileName); + return; + } + + auto log = [&](const std::string& str) { + if (FileName.empty()) + { + LOG_INFO(LogObjectViewer, "{}", str); + } + else + { + Stream << str; + } + }; + + for (auto CurrentClass = Object->ClassPrivate; CurrentClass; CurrentClass = (UClass*)CurrentClass->GetSuperStruct()) + { + void* Property = *(void**)(__int64(CurrentClass) + Offsets::Children); + + while (Property) + { + std::string PropertyName = GetFNameOfProp(Property)->ToString(); + int Offset = *(int*)(__int64(Property) + Offsets::Offset_Internal); + + // log(std::format("Handling prop {}\n", PropertyName)); + + if (Offsets::PropertyClass) + { + if (IsPropertyA(Property, ObjectPropertyClass)) + { + auto PropertyClass = *(UClass**)(__int64(Property) + Offsets::PropertyClass); + + if (PropertyClass->IsValidLowLevel()) + log(std::format("{} Object: {}\n", PropertyName, PropertyClass->GetPathName())); + } + + /* + else if (IsPropertyA(Property, SoftObjectPropertyClass)) + { + auto PropertyClass = *(UClass**)(__int64(Property) + Offsets::PropertyClass); + + if (PropertyClass->IsValidLowLevel()) + { + auto SoftObjectPtr = *(TSoftObjectPtr*)(__int64(Object) + Offset); + auto SoftObjectPtrObject = SoftObjectPtr.Get(PropertyClass); + log(std::format("{} SoftObjectPtr (type: {}): {}\n", PropertyName, PropertyClass->GetName(), SoftObjectPtrObject ? SoftObjectPtrObject->GetPathName() : "BadRead")); + } + } + */ + } + + if (IsPropertyA(Property, BytePropertyClass)) + { + log(std::format("uint8 {} = {}\n", PropertyName, *(uint8*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, DoublePropertyClass)) + { + log(std::format("double {} = {}\n", PropertyName, *(double*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, UInt16PropertyClass)) + { + log(std::format("uint16 {} = {}\n", PropertyName, *(uint16*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, Int8PropertyClass)) + { + log(std::format("int8 {} = {}\n", PropertyName, *(int8*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, NamePropertyClass)) + { + log(std::format("FName {} = {}\n", PropertyName, (*(FName*)(__int64(Object) + Offset)).ToString())); + } + else if (IsPropertyA(Property, StrPropertyClass)) + { + auto string = (FString*)(__int64(Object) + Offset); + + log(std::format("FString {} = {}\n", PropertyName, string->Data.Data ? string->ToString() : "")); + } + else if (IsPropertyA(Property, FloatPropertyClass)) + { + log(std::format("float {} = {}\n", PropertyName, *(float*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, BoolPropertyClass)) + { + auto FieldMask = GetFieldMask(Property); + + log(std::format("bool {} = {}\n", PropertyName, ReadBitfield((PlaceholderBitfield*)(__int64(Object) + Offset), FieldMask))); + } + else if (IsPropertyA(Property, IntPropertyClass)) + { + log(std::format("int32 {} = {}\n", PropertyName, *(int*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, UInt32PropertyClass)) + { + log(std::format("uint32 {} = {}\n", PropertyName, *(uint32*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, UInt64PropertyClass)) + { + log(std::format("uint64 {} = {}\n", PropertyName, *(uint64*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, Int64PropertyClass)) + { + log(std::format("int64 {} = {}\n", PropertyName, *(int64*)(__int64(Object) + Offset))); + } + else if (IsPropertyA(Property, ArrayPropertyClass)) + { + log(std::format("{} Array\n", PropertyName)); + } + /* + else if (IsPropertyA(Property, EnumPropertyClass)) + { + using UNumericProperty = UObject; + + auto EnumValueIg = *(uint8*)(__int64(Property) + Offset); + auto UnderlyingType = *(UNumericProperty**)(__int64(Property) + Offsets::UnderlyingType); + // log(std::format("{} Enum: {}\n", PropertyName, (int)EnumValueIg)); + log(std::format("{} Enum\n", PropertyName)); + } + */ + else if (IsPropertyA(Property, FunctionClass)) + { + + } + else if (!bExcludeUnhandled) + { + // log(std::format("{}: {}\n", PropertyName, "UNHANDLED"); + log(std::format("{}: {} {}\n", PropertyName, "UNHANDLED", ""/*, ((UObject*)Property)->GetName()*/)); + } + + Property = GetNext(Property); + } + } + + return; +} \ No newline at end of file diff --git a/Project Reboot 3.0/objectviewer.h b/Project Reboot 3.0/objectviewer.h index 3f59c93..69a529e 100644 --- a/Project Reboot 3.0/objectviewer.h +++ b/Project Reboot 3.0/objectviewer.h @@ -1,2 +1,26 @@ #pragma once +#include "reboot.h" +#include + +static inline bool IsPropertyA(void* Property, UClass* Class) +{ + if (Fortnite_Version < 12.10) + { + if (((UField*)Property)->IsA(Class)) + return true; + } + else + { + // TODO + } + + return false; +} + +namespace ObjectViewer +{ + void DumpContentsToFile(UObject* Object, const std::string& FileName = "", bool bExcludeUnhandled = false); + + static inline void DumpContentsToFile(const std::string& ObjectName, const std::string& FileName = "", bool bExcludeUnhandled = false) { return DumpContentsToFile(FindObject(ObjectName), FileName, bExcludeUnhandled); } +} \ No newline at end of file