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->GetMarkerType() = MarkerRequestPtr->GetMarkerType();
MarkerData->GetOwner() = PlayerState; MarkerData->GetOwner() = PlayerState;
MarkerData->GetWorldNormal() = MarkerRequestPtr->GetWorldNormal(); MarkerData->GetWorldNormal() = MarkerRequestPtr->GetWorldNormal();
if (WorldPositionOffset != -1) if (WorldPositionOffset != -1)
MarkerData->GetWorldPosition() = MarkerRequestPtr->GetWorldPosition(); MarkerData->GetWorldPosition() = MarkerRequestPtr->GetWorldPosition();
if (WorldPositionOffset != -1) if (WorldPositionOffset != -1)
@@ -54,30 +55,6 @@ void UAthenaMarkerComponent::ServerAddMapMarkerHook(UAthenaMarkerComponent* Mark
((TSoftObjectPtr<UObject>*)(__int64(MarkerData->GetCustomDisplayInfo()) + IconOffset))->SoftObjectPtr.WeakPtr.ObjectSerialNumber = 0; ((TSoftObjectPtr<UObject>*)(__int64(MarkerData->GetCustomDisplayInfo()) + IconOffset))->SoftObjectPtr.WeakPtr.ObjectSerialNumber = 0;
*(FText*)(__int64(MarkerData->GetCustomDisplayInfo()) + DisplayNameOffset) = UKismetTextLibrary::Conv_StringToText(L""); *(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"); static auto PlayerTeamOffset = PlayerState->GetOffset("PlayerTeam");
auto PlayerTeam = PlayerState->Get<UObject*>(PlayerTeamOffset); auto PlayerTeam = PlayerState->Get<UObject*>(PlayerTeamOffset);
@@ -124,8 +101,8 @@ void UAthenaMarkerComponent::ServerAddMapMarkerHook(UAthenaMarkerComponent* Mark
((FFastArraySerializerItem*)MarkerData)->ReplicationID = -1; ((FFastArraySerializerItem*)MarkerData)->ReplicationID = -1;
((FFastArraySerializerItem*)MarkerData)->ReplicationKey = -1; ((FFastArraySerializerItem*)MarkerData)->ReplicationKey = -1;
auto& Markers = *(TArray<FFortWorldMarkerData>*)(__int64(MarkerStream) + MarkersOffset); auto Markers = (TArray<FFortWorldMarkerData>*)(__int64(MarkerStream) + MarkersOffset);
Markers.AddPtr(MarkerData, FFortWorldMarkerData::GetStructSize()); Markers->AddPtr(MarkerData, FFortWorldMarkerData::GetStructSize());
MarkerStream->MarkArrayDirty(); MarkerStream->MarkArrayDirty();
} }
} }

View File

@@ -60,7 +60,7 @@ struct FFortWorldMarkerData
{ {
static UStruct* GetStruct() static UStruct* GetStruct()
{ {
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortWorldMarkerData"); static auto Struct = FindObject<UStruct>(L"/Script/FortniteGame.FortWorldMarkerData");
return Struct; 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"); 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); // 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; Globals::bInitializedPlaylist = true;
} }
@@ -790,12 +798,9 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
AllRebootVans.Free(); AllRebootVans.Free();
static auto DefaultRebootMachineHotfixOffset = GameState->GetOffset("DefaultRebootMachineHotfix", false); if (Engine_Version >= 500)
if (DefaultRebootMachineHotfixOffset != -1)
{ {
// LOG_INFO(LogDev, "Beraau: {}", GameState->Get<float>(DefaultRebootMachineHotfixOffset)); GameState->Get<float>("DefaultParachuteDeployTraceForGroundDistance") = 10000;
GameState->Get<float>(DefaultRebootMachineHotfixOffset) = 1; // idk i dont think we need to set
} }
if (AmountOfBotsToSpawn != 0) 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); static auto SquadIdOffset = PlayerStateAthena->GetOffset("SquadId", false);
if (SquadIdOffset != -1) if (SquadIdOffset != -1)

View File

@@ -6,12 +6,25 @@
#include "OnlineReplStructs.h" #include "OnlineReplStructs.h"
#include "gui.h" #include "gui.h"
uint8 AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, __int64 UniqueId) uint8 AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook(AFortGameSessionDedicatedAthena* GameSessionDedicated, void* UniqueId)
{ {
LOG_INFO(LogDev, "GetSquadIdForCurrentPlayerHook!"); LOG_INFO(LogDev, "GetSquadIdForCurrentPlayerHook!");
TArray<AActor*> CONTRTOLLERS = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFortPlayerControllerAthena::StaticClass()); 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++) for (int i = 0; i < CONTRTOLLERS.Num(); i++)
{ {
auto Controller = (AFortPlayerControllerAthena*)CONTRTOLLERS.at(i); auto Controller = (AFortPlayerControllerAthena*)CONTRTOLLERS.at(i);
@@ -24,12 +37,14 @@ uint8 AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook(AFortGameS
static auto UniqueIdOffset = PlayerState->GetOffset("UniqueId"); static auto UniqueIdOffset = PlayerState->GetOffset("UniqueId");
if (IsBadReadPtr(PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset))) // if (IsBadReadPtr(PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset)))
continue; // 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; return PlayerState->GetTeamIndex() - NumToSubtractFromSquadId;
} }
} }

View File

@@ -5,5 +5,5 @@
class AFortGameSessionDedicatedAthena : public AActor class AFortGameSessionDedicatedAthena : public AActor
{ {
public: 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() TeamsArrayContainer* AFortGameStateAthena::GetTeamsArrayContainer()
{ {
// if (!bEnableRebooting) // todo (milxnor) remove when safer if (true)
// return nullptr; return nullptr;
if (Fortnite_Version < 8.0) // I'm pretty sure it got added on 7.40 but idk if it is structured differently. if (Fortnite_Version < 8.0) // I'm pretty sure it got added on 7.40 but idk if it is structured differently.
return nullptr; 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. 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 LootTier = ForcedLootTier;
float IdkForcedWeightorsomething = 1; float IdkForcedWeightorsomething = -1;
if (LootTier == -1) if (LootTier == -1)
{ {

View File

@@ -1436,27 +1436,60 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
UFortWeaponItemDefinition* KillerWeaponDef = nullptr; UFortWeaponItemDefinition* KillerWeaponDef = nullptr;
static auto FortProjectileBaseClass = FindObject<UClass>(L"/Script/FortniteGame.FortProjectileBase"); static auto FortProjectileBaseClass = FindObject<UClass>(L"/Script/FortniteGame.FortProjectileBase");
LOG_INFO(LogDev, "FortProjectileBaseClass: {}", __int64(FortProjectileBaseClass));
if (DamageCauser) if (DamageCauser)
{ {
if (DamageCauser->IsA(FortProjectileBaseClass)) if (DamageCauser->IsA(FortProjectileBaseClass))
{ {
// LOG_INFO(LogDev, "From a projectile!");
auto Owner = Cast<AFortWeapon>(DamageCauser->GetOwner()); auto Owner = Cast<AFortWeapon>(DamageCauser->GetOwner());
KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys? KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys?
} }
if (auto Weapon = Cast<AFortWeapon>(DamageCauser)) if (auto Weapon = Cast<AFortWeapon>(DamageCauser))
{ {
// LOG_INFO(LogDev, "From a weapon!");
KillerWeaponDef = Weapon->GetWeaponData(); KillerWeaponDef = Weapon->GetWeaponData();
} }
} }
// LOG_INFO(LogDev, "KillerWeaponDef: {}", KillerWeaponDef ? KillerWeaponDef->GetFullName() : "InvalidObject");
RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0); 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!"); LOG_INFO(LogDev, "Removed!");
if (Fortnite_Version < 6) // Spectating if (Fortnite_Version < 6) // Spectating

View File

@@ -7,6 +7,7 @@
#include "FortKismetLibrary.h" #include "FortKismetLibrary.h"
#include "AthenaMarkerComponent.h" #include "AthenaMarkerComponent.h"
#include "FortVolume.h" #include "FortVolume.h"
#include "AthenaPlayerMatchReport.h"
static void ApplyHID(AFortPlayerPawn* Pawn, UObject* HeroDefinition, bool bUseServerChoosePart = false) static void ApplyHID(AFortPlayerPawn* Pawn, UObject* HeroDefinition, bool bUseServerChoosePart = false)
{ {
@@ -191,6 +192,25 @@ public:
this->ProcessEvent(ClientClearDeathNotificationFn); 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) void RespawnPlayerAfterDeath(bool bEnterSkydiving)
{ {
static auto RespawnPlayerAfterDeathFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerAthena.RespawnPlayerAfterDeath"); 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); return *(TArray<uint8>*)(__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 return (GetSize() == OtherUniqueId->GetSize()) &&
(memcmp(GetBytes(), OtherUniqueId->GetBytes(), GetSize()) == 0);
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;
} }
void CopyFromAnotherUniqueId(FUniqueNetIdRepl* OtherUniqueId) void CopyFromAnotherUniqueId(FUniqueNetIdRepl* OtherUniqueId)

View File

@@ -11,4 +11,10 @@ public:
static auto PlayerControllerOffset = GetOffset("PlayerController"); static auto PlayerControllerOffset = GetOffset("PlayerController");
return Get<APlayerController*>(PlayerControllerOffset); 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); return this->Get<UCheatManager*>(CheatManagerOffset);
} }
class UNetConnection*& GetNetConnection()
{
static auto NetConnectionOffset = GetOffset("NetConnection");
return Get<class UNetConnection*>(NetConnectionOffset);
}
void SetPlayerIsWaiting(bool NewValue); void SetPlayerIsWaiting(bool NewValue);
void ServerChangeName(FString& S); void ServerChangeName(FString& S);
UCheatManager*& SpawnCheatManager(UClass* CheatManagerClass); UCheatManager*& SpawnCheatManager(UClass* CheatManagerClass);

View File

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

View File

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

View File

@@ -489,6 +489,7 @@ void Offsets::Print()
LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors); LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors);
LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame); LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame);
LOG_INFO(LogDev, "Script: 0x{:x}", Script); LOG_INFO(LogDev, "Script: 0x{:x}", Script);
LOG_INFO(LogDev, "PropertyClass: 0x{:x}", PropertyClass);
} }
void Addresses::Init() void Addresses::Init()

View File

@@ -97,6 +97,7 @@ namespace Offsets
extern inline uint64 NetworkObjectList = 0; extern inline uint64 NetworkObjectList = 0;
extern inline uint64 ClientWorldPackageName = 0; extern inline uint64 ClientWorldPackageName = 0;
extern inline uint64 Script = 0; extern inline uint64 Script = 0;
extern inline uint64 PropertyClass = 0;
void FindAll(); void FindAll();
void Print(); void Print();

View File

@@ -16,41 +16,42 @@ static inline void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int O
: std::floor(Fortnite_Version) >= 18 ? 0x248 : std::floor(Fortnite_Version) >= 18 ? 0x248
: 0x1F8; // S13-S14 : 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()); auto GameState = Cast<AFortGameStateAthena>(GameModeAthena->GetGameState());
if (!GameState)
return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK);
LOG_INFO(LogDev, "GamePhaseStep: {}", (int)GameState->GetGamePhaseStep()); LOG_INFO(LogDev, "GamePhaseStep: {}", (int)GameState->GetGamePhaseStep());
if (Globals::bLateGame) if (false)
{ {
static auto GameMode_SafeZonePhaseOffset = GameModeAthena->GetOffset("SafeZonePhase"); if (Globals::bLateGame)
static auto GameState_SafeZonePhaseOffset = GameState->GetOffset("SafeZonePhase");
static int ahaaSafeZonePhase = 4;
int NewSafeZonePhase = ahaaSafeZonePhase; // GameModeAthena->Get<int>(GameMode_SafeZonePhaseOffset);
const int OriginalOldSafeZonePhase = GameModeAthena->Get<int>(GameMode_SafeZonePhaseOffset);
if (NewSafeZonePhase < 4)
{ {
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<int>(GameMode_SafeZonePhaseOffset);
const int OriginalOldSafeZonePhase = GameModeAthena->Get<int>(GameMode_SafeZonePhaseOffset);
if (NewSafeZonePhase < 4)
{
NewSafeZonePhase = 4;
}
LOG_INFO(LogDev, "Setting zone to: {} ({})", NewSafeZonePhase, OriginalOldSafeZonePhase);
GameModeAthena->Get<int>(GameMode_SafeZonePhaseOffset) = NewSafeZonePhase;
GameState->Get<int>(GameState_SafeZonePhaseOffset) = NewSafeZonePhase;
ahaaSafeZonePhase++;
} }
LOG_INFO(LogDev, "Setting zone to: {} ({})", NewSafeZonePhase, OriginalOldSafeZonePhase);
GameModeAthena->Get<int>(GameMode_SafeZonePhaseOffset) = NewSafeZonePhase;
GameState->Get<int>(GameState_SafeZonePhaseOffset) = NewSafeZonePhase;
ahaaSafeZonePhase++;
} }
if (Fortnite_Version < 13) if (Fortnite_Version < 13)
{
SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK);
return;
}
if (!GameState)
return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK);
static auto SafeZoneIndicatorOffset = GameModeAthena->GetOffset("SafeZoneIndicator"); static auto SafeZoneIndicatorOffset = GameModeAthena->GetOffset("SafeZoneIndicator");

View File

@@ -378,7 +378,7 @@ DWORD WINAPI Main(LPVOID)
Addresses::Init(); Addresses::Init();
Addresses::Print(); 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_CL: {}", Fortnite_CL);
LOG_INFO(LogDev, "Fortnite_Version: {}", Fortnite_Version); LOG_INFO(LogDev, "Fortnite_Version: {}", Fortnite_Version);

View File

@@ -199,7 +199,7 @@ static inline uint64 FindFinishResurrection()
static inline uint64 FindGetSquadIdForCurrentPlayer() 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) if (!Addrr)
return 0; return 0;

View File

@@ -22,6 +22,7 @@
#include <fstream> #include <fstream>
#include <olectl.h> #include <olectl.h>
#include "objectviewer.h"
#include "FortAthenaMutator_Disco.h" #include "FortAthenaMutator_Disco.h"
#include "globals.h" #include "globals.h"
#include "Fonts/ruda-bold.h" #include "Fonts/ruda-bold.h"
@@ -62,6 +63,7 @@
#define LOADOUT_PLAYERTAB 4 #define LOADOUT_PLAYERTAB 4
#define FUN_PLAYERTAB 5 #define FUN_PLAYERTAB 5
extern inline int AmountOfPlayersWhenBusStart = 0;
extern inline bool bHandleDeath = true; extern inline bool bHandleDeath = true;
extern inline bool bUseCustomMap = false; extern inline bool bUseCustomMap = false;
extern inline std::string CustomMapName = ""; extern inline std::string CustomMapName = "";
@@ -514,6 +516,23 @@ static inline void MainUI()
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), cmd, nullptr); 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")) /* if (ImGui::Button("Spawn BGAs"))
{ {
SpawnBGAs(); SpawnBGAs();
@@ -615,7 +634,9 @@ static inline void MainUI()
bStartedBus = true; bStartedBus = true;
auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode(); auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode();
auto GameState = GameMode->GetGameState(); auto GameState = Cast<AFortGameStateAthena>(GameMode->GetGameState());
AmountOfPlayersWhenBusStart = GameState->GetPlayersLeft();
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"startaircraft", nullptr); UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"startaircraft", nullptr);
@@ -846,7 +867,9 @@ static inline void MainUI()
bStartedBus = true; bStartedBus = true;
auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode(); auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode();
auto GameState = GameMode->GetGameState(); auto GameState = Cast<AFortGameStateAthena>(GameMode->GetGameState());
AmountOfPlayersWhenBusStart = GameState->GetPlayersLeft(); // scuffed!!!!
if (Fortnite_Version == 1.11) if (Fortnite_Version == 1.11)
{ {
@@ -1159,14 +1182,20 @@ static inline void MainUI()
{ {
static std::string ClassNameToDump; static std::string ClassNameToDump;
static std::string FunctionNameToDump; static std::string FunctionNameToDump;
static std::string ObjectToDump;
static std::string FileNameToSaveTo;
static bool bExcludeUnhandled = true;
ImGui::Checkbox("Handle Death", &bHandleDeath); ImGui::Checkbox("Handle Death", &bHandleDeath);
ImGui::Checkbox("Fill Vending Machines", &Globals::bFillVendingMachines); ImGui::Checkbox("Fill Vending Machines", &Globals::bFillVendingMachines);
ImGui::Checkbox("Enable Bot Tick", &bEnableBotTick); ImGui::Checkbox("Enable Bot Tick", &bEnableBotTick);
ImGui::Checkbox("Enable Rebooting", &bEnableRebooting); ImGui::Checkbox("Enable Rebooting", &bEnableRebooting);
ImGui::Checkbox("Enable Combine Pickup", &bEnableCombinePickup); ImGui::Checkbox("Enable Combine Pickup", &bEnableCombinePickup);
ImGui::Checkbox("Exclude unhandled", &bExcludeUnhandled);
ImGui::InputInt("Amount To Subtract Index", &AmountToSubtractIndex); ImGui::InputInt("Amount To Subtract Index", &AmountToSubtractIndex);
ImGui::InputText("Class Name to mess with", &ClassNameToDump); 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); 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")) if (ImGui::Button("Find all classes that inherit"))
{ {
auto ClassToScuff = FindObject<UClass>(ClassNameToDump); auto ClassToScuff = FindObject<UClass>(ClassNameToDump);

View File

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