disable rebooting again

fixed looting bug, fixed parachute not auto deploying on some builds
This commit is contained in:
Milxnor
2023-06-21 10:51:24 -04:00
parent 1d12b8929f
commit 5e2a74764a
24 changed files with 479 additions and 99 deletions

View File

@@ -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<UObject>*)(__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<AFortPickup>(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<UObject*>(PlayerTeamOffset);
@@ -124,8 +101,8 @@ void UAthenaMarkerComponent::ServerAddMapMarkerHook(UAthenaMarkerComponent* Mark
((FFastArraySerializerItem*)MarkerData)->ReplicationID = -1;
((FFastArraySerializerItem*)MarkerData)->ReplicationKey = -1;
auto& Markers = *(TArray<FFortWorldMarkerData>*)(__int64(MarkerStream) + MarkersOffset);
Markers.AddPtr(MarkerData, FFortWorldMarkerData::GetStructSize());
auto Markers = (TArray<FFortWorldMarkerData>*)(__int64(MarkerStream) + MarkersOffset);
Markers->AddPtr(MarkerData, FFortWorldMarkerData::GetStructSize());
MarkerStream->MarkArrayDirty();
}
}

View File

@@ -60,7 +60,7 @@ struct FFortWorldMarkerData
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortWorldMarkerData");
static auto Struct = FindObject<UStruct>(L"/Script/FortniteGame.FortWorldMarkerData");
return Struct;
}

View File

@@ -0,0 +1,55 @@
#pragma once
#include "reboot.h"
struct FAthenaMatchTeamStats
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>(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<bool>(bHasTeamStatsOffset);
}
bool& HasMatchStats()
{
static auto bHasMatchStatsOffset = GetOffset("bHasMatchStats");
return Get<bool>(bHasMatchStatsOffset);
}
FAthenaMatchTeamStats* GetTeamStats()
{
static auto TeamStatsOffset = GetOffset("TeamStats");
return GetPtr<FAthenaMatchTeamStats>(TeamStatsOffset);
}
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.AthenaPlayerMatchReport");
return Class;
}
};

View File

@@ -538,10 +538,18 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
}
static auto bWorldIsReadyOffset = GameMode->GetOffset("bWorldIsReady");
SetBitfield(GameMode->GetPtr<PlaceholderBitfield>(bWorldIsReadyOffset), 1, true); // idk when we actually set this (probably after we listen)
SetBitfield(GameMode->GetPtr<PlaceholderBitfield>(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<float>(DefaultRebootMachineHotfixOffset));
GameState->Get<float>(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<float>(DefaultRebootMachineHotfixOffset));
GameState->Get<float>(DefaultRebootMachineHotfixOffset) = 1; // idk i dont think we need to set
GameState->Get<float>("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)

View File

@@ -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<AActor*> 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<FUniqueNetIdRepl>(UniqueIdOffset)))
continue;
// if (IsBadReadPtr(PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset)))
// continue;
if (PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset)->IsIdentical((FUniqueNetIdRepl*)&UniqueId))
LOG_INFO(LogDev, "PS PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset)->GetReplicationBytes().Num(): {}", PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset)->GetReplicationBytes().Num());
if (PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset)->IsIdentical(OwnerUniqueId))
{
LOG_INFO(LogDev, "Found!");
LOG_INFO(LogDev, "Found {}!", PlayerState->GetPlayerName().ToString());
return PlayerState->GetTeamIndex() - NumToSubtractFromSquadId;
}
}

View File

@@ -5,5 +5,5 @@
class AFortGameSessionDedicatedAthena : public AActor
{
public:
static uint8 GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, __int64 UniqueId);
static uint8 GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, void* UniqueId);
};

View File

@@ -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;

View File

@@ -154,7 +154,7 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina
FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& 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)
{

View File

@@ -1436,27 +1436,60 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
UFortWeaponItemDefinition* KillerWeaponDef = nullptr;
static auto FortProjectileBaseClass = FindObject<UClass>(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<AFortWeapon>(DamageCauser->GetOwner());
KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys?
}
if (auto Weapon = Cast<AFortWeapon>(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<AFortPlayerControllerAthena>(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

View File

@@ -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<UAthenaPlayerMatchReport*>(MatchReportOffset);
}
void ClientSendTeamStatsForPlayer(FAthenaMatchTeamStats* TeamStats)
{
static auto ClientSendTeamStatsForPlayerFn = FindObject<UFunction>("/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<UFunction>(L"/Script/FortniteGame.FortPlayerControllerAthena.RespawnPlayerAfterDeath");

View File

@@ -24,31 +24,13 @@ struct FUniqueNetIdRepl // : public FUniqueNetIdWrapper
return *(TArray<uint8>*)(__int64(this) + ReplicationBytesOffset);
}
bool IsIdentical(FUniqueNetIdRepl* OtherUniqueId)
{
// idk if this is right but whatever
FORCEINLINE int GetSize() { return GetReplicationBytes().Num(); } // LITERLALY IDK IF THIS IS RIGHT CUZ I CANT FIND IMPL
FORCEINLINE uint8* GetBytes() { return GetReplicationBytes().Data; } // ^^^
bool bTest = true;
if (this->GetReplicationBytes().Num() >= OtherUniqueId->GetReplicationBytes().Num())
FORCENOINLINE bool IsIdentical(FUniqueNetIdRepl* OtherUniqueId)
{
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)

View File

@@ -11,4 +11,10 @@ public:
static auto PlayerControllerOffset = GetOffset("PlayerController");
return Get<APlayerController*>(PlayerControllerOffset);
}
int& GetCurrentNetSpeed()
{
static auto CurrentNetSpeedOffset = GetOffset("CurrentNetSpeed");
return Get<int>(CurrentNetSpeedOffset);
}
};

View File

@@ -16,6 +16,12 @@ public:
return this->Get<UCheatManager*>(CheatManagerOffset);
}
class UNetConnection*& GetNetConnection()
{
static auto NetConnectionOffset = GetOffset("NetConnection");
return Get<class UNetConnection*>(NetConnectionOffset);
}
void SetPlayerIsWaiting(bool NewValue);
void ServerChangeName(FString& S);
UCheatManager*& SpawnCheatManager(UClass* CheatManagerClass);

View File

@@ -253,6 +253,7 @@
<ClCompile Include="NetDriver.cpp" />
<ClCompile Include="NetworkObjectList.cpp" />
<ClCompile Include="Object.cpp" />
<ClCompile Include="objectviewer.cpp" />
<ClCompile Include="PlayerController.cpp" />
<ClCompile Include="PlayerState.cpp" />
<ClCompile Include="reboot.cpp" />
@@ -279,6 +280,7 @@
<ClInclude Include="AthenaBarrierObjective.h" />
<ClInclude Include="AthenaBigBaseWall.h" />
<ClInclude Include="AthenaMarkerComponent.h" />
<ClInclude Include="AthenaPlayerMatchReport.h" />
<ClInclude Include="AthenaResurrectionComponent.h" />
<ClInclude Include="AttributeSet.h" />
<ClInclude Include="BGA.h" />

View File

@@ -295,6 +295,9 @@
<ClCompile Include="finder.cpp">
<Filter>Reboot\Private</Filter>
</ClCompile>
<ClCompile Include="objectviewer.cpp">
<Filter>Reboot\Private</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="log.h" />
@@ -945,6 +948,9 @@
<ClInclude Include="objectviewer.h">
<Filter>Reboot\Public</Filter>
</ClInclude>
<ClInclude Include="AthenaPlayerMatchReport.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Stats</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Engine">
@@ -1211,6 +1217,9 @@
<Filter Include="FortniteGame\Source\FortniteGame\Private\Vehicle">
<UniqueIdentifier>{702a4ab1-e5e1-46e1-b8cd-2fab1c4fb48c}</UniqueIdentifier>
</Filter>
<Filter Include="FortniteGame\Source\FortniteGame\Public\Stats">
<UniqueIdentifier>{3c8e3f87-8a4c-4220-b952-39b0e0315e85}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="UnrealEngine.cpp">

View File

@@ -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()

View File

@@ -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();

View File

@@ -16,12 +16,18 @@ 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<int>(GameMode_SafeZonePhaseOffset));
auto GameState = Cast<AFortGameStateAthena>(GameModeAthena->GetGameState());
if (!GameState)
return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK);
LOG_INFO(LogDev, "GamePhaseStep: {}", (int)GameState->GetGamePhaseStep());
if (false)
{
if (Globals::bLateGame)
{
static auto GameMode_SafeZonePhaseOffset = GameModeAthena->GetOffset("SafeZonePhase");
@@ -43,14 +49,9 @@ static inline void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int O
GameState->Get<int>(GameState_SafeZonePhaseOffset) = NewSafeZonePhase;
ahaaSafeZonePhase++;
}
if (Fortnite_Version < 13)
{
SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK);
return;
}
if (!GameState)
if (Fortnite_Version < 13)
return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK);
static auto SafeZoneIndicatorOffset = GameModeAthena->GetOffset("SafeZoneIndicator");

View File

@@ -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);

View File

@@ -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;

View File

@@ -22,6 +22,7 @@
#include <fstream>
#include <olectl.h>
#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<AFortGameStateAthena>(GetWorld()->GetGameState());
if (GameState)
{
static auto DefaultGliderRedeployCanRedeployOffset = FindOffsetStruct("/Script/FortniteGame.FortGameStateAthena", "DefaultGliderRedeployCanRedeploy");
if (DefaultGliderRedeployCanRedeployOffset != -1)
{
bool EnableGliderRedeploy = (bool)GameState->Get<float>(DefaultGliderRedeployCanRedeployOffset);
if (ImGui::Checkbox("Enable Glider Redeploy", &EnableGliderRedeploy))
{
GameState->Get<float>(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<AFortGameStateAthena>(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<AFortGameStateAthena>(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<UClass>(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<UClass>(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<UClass>(ClassNameToDump);

View File

@@ -86,6 +86,7 @@ inline void InitLogger()
MakeLogger("LogCosmetics");
MakeLogger("LogMatchmaker");
MakeLogger("LogRebooting");
MakeLogger("LogObjectViewer");
}
#define LOG_DEBUG(loggerName, ...) \

View File

@@ -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<UClass>(L"/Script/CoreUObject.Class");
if (Object->IsA(ClassClass))
{
LOG_ERROR(LogObjectViewer, "Object passed into DumpContentsToFile was a class!");
return;
}
static auto BytePropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ByteProperty");
static auto ObjectPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ObjectProperty");
static auto ClassPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ClassProperty");
static auto DoublePropertyClass = FindObject<UClass>(L"/Script/CoreUObject.DoubleProperty");
static auto FloatPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.FloatProperty");
static auto Int8PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.Int8Property");
static auto EnumPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.EnumProperty");
static auto ArrayPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ArrayProperty");
static auto Int64PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.Int64Property");
static auto UInt16PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.UInt16Property");
static auto BoolPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.BoolProperty");
static auto NamePropertyClass = FindObject<UClass>(L"/Script/CoreUObject.NameProperty");
static auto UInt32PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.UInt32Property");
static auto FunctionClass = FindObject<UClass>(L"/Script/CoreUObject.Function");
static auto IntPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.IntProperty");
static auto UInt64PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.UInt64Property");
static auto StrPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.StrProperty");
static auto SoftObjectPropertyClass = FindObject<UClass>(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<UObject>*)(__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;
}

View File

@@ -1,2 +1,26 @@
#pragma once
#include "reboot.h"
#include <fstream>
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); }
}