mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
too much stuff
fix s3, fix health + backpack bug on 1.11, change replciation, fix 7.20 & 12.61, fix backpack on >S9, probably some other stuff i forgot
This commit is contained in:
@@ -126,6 +126,28 @@ void AActor::ForceNetUpdate()
|
|||||||
this->ProcessEvent(ForceNetUpdateFn);
|
this->ProcessEvent(ForceNetUpdateFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AActor::IsNetStartupActor()
|
||||||
|
{
|
||||||
|
return IsNetStartup(); // The implementation on this function depends on the version.
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AActor::IsPendingKillPending()
|
||||||
|
{
|
||||||
|
return IsActorBeingDestroyed() || !IsValidChecked(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
float& AActor::GetNetUpdateFrequency()
|
||||||
|
{
|
||||||
|
static auto NetUpdateFrequencyOffset = GetOffset("NetUpdateFrequency");
|
||||||
|
return Get<float>(NetUpdateFrequencyOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float& AActor::GetMinNetUpdateFrequency()
|
||||||
|
{
|
||||||
|
static auto MinNetUpdateFrequencyOffset = GetOffset("MinNetUpdateFrequency");
|
||||||
|
return Get<float>(MinNetUpdateFrequencyOffset);
|
||||||
|
}
|
||||||
|
|
||||||
bool AActor::IsAlwaysRelevant()
|
bool AActor::IsAlwaysRelevant()
|
||||||
{
|
{
|
||||||
static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant");
|
static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant");
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ public:
|
|||||||
void SetCanBeDamaged(bool NewValue);
|
void SetCanBeDamaged(bool NewValue);
|
||||||
void SetOwner(AActor* Owner);
|
void SetOwner(AActor* Owner);
|
||||||
void ForceNetUpdate();
|
void ForceNetUpdate();
|
||||||
|
bool IsNetStartupActor();
|
||||||
|
bool IsPendingKillPending();
|
||||||
|
float& GetNetUpdateFrequency();
|
||||||
|
float& GetMinNetUpdateFrequency();
|
||||||
|
|
||||||
static class UClass* StaticClass();
|
static class UClass* StaticClass();
|
||||||
};
|
};
|
||||||
@@ -2,6 +2,20 @@
|
|||||||
|
|
||||||
#include "ContainerAllocationPolicies.h"
|
#include "ContainerAllocationPolicies.h"
|
||||||
|
|
||||||
|
static FORCEINLINE uint32 CountLeadingZeros(uint32 Value)
|
||||||
|
{
|
||||||
|
unsigned long Log2;
|
||||||
|
if (_BitScanReverse(&Log2, Value) != 0)
|
||||||
|
{
|
||||||
|
return 31 - Log2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NumBitsPerDWORD ((int32)32)
|
||||||
|
#define NumBitsPerDWORDLogTwo ((int32)5)
|
||||||
|
|
||||||
class TBitArray
|
class TBitArray
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -10,8 +24,308 @@ private:
|
|||||||
template <typename SetType>
|
template <typename SetType>
|
||||||
friend class TSet;
|
friend class TSet;
|
||||||
|
|
||||||
private:
|
public:
|
||||||
TInlineAllocator<4>::ForElementType<unsigned int> Data;
|
TInlineAllocator<4>::ForElementType<unsigned int> Data;
|
||||||
int NumBits;
|
int NumBits;
|
||||||
int MaxBits;
|
int MaxBits;
|
||||||
|
|
||||||
|
struct FRelativeBitReference
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FORCEINLINE explicit FRelativeBitReference(int32 BitIndex)
|
||||||
|
: DWORDIndex(BitIndex >> NumBitsPerDWORDLogTwo)
|
||||||
|
, Mask(1 << (BitIndex & ((NumBitsPerDWORD)-1)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 DWORDIndex;
|
||||||
|
uint32 Mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct FBitReference
|
||||||
|
{
|
||||||
|
FORCEINLINE FBitReference(uint32& InData, uint32 InMask)
|
||||||
|
: Data(InData)
|
||||||
|
, Mask(InMask)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
FORCEINLINE const FBitReference(const uint32& InData, const uint32 InMask)
|
||||||
|
: Data(const_cast<uint32&>(InData))
|
||||||
|
, Mask(InMask)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void SetBit(const bool Value)
|
||||||
|
{
|
||||||
|
Value ? Data |= Mask : Data &= ~Mask;
|
||||||
|
|
||||||
|
// 10011101 - Data // 10011101 - Data
|
||||||
|
// 00000010 - Mask - true | // 00000010 - Mask - false
|
||||||
|
// 10011111 - |= // 11111101 - ~
|
||||||
|
// // 10011111 - &=
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE operator bool() const
|
||||||
|
{
|
||||||
|
return (Data & Mask) != 0;
|
||||||
|
}
|
||||||
|
FORCEINLINE void operator=(const bool Value)
|
||||||
|
{
|
||||||
|
this->SetBit(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32& Data;
|
||||||
|
uint32 Mask;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
class FBitIterator : public FRelativeBitReference
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
int32 Index;
|
||||||
|
const TBitArray& IteratedArray;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE const FBitIterator(const TBitArray& ToIterate, const int32 StartIndex) // Begin
|
||||||
|
: IteratedArray(ToIterate)
|
||||||
|
, Index(StartIndex)
|
||||||
|
, FRelativeBitReference(StartIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
FORCEINLINE const FBitIterator(const TBitArray& ToIterate) // End
|
||||||
|
: IteratedArray(ToIterate)
|
||||||
|
, Index(ToIterate.NumBits)
|
||||||
|
, FRelativeBitReference(ToIterate.NumBits)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
|
{
|
||||||
|
return Index < IteratedArray.Num();
|
||||||
|
}
|
||||||
|
FORCEINLINE FBitIterator& operator++()
|
||||||
|
{
|
||||||
|
++Index;
|
||||||
|
this->Mask <<= 1;
|
||||||
|
if (!this->Mask)
|
||||||
|
{
|
||||||
|
this->Mask = 1;
|
||||||
|
++this->DWORDIndex;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator*() const
|
||||||
|
{
|
||||||
|
// Thesis: Once there are more elements in the BitArray than InlineData can hold it'll just allocate all of
|
||||||
|
// them through SecondaryElements, leaving InlineData all true
|
||||||
|
|
||||||
|
if (IteratedArray.NumBits < IteratedArray.Data.NumInlineBits())
|
||||||
|
{
|
||||||
|
return (bool)FBitReference(IteratedArray.Data.GetInlineElement(this->DWORDIndex), this->Mask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (bool)FBitReference(IteratedArray.Data.GetSecondaryElement(this->DWORDIndex), this->Mask);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator==(const FBitIterator& OtherIt) const
|
||||||
|
{
|
||||||
|
return Index == OtherIt.Index;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator!=(const FBitIterator& OtherIt) const
|
||||||
|
{
|
||||||
|
return Index </*=*/ OtherIt.Index;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator < (const int32 Other) const
|
||||||
|
{
|
||||||
|
return Index < Other;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator > (const int32 Other) const
|
||||||
|
{
|
||||||
|
return Index < Other;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 GetIndex() const
|
||||||
|
{
|
||||||
|
return Index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FSetBitIterator : public FRelativeBitReference
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const TBitArray& IteratedArray;
|
||||||
|
|
||||||
|
uint32 UnvisitedBitMask;
|
||||||
|
int32 CurrentBitIndex;
|
||||||
|
int32 BaseBitIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE FSetBitIterator(const TBitArray& ToIterate, int32 StartIndex)
|
||||||
|
: FRelativeBitReference(StartIndex)
|
||||||
|
, IteratedArray(const_cast<TBitArray&>(ToIterate))
|
||||||
|
, UnvisitedBitMask((~0U) << (StartIndex & (NumBitsPerDWORD - 1)))
|
||||||
|
, CurrentBitIndex(StartIndex)
|
||||||
|
, BaseBitIndex(StartIndex & ~(NumBitsPerDWORD - 1))
|
||||||
|
{
|
||||||
|
if (StartIndex != IteratedArray.NumBits)
|
||||||
|
{
|
||||||
|
FindNextSetBit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FORCEINLINE FSetBitIterator(const TBitArray& ToIterate)
|
||||||
|
: FRelativeBitReference(ToIterate.NumBits)
|
||||||
|
, IteratedArray(const_cast<TBitArray&>(ToIterate))
|
||||||
|
, UnvisitedBitMask(0)
|
||||||
|
, CurrentBitIndex(ToIterate.NumBits)
|
||||||
|
, BaseBitIndex(ToIterate.NumBits)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE FSetBitIterator& operator++()
|
||||||
|
{
|
||||||
|
UnvisitedBitMask &= ~this->Mask;
|
||||||
|
|
||||||
|
FindNextSetBit();
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator*() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE bool operator==(const FSetBitIterator& Other) const
|
||||||
|
{
|
||||||
|
return CurrentBitIndex == Other.CurrentBitIndex;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator!=(const FSetBitIterator& Other) const
|
||||||
|
{
|
||||||
|
return CurrentBitIndex </*=*/ Other.CurrentBitIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
|
{
|
||||||
|
return CurrentBitIndex < IteratedArray.NumBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 GetIndex() const
|
||||||
|
{
|
||||||
|
return CurrentBitIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void FindNextSetBit()
|
||||||
|
{
|
||||||
|
//InlineData is the first 16-bytes of TBitArray
|
||||||
|
const uint32* ArrayData = (IteratedArray.Data.SecondaryData ? IteratedArray.Data.SecondaryData : (uint32*)&IteratedArray.Data.InlineData);
|
||||||
|
|
||||||
|
const int32 ArrayNum = IteratedArray.NumBits;
|
||||||
|
const int32 LastDWORDIndex = (ArrayNum - 1) / NumBitsPerDWORD;
|
||||||
|
|
||||||
|
uint32 RemainingBitMask = ArrayData[this->DWORDIndex] & UnvisitedBitMask;
|
||||||
|
while (!RemainingBitMask)
|
||||||
|
{
|
||||||
|
++this->DWORDIndex;
|
||||||
|
BaseBitIndex += NumBitsPerDWORD;
|
||||||
|
|
||||||
|
if (this->DWORDIndex > LastDWORDIndex)
|
||||||
|
{
|
||||||
|
CurrentBitIndex = ArrayNum;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemainingBitMask = ArrayData[this->DWORDIndex];
|
||||||
|
UnvisitedBitMask = ~0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32 NewRemainingBitMask = RemainingBitMask & (RemainingBitMask - 1);
|
||||||
|
|
||||||
|
this->Mask = NewRemainingBitMask ^ RemainingBitMask;
|
||||||
|
|
||||||
|
CurrentBitIndex = BaseBitIndex + NumBitsPerDWORD - 1 - CountLeadingZeros(this->Mask);
|
||||||
|
|
||||||
|
if (CurrentBitIndex > ArrayNum)
|
||||||
|
{
|
||||||
|
CurrentBitIndex = ArrayNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE FBitIterator Iterator(int32 StartIndex)
|
||||||
|
{
|
||||||
|
return FBitIterator(*this, StartIndex);
|
||||||
|
}
|
||||||
|
FORCEINLINE FSetBitIterator SetBitIterator(int32 StartIndex)
|
||||||
|
{
|
||||||
|
return FSetBitIterator(*this, StartIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE FBitIterator begin()
|
||||||
|
{
|
||||||
|
return FBitIterator(*this, 0);
|
||||||
|
}
|
||||||
|
FORCEINLINE const FBitIterator begin() const
|
||||||
|
{
|
||||||
|
return FBitIterator(*this, 0);
|
||||||
|
}
|
||||||
|
FORCEINLINE FBitIterator end()
|
||||||
|
{
|
||||||
|
return FBitIterator(*this);
|
||||||
|
}
|
||||||
|
FORCEINLINE const FBitIterator end() const
|
||||||
|
{
|
||||||
|
return FBitIterator(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE FSetBitIterator SetBitsItBegin()
|
||||||
|
{
|
||||||
|
return FSetBitIterator(*this, 0);
|
||||||
|
}
|
||||||
|
FORCEINLINE const FSetBitIterator SetBitsItBegin() const
|
||||||
|
{
|
||||||
|
return FSetBitIterator(*this, 0);
|
||||||
|
}
|
||||||
|
FORCEINLINE const FSetBitIterator SetBitsItEnd()
|
||||||
|
{
|
||||||
|
return FSetBitIterator(*this);
|
||||||
|
}
|
||||||
|
FORCEINLINE const FSetBitIterator SetBitsItEnd() const
|
||||||
|
{
|
||||||
|
return FSetBitIterator(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 Num() const
|
||||||
|
{
|
||||||
|
return NumBits;
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 Max() const
|
||||||
|
{
|
||||||
|
return MaxBits;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool IsSet(int32 Index) const
|
||||||
|
{
|
||||||
|
return *FBitIterator(*this, Index);
|
||||||
|
}
|
||||||
|
FORCEINLINE void Set(const int32 Index, const bool Value, bool bIsSettingAllZero = false)
|
||||||
|
{
|
||||||
|
const int32 DWORDIndex = (Index >> ((int32)5));
|
||||||
|
const int32 Mask = (1 << (Index & (((int32)32) - 1)));
|
||||||
|
|
||||||
|
if (!bIsSettingAllZero)
|
||||||
|
NumBits = Index >= NumBits ? Index < MaxBits ? Index + 1 : NumBits : NumBits;
|
||||||
|
|
||||||
|
FBitReference(Data[DWORDIndex], Mask).SetBit(Value);
|
||||||
|
}
|
||||||
|
FORCEINLINE void ZeroAll()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < MaxBits; i++)
|
||||||
|
{
|
||||||
|
Set(i, false, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -25,5 +25,47 @@ public:
|
|||||||
TTypeCompatibleBytes<ElementType> InlineData[NumElements];
|
TTypeCompatibleBytes<ElementType> InlineData[NumElements];
|
||||||
|
|
||||||
ElementType* SecondaryData;
|
ElementType* SecondaryData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
FORCEINLINE int32 NumInlineBytes() const
|
||||||
|
{
|
||||||
|
return sizeof(ElementType) * NumElements;
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 NumInlineBits() const
|
||||||
|
{
|
||||||
|
return NumInlineBytes() * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE ElementType& operator[](int32 Index)
|
||||||
|
{
|
||||||
|
return *(ElementType*)(&InlineData[Index]);
|
||||||
|
}
|
||||||
|
FORCEINLINE const ElementType& operator[](int32 Index) const
|
||||||
|
{
|
||||||
|
return *(ElementType*)(&InlineData[Index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE void operator=(void* InElements)
|
||||||
|
{
|
||||||
|
SecondaryData = InElements;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE ElementType& GetInlineElement(int32 Index)
|
||||||
|
{
|
||||||
|
return *(ElementType*)(&InlineData[Index]);
|
||||||
|
}
|
||||||
|
FORCEINLINE const ElementType& GetInlineElement(int32 Index) const
|
||||||
|
{
|
||||||
|
return *(ElementType*)(&InlineData[Index]);
|
||||||
|
}
|
||||||
|
FORCEINLINE ElementType& GetSecondaryElement(int32 Index)
|
||||||
|
{
|
||||||
|
return SecondaryData[Index];
|
||||||
|
}
|
||||||
|
FORCEINLINE const ElementType& GetSecondaryElement(int32 Index) const
|
||||||
|
{
|
||||||
|
return SecondaryData[Index];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -283,10 +283,12 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Fortnite_Version >= 4)
|
if (Fortnite_Version >= 4)
|
||||||
|
{
|
||||||
SetPlaylist(PlaylistToUse, true);
|
SetPlaylist(PlaylistToUse, true);
|
||||||
|
|
||||||
auto CurrentPlaylist = GameState->GetCurrentPlaylist();
|
auto CurrentPlaylist = GameState->GetCurrentPlaylist();
|
||||||
LOG_INFO(LogDev, "Set playlist to {}!", CurrentPlaylist->IsValidLowLevel() ? CurrentPlaylist->GetFullName() : "Invalid");
|
LOG_INFO(LogDev, "Set playlist to {}!", CurrentPlaylist->IsValidLowLevel() ? CurrentPlaylist->GetFullName() : "Invalid");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (false)
|
// if (false)
|
||||||
@@ -424,15 +426,17 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto PlaylistToUse = GetPlaylistToUse();
|
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
|
||||||
|
|
||||||
if (PlaylistToUse)
|
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
|
||||||
|
|
||||||
|
if (CurrentPlaylist)
|
||||||
{
|
{
|
||||||
static auto AdditionalLevelsOffset = PlaylistToUse->GetOffset("AdditionalLevels", false);
|
static auto AdditionalLevelsOffset = CurrentPlaylist->GetOffset("AdditionalLevels", false);
|
||||||
|
|
||||||
if (AdditionalLevelsOffset != -1)
|
if (AdditionalLevelsOffset != -1)
|
||||||
{
|
{
|
||||||
auto& AdditionalLevels = PlaylistToUse->Get<TArray<TSoftObjectPtr<UClass>>>(AdditionalLevelsOffset);
|
auto& AdditionalLevels = CurrentPlaylist->Get<TArray<TSoftObjectPtr<UClass>>>(AdditionalLevelsOffset);
|
||||||
|
|
||||||
LOG_INFO(LogPlaylist, "Loading {} playlist levels.", AdditionalLevels.Num());
|
LOG_INFO(LogPlaylist, "Loading {} playlist levels.", AdditionalLevels.Num());
|
||||||
|
|
||||||
@@ -525,6 +529,10 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
float TimeSeconds = UGameplayStatics::GetTimeSeconds(GetWorld());
|
float TimeSeconds = UGameplayStatics::GetTimeSeconds(GetWorld());
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Initializing!");
|
LOG_INFO(LogDev, "Initializing!");
|
||||||
|
|
||||||
|
if (std::floor(Fortnite_Version) == 3)
|
||||||
|
SetPlaylist(GetPlaylistToUse(), true);
|
||||||
|
|
||||||
LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode));
|
LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode));
|
||||||
|
|
||||||
GameState->Get<float>("WarmupCountdownEndTime") = TimeSeconds + Duration;
|
GameState->Get<float>("WarmupCountdownEndTime") = TimeSeconds + Duration;
|
||||||
@@ -539,26 +547,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
|
|
||||||
GameSession->Get<int>(MaxPlayersOffset) = 100;
|
GameSession->Get<int>(MaxPlayersOffset) = 100;
|
||||||
|
|
||||||
/*
|
|
||||||
auto AllMegaStormManagers = UGameplayStatics::GetAllActorsOfClass(GetWorld(), GameMode->Get<UClass*>("MegaStormManagerClass"));
|
|
||||||
|
|
||||||
LOG_INFO(LogDev, "AllMegaStormManagers.Num() {}", AllMegaStormManagers.Num());
|
|
||||||
|
|
||||||
if (AllMegaStormManagers.Num())
|
|
||||||
{
|
|
||||||
auto MegaStormManager = (AMegaStormManager*)AllMegaStormManagers.at(0); // GameMode->Get<AMegaStormManager*>(MegaStormManagerOffset);
|
|
||||||
|
|
||||||
LOG_INFO(LogDev, "MegaStormManager {}", __int64(MegaStormManager));
|
|
||||||
|
|
||||||
if (MegaStormManager)
|
|
||||||
{
|
|
||||||
LOG_INFO(LogDev, "MegaStormManager->GetMegaStormCircles().Num() {}", MegaStormManager->GetMegaStormCircles().Num());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// GameState->Get<bool>("bGameModeWillSkipAircraft") = Globals::bGoingToPlayEvent && Fortnite_Version == 17.30;
|
|
||||||
|
|
||||||
// if (Engine_Version < 424)
|
// if (Engine_Version < 424)
|
||||||
GameState->OnRep_CurrentPlaylistInfo(); // ?
|
GameState->OnRep_CurrentPlaylistInfo(); // ?
|
||||||
|
|
||||||
@@ -807,8 +795,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
Parts[(int)EFortCustomPartType::Head] = headPart;
|
Parts[(int)EFortCustomPartType::Head] = headPart;
|
||||||
Parts[(int)EFortCustomPartType::Body] = bodyPart;
|
Parts[(int)EFortCustomPartType::Body] = bodyPart;
|
||||||
|
|
||||||
if (Fortnite_Version > 2.5)
|
// if (Fortnite_Version > 2.5)
|
||||||
Parts[(int)EFortCustomPartType::Backpack] = backpackPart;
|
Parts[(int)EFortCustomPartType::Backpack] = backpackPart;
|
||||||
|
|
||||||
static auto OnRep_CharacterPartsFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts");
|
static auto OnRep_CharacterPartsFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts");
|
||||||
PlayerStateAthena->ProcessEvent(OnRep_CharacterPartsFn);
|
PlayerStateAthena->ProcessEvent(OnRep_CharacterPartsFn);
|
||||||
@@ -865,16 +853,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
{
|
{
|
||||||
UClass* AbilityClass = GameplayAbilities->At(i);
|
UClass* AbilityClass = GameplayAbilities->At(i);
|
||||||
|
|
||||||
// LOG_INFO(LogDev, "AbilityClass {}", __int64(AbilityClass));
|
|
||||||
|
|
||||||
if (!AbilityClass)
|
if (!AbilityClass)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// LOG_INFO(LogDev, "AbilityClass Name {}", AbilityClass->GetFullName());
|
|
||||||
|
|
||||||
// LOG_INFO(LogDev, "DefaultAbility {}", __int64(DefaultAbility));
|
|
||||||
// LOG_INFO(LogDev, "DefaultAbility Name {}", DefaultAbility->GetFullName());
|
|
||||||
|
|
||||||
PlayerStateAthena->GetAbilitySystemComponent()->GiveAbilityEasy(AbilityClass);
|
PlayerStateAthena->GetAbilitySystemComponent()->GiveAbilityEasy(AbilityClass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
|||||||
|
|
||||||
if (LoadedAmmo == -1)
|
if (LoadedAmmo == -1)
|
||||||
{
|
{
|
||||||
if (auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDefinition))
|
if (auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDefinition)) // bPreventDefaultPreload ?
|
||||||
LoadedAmmo = WeaponDef->GetClipSize();
|
LoadedAmmo = WeaponDef->GetClipSize();
|
||||||
else
|
else
|
||||||
LoadedAmmo = 0;
|
LoadedAmmo = 0;
|
||||||
|
|||||||
@@ -229,125 +229,128 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
|||||||
auto GameFeatureData = Object;
|
auto GameFeatureData = Object;
|
||||||
static auto DefaultLootTableDataOffset = GameFeatureData->GetOffset("DefaultLootTableData");
|
static auto DefaultLootTableDataOffset = GameFeatureData->GetOffset("DefaultLootTableData");
|
||||||
|
|
||||||
auto DefaultLootTableData = GameFeatureData->GetPtr<FFortGameFeatureLootTableData>(DefaultLootTableDataOffset);
|
if (DefaultLootTableDataOffset != -1)
|
||||||
|
|
||||||
auto LootTierDataTableStr = DefaultLootTableData->LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
|
|
||||||
auto LootTierDataTableIsComposite = LootTierDataTableStr.contains("Composite");
|
|
||||||
auto LootPackageTableStr = DefaultLootTableData->LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto LootPackageTableIsComposite = LootPackageTableStr.contains("Composite");
|
|
||||||
|
|
||||||
auto LootTierDataPtr = DefaultLootTableData->LootTierData.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
|
||||||
auto LootPackagePtr = DefaultLootTableData->LootPackageData.Get(LootPackageTableIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
|
||||||
|
|
||||||
if (LootPackagePtr)
|
|
||||||
{
|
{
|
||||||
LPTables.push_back(LootPackagePtr);
|
auto DefaultLootTableData = GameFeatureData->GetPtr<FFortGameFeatureLootTableData>(DefaultLootTableDataOffset);
|
||||||
}
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
auto LootTierDataTableStr = DefaultLootTableData->LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
{
|
|
||||||
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
|
||||||
auto PlaylistOverrideLootTableData = GameFeatureData->GetPtr<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
|
||||||
|
|
||||||
auto PlaylistOverrideLootTableData_Data = PlaylistOverrideLootTableData->Pairs.Elements.Data;
|
auto LootTierDataTableIsComposite = LootTierDataTableStr.contains("Composite");
|
||||||
|
auto LootPackageTableStr = DefaultLootTableData->LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto LootPackageTableIsComposite = LootPackageTableStr.contains("Composite");
|
||||||
|
|
||||||
static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer");
|
auto LootTierDataPtr = DefaultLootTableData->LootTierData.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
||||||
auto GameplayTagContainer = CurrentPlaylist->GetPtr<FGameplayTagContainer>(GameplayTagContainerOffset);
|
auto LootPackagePtr = DefaultLootTableData->LootPackageData.Get(LootPackageTableIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
||||||
|
|
||||||
for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++)
|
if (LootPackagePtr)
|
||||||
{
|
{
|
||||||
auto& Tag = GameplayTagContainer->GameplayTags.At(i);
|
LPTables.push_back(LootPackagePtr);
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < PlaylistOverrideLootTableData_Data.Num(); j++)
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
||||||
|
auto PlaylistOverrideLootTableData = GameFeatureData->GetPtr<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
||||||
|
|
||||||
|
auto PlaylistOverrideLootTableData_Data = PlaylistOverrideLootTableData->Pairs.Elements.Data;
|
||||||
|
|
||||||
|
static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer");
|
||||||
|
auto GameplayTagContainer = CurrentPlaylist->GetPtr<FGameplayTagContainer>(GameplayTagContainerOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++)
|
||||||
{
|
{
|
||||||
auto Value = PlaylistOverrideLootTableData_Data.at(j).ElementData.Value;
|
auto& Tag = GameplayTagContainer->GameplayTags.At(i);
|
||||||
auto CurrentOverrideTag = Value.First;
|
|
||||||
|
|
||||||
if (Tag.TagName == CurrentOverrideTag.TagName)
|
for (int j = 0; j < PlaylistOverrideLootTableData_Data.Num(); j++)
|
||||||
{
|
{
|
||||||
auto OverrideLootPackageTableStr = Value.Second.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
auto Value = PlaylistOverrideLootTableData_Data.at(j).ElementData.Value;
|
||||||
auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite");
|
auto CurrentOverrideTag = Value.First;
|
||||||
|
|
||||||
auto ptr = Value.Second.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
if (Tag.TagName == CurrentOverrideTag.TagName)
|
||||||
|
|
||||||
if (ptr)
|
|
||||||
{
|
{
|
||||||
if (bOverrideIsComposite)
|
auto OverrideLootPackageTableStr = Value.Second.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite");
|
||||||
|
|
||||||
|
auto ptr = Value.Second.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
{
|
{
|
||||||
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
if (bOverrideIsComposite)
|
||||||
|
|
||||||
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
|
||||||
|
|
||||||
for (int z = 0; z < ParentTables->size(); z++)
|
|
||||||
{
|
{
|
||||||
auto ParentTable = ParentTables->At(z);
|
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
||||||
|
|
||||||
if (ParentTable)
|
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
||||||
|
|
||||||
|
for (int z = 0; z < ParentTables->size(); z++)
|
||||||
{
|
{
|
||||||
LPTables.push_back(ParentTable);
|
auto ParentTable = ParentTables->At(z);
|
||||||
|
|
||||||
|
if (ParentTable)
|
||||||
|
{
|
||||||
|
LPTables.push_back(ParentTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LPTables.push_back(ptr);
|
LPTables.push_back(ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (LootTierDataPtr)
|
if (LootTierDataPtr)
|
||||||
{
|
|
||||||
LTDTables.push_back(LootTierDataPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
|
||||||
{
|
|
||||||
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
|
||||||
auto PlaylistOverrideLootTableData = GameFeatureData->GetPtr<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
|
||||||
|
|
||||||
auto PlaylistOverrideLootTableData_Data = PlaylistOverrideLootTableData->Pairs.Elements.Data;
|
|
||||||
|
|
||||||
static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer");
|
|
||||||
auto GameplayTagContainer = CurrentPlaylist->GetPtr<FGameplayTagContainer>(GameplayTagContainerOffset);
|
|
||||||
|
|
||||||
for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++)
|
|
||||||
{
|
{
|
||||||
auto& Tag = GameplayTagContainer->GameplayTags.At(i);
|
LTDTables.push_back(LootTierDataPtr);
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = 0; j < PlaylistOverrideLootTableData_Data.Num(); j++)
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
||||||
|
auto PlaylistOverrideLootTableData = GameFeatureData->GetPtr<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
||||||
|
|
||||||
|
auto PlaylistOverrideLootTableData_Data = PlaylistOverrideLootTableData->Pairs.Elements.Data;
|
||||||
|
|
||||||
|
static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer");
|
||||||
|
auto GameplayTagContainer = CurrentPlaylist->GetPtr<FGameplayTagContainer>(GameplayTagContainerOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++)
|
||||||
{
|
{
|
||||||
auto Value = PlaylistOverrideLootTableData_Data.at(j).ElementData.Value;
|
auto& Tag = GameplayTagContainer->GameplayTags.At(i);
|
||||||
auto CurrentOverrideTag = Value.First;
|
|
||||||
|
|
||||||
if (Tag.TagName == CurrentOverrideTag.TagName)
|
for (int j = 0; j < PlaylistOverrideLootTableData_Data.Num(); j++)
|
||||||
{
|
{
|
||||||
auto OverrideLootTierDataStr = Value.Second.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
auto Value = PlaylistOverrideLootTableData_Data.at(j).ElementData.Value;
|
||||||
auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite");
|
auto CurrentOverrideTag = Value.First;
|
||||||
|
|
||||||
auto ptr = Value.Second.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
if (Tag.TagName == CurrentOverrideTag.TagName)
|
||||||
|
|
||||||
if (ptr)
|
|
||||||
{
|
{
|
||||||
if (bOverrideIsComposite)
|
auto OverrideLootTierDataStr = Value.Second.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite");
|
||||||
|
|
||||||
|
auto ptr = Value.Second.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : DataTableClass, true);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
{
|
{
|
||||||
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
if (bOverrideIsComposite)
|
||||||
|
|
||||||
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
|
||||||
|
|
||||||
for (int z = 0; z < ParentTables->size(); z++)
|
|
||||||
{
|
{
|
||||||
auto ParentTable = ParentTables->At(z);
|
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
||||||
|
|
||||||
if (ParentTable)
|
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
||||||
|
|
||||||
|
for (int z = 0; z < ParentTables->size(); z++)
|
||||||
{
|
{
|
||||||
LTDTables.push_back(ParentTable);
|
auto ParentTable = ParentTables->At(z);
|
||||||
|
|
||||||
|
if (ParentTable)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(ParentTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LTDTables.push_back(ptr);
|
LTDTables.push_back(ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController
|
|||||||
if (Engine_Version <= 420)
|
if (Engine_Version <= 420)
|
||||||
{
|
{
|
||||||
static auto OverriddenBackpackSizeOffset = PlayerController->GetOffset("OverriddenBackpackSize");
|
static auto OverriddenBackpackSizeOffset = PlayerController->GetOffset("OverriddenBackpackSize");
|
||||||
LOG_INFO(LogDev, "PlayerController->Get<int>(OverriddenBackpackSizeOffset): {}", PlayerController->Get<int>(OverriddenBackpackSizeOffset));
|
// LOG_INFO(LogDev, "PlayerController->Get<int>(OverriddenBackpackSizeOffset): {}", PlayerController->Get<int>(OverriddenBackpackSizeOffset));
|
||||||
// PlayerController->Get<int>(OverriddenBackpackSizeOffset) = 5;
|
// PlayerController->Get<int>(OverriddenBackpackSizeOffset) = 5;
|
||||||
// PlayerController->ForceNetUpdate();
|
// PlayerController->ForceNetUpdate();
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
|||||||
auto Vehicle = ReceivingActor;
|
auto Vehicle = ReceivingActor;
|
||||||
ServerAttemptInteractOriginal(Context, Stack, Ret);
|
ServerAttemptInteractOriginal(Context, Stack, Ret);
|
||||||
|
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
auto Pawn = (AFortPlayerPawn*)PlayerController->GetMyFortPawn();
|
auto Pawn = (AFortPlayerPawn*)PlayerController->GetMyFortPawn();
|
||||||
|
|
||||||
@@ -287,19 +287,6 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
else if (ReceivingActor->IsA(FortAthenaSupplyDropClass))
|
|
||||||
{
|
|
||||||
auto LootTierGroup = ReceivingActor->IsA(LlamaClass) ? UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaLlama") : UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaSupplyDrop"); // SupplyDrop->GetLootTierGroupOverride();
|
|
||||||
|
|
||||||
auto LootDrops = PickLootDrops(LootTierGroup);
|
|
||||||
|
|
||||||
for (auto& LootDrop : LootDrops)
|
|
||||||
{
|
|
||||||
AFortPickup::SpawnPickup(LootDrop.ItemDefinition, LocationToSpawnLoot, LootDrop.Count, EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::SupplyDrop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
return ServerAttemptInteractOriginal(Context, Stack, Ret);
|
return ServerAttemptInteractOriginal(Context, Stack, Ret);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,29 @@
|
|||||||
|
|
||||||
struct FFortAthenaLoadout
|
struct FFortAthenaLoadout
|
||||||
{
|
{
|
||||||
|
static UStruct* GetStruct()
|
||||||
|
{
|
||||||
|
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortAthenaLoadout");
|
||||||
|
return Struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int GetStructSize()
|
||||||
|
{
|
||||||
|
return GetStruct()->GetPropertiesSize();
|
||||||
|
}
|
||||||
|
|
||||||
UObject*& GetCharacter()
|
UObject*& GetCharacter()
|
||||||
{
|
{
|
||||||
static auto CharacterOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Character");
|
static auto CharacterOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Character");
|
||||||
return *(UObject**)(__int64(this) + CharacterOffset);
|
return *(UObject**)(__int64(this) + CharacterOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UObject*& GetBackpack()
|
||||||
|
{
|
||||||
|
static auto BackpackOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Backpack");
|
||||||
|
return *(UObject**)(__int64(this) + BackpackOffset);
|
||||||
|
}
|
||||||
|
|
||||||
UObject*& GetPickaxe()
|
UObject*& GetPickaxe()
|
||||||
{
|
{
|
||||||
static auto PickaxeOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Pickaxe");
|
static auto PickaxeOffset = FindOffsetStruct("/Script/FortniteGame.FortAthenaLoadout", "Pickaxe");
|
||||||
|
|||||||
@@ -72,12 +72,19 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl
|
|||||||
auto PawnAsFort = Cast<AFortPlayerPawn>(Pawn);
|
auto PawnAsFort = Cast<AFortPlayerPawn>(Pawn);
|
||||||
auto PlayerStateAsFort = Cast<AFortPlayerState>(Pawn->GetPlayerState());
|
auto PlayerStateAsFort = Cast<AFortPlayerState>(Pawn->GetPlayerState());
|
||||||
|
|
||||||
if (Globals::bNoMCP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!PawnAsFort)
|
if (!PawnAsFort)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (Globals::bNoMCP)
|
||||||
|
{
|
||||||
|
static auto CustomCharacterPartClass = FindObject<UClass>("/Script/FortniteGame.CustomCharacterPart");
|
||||||
|
static auto backpackPart = LoadObject("/Game/Characters/CharacterParts/Backpacks/NoBackpack.NoBackpack", CustomCharacterPartClass);
|
||||||
|
|
||||||
|
// PawnAsFort->ServerChoosePart(EFortCustomPartType::Backpack, backpackPart);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static auto UpdatePlayerCustomCharacterPartsVisualizationFn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.UpdatePlayerCustomCharacterPartsVisualization");
|
static auto UpdatePlayerCustomCharacterPartsVisualizationFn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.UpdatePlayerCustomCharacterPartsVisualization");
|
||||||
|
|
||||||
if (!UpdatePlayerCustomCharacterPartsVisualizationFn)
|
if (!UpdatePlayerCustomCharacterPartsVisualizationFn)
|
||||||
@@ -85,8 +92,41 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl
|
|||||||
auto CosmeticLoadout = ControllerAsFort->GetCosmeticLoadout();
|
auto CosmeticLoadout = ControllerAsFort->GetCosmeticLoadout();
|
||||||
|
|
||||||
if (CosmeticLoadout)
|
if (CosmeticLoadout)
|
||||||
|
{
|
||||||
|
/* static auto Pawn_CosmeticLoadoutOffset = PawnAsFort->GetOffset("CosmeticLoadout");
|
||||||
|
|
||||||
|
if (Pawn_CosmeticLoadoutOffset != -1)
|
||||||
|
{
|
||||||
|
CopyStruct(PawnAsFort->GetPtr<__int64>(Pawn_CosmeticLoadoutOffset), CosmeticLoadout, FFortAthenaLoadout::GetStructSize());
|
||||||
|
} */
|
||||||
|
|
||||||
ApplyCID(PawnAsFort, CosmeticLoadout->GetCharacter());
|
ApplyCID(PawnAsFort, CosmeticLoadout->GetCharacter());
|
||||||
|
|
||||||
|
auto Backpack = CosmeticLoadout->GetBackpack();
|
||||||
|
|
||||||
|
if (Backpack)
|
||||||
|
{
|
||||||
|
static auto CharacterPartsOffset = Backpack->GetOffset("CharacterParts");
|
||||||
|
|
||||||
|
if (CharacterPartsOffset != -1)
|
||||||
|
{
|
||||||
|
auto& BackpackCharacterParts = Backpack->Get<TArray<UObject*>>(CharacterPartsOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < BackpackCharacterParts.Num(); i++)
|
||||||
|
{
|
||||||
|
auto BackpackCharacterPart = BackpackCharacterParts.at(i);
|
||||||
|
|
||||||
|
if (!BackpackCharacterPart)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
PawnAsFort->ServerChoosePart(EFortCustomPartType::Backpack, BackpackCharacterPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UFortKismetLibrary::ApplyCharacterCosmetics(GetWorld(), BackpackCharacterParts, PlayerStateAsFort, &aa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID)
|
|||||||
{
|
{
|
||||||
auto& SpecializationSoft = Specializations.at(i);
|
auto& SpecializationSoft = Specializations.at(i);
|
||||||
|
|
||||||
auto Specialization = SpecializationSoft.Get();
|
static auto FortHeroSpecializationClass = FindObject<UClass>("/Script/FortniteGame.FortHeroSpecialization");
|
||||||
|
auto Specialization = SpecializationSoft.Get(FortHeroSpecializationClass, true);
|
||||||
|
|
||||||
if (Specialization)
|
if (Specialization)
|
||||||
{
|
{
|
||||||
@@ -40,7 +41,8 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID)
|
|||||||
for (int z = 0; z < CharacterParts.Num(); z++)
|
for (int z = 0; z < CharacterParts.Num(); z++)
|
||||||
{
|
{
|
||||||
auto& CharacterPartSoft = CharacterParts.at(z);
|
auto& CharacterPartSoft = CharacterParts.at(z);
|
||||||
auto CharacterPart = CharacterPartSoft.Get();
|
static auto CustomCharacterPartClass = FindObject<UClass>("/Script/FortniteGame.CustomCharacterPart");
|
||||||
|
auto CharacterPart = CharacterPartSoft.Get(CustomCharacterPartClass, true);
|
||||||
|
|
||||||
CharacterPartsaa.Add(CharacterPart);
|
CharacterPartsaa.Add(CharacterPart);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void AFortPlayerPawn::ServerChoosePart(EFortCustomPartType Part, UObject* Chosen
|
|||||||
this->ProcessEvent(fn, &AFortPlayerPawn_ServerChoosePart_Params);
|
this->ProcessEvent(fn, &AFortPlayerPawn_ServerChoosePart_Params);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AFortPlayerPawn::ForceLaunchPlayerZiplinine() // Thanks android
|
void AFortPlayerPawn::ForceLaunchPlayerZipline() // Thanks android
|
||||||
{
|
{
|
||||||
float ZiplineJumpDampening = -0.5f;
|
float ZiplineJumpDampening = -0.5f;
|
||||||
float ZiplineJumpStrength = 1500.f;
|
float ZiplineJumpStrength = 1500.f;
|
||||||
@@ -70,7 +70,7 @@ void AFortPlayerPawn::ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZipline
|
|||||||
{
|
{
|
||||||
if ((*(bool*)(__int64(PawnZiplineState) + bJumpedOffset)))
|
if ((*(bool*)(__int64(PawnZiplineState) + bJumpedOffset)))
|
||||||
{
|
{
|
||||||
Pawn->ForceLaunchPlayerZiplinine();
|
Pawn->ForceLaunchPlayerZipline();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class AFortPlayerPawn : public AFortPawn
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void ServerChoosePart(EFortCustomPartType Part, class UObject* ChosenCharacterPart);
|
void ServerChoosePart(EFortCustomPartType Part, class UObject* ChosenCharacterPart);
|
||||||
void ForceLaunchPlayerZiplinine(); // Thanks android
|
void ForceLaunchPlayerZipline(); // Thanks android
|
||||||
|
|
||||||
static void ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZiplinePawnState InZiplineState);
|
static void ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZiplinePawnState InZiplineState);
|
||||||
static void ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup, float InFlyTime, FVector InStartDirection, bool bPlayPickupSound);
|
static void ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup, float InFlyTime, FVector InStartDirection, bool bPlayPickupSound);
|
||||||
|
|||||||
25
Project Reboot 3.0/Level.cpp
Normal file
25
Project Reboot 3.0/Level.cpp
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#include "Level.h"
|
||||||
|
|
||||||
|
UWorld*& ULevel::GetOwningWorld()
|
||||||
|
{
|
||||||
|
static auto OwningWorldOffset = GetOffset("OwningWorld");
|
||||||
|
return Get<UWorld*>(OwningWorldOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ULevel::HasVisibilityChangeRequestPending()
|
||||||
|
{
|
||||||
|
// I believe implementation on this changes depending on the version
|
||||||
|
|
||||||
|
auto OwningWorld = GetOwningWorld();
|
||||||
|
|
||||||
|
if (!OwningWorld)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
static auto CurrentLevelPendingVisibilityOffset = OwningWorld->GetOffset("CurrentLevelPendingVisibility");
|
||||||
|
auto CurrentLevelPendingVisibility = OwningWorld->Get<ULevel*>(CurrentLevelPendingVisibilityOffset);
|
||||||
|
|
||||||
|
static auto CurrentLevelPendingInvisibilityOffset= OwningWorld->GetOffset("CurrentLevelPendingInvisibility");
|
||||||
|
auto CurrentLevelPendingInvisibility = OwningWorld->Get<ULevel*>(CurrentLevelPendingInvisibilityOffset);
|
||||||
|
|
||||||
|
return this == CurrentLevelPendingVisibility || this == CurrentLevelPendingInvisibility;
|
||||||
|
}
|
||||||
10
Project Reboot 3.0/Level.h
Normal file
10
Project Reboot 3.0/Level.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "World.h"
|
||||||
|
|
||||||
|
class ULevel : public UObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UWorld*& GetOwningWorld();
|
||||||
|
bool HasVisibilityChangeRequestPending();
|
||||||
|
};
|
||||||
@@ -5,6 +5,20 @@
|
|||||||
#include "NetConnection.h"
|
#include "NetConnection.h"
|
||||||
#include "FortPlayerControllerAthena.h"
|
#include "FortPlayerControllerAthena.h"
|
||||||
#include "GameplayStatics.h"
|
#include "GameplayStatics.h"
|
||||||
|
#include "KismetMathLibrary.h"
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
FNetworkObjectList& UNetDriver::GetNetworkObjectList()
|
||||||
|
{
|
||||||
|
return *(*(TSharedPtr<FNetworkObjectList>*)(__int64(this) + 0x490));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UNetDriver::RemoveNetworkActor(AActor* Actor)
|
||||||
|
{
|
||||||
|
GetNetworkObjectList().Remove(Actor);
|
||||||
|
|
||||||
|
// RenamedStartupActors.Remove(Actor->GetFName());
|
||||||
|
}
|
||||||
|
|
||||||
void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
|
void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
|
||||||
{
|
{
|
||||||
@@ -34,7 +48,7 @@ int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
|||||||
for (int32 ConnIdx = 0; ConnIdx < ClientConnections.Num(); ConnIdx++)
|
for (int32 ConnIdx = 0; ConnIdx < ClientConnections.Num(); ConnIdx++)
|
||||||
{
|
{
|
||||||
UNetConnection* Connection = ClientConnections.at(ConnIdx);
|
UNetConnection* Connection = ClientConnections.at(ConnIdx);
|
||||||
// check(Connection);
|
if (!Connection) continue;
|
||||||
// check(Connection->State == USOCK_Pending || Connection->State == USOCK_Open || Connection->State == USOCK_Closed);
|
// check(Connection->State == USOCK_Pending || Connection->State == USOCK_Open || Connection->State == USOCK_Closed);
|
||||||
// checkSlow(Connection->GetUChildConnection() == NULL);
|
// checkSlow(Connection->GetUChildConnection() == NULL);
|
||||||
|
|
||||||
@@ -42,13 +56,8 @@ int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver)
|
|||||||
|
|
||||||
if (OwningActor != NULL) // && /* Connection->State == USOCK_Open && */ (Connection->Driver->Time - Connection->LastReceiveTime < 1.5f))
|
if (OwningActor != NULL) // && /* Connection->State == USOCK_Open && */ (Connection->Driver->Time - Connection->LastReceiveTime < 1.5f))
|
||||||
{
|
{
|
||||||
// check(World == OwningActor->GetWorld());
|
|
||||||
|
|
||||||
bFoundReadyConnection = true;
|
bFoundReadyConnection = true;
|
||||||
|
|
||||||
// the view target is what the player controller is looking at OR the owning actor itself when using beacons
|
|
||||||
// Connection->GetViewTarget() = Connection->GetPlayerController() ? Connection->GetPlayerController()->GetViewTarget() : OwningActor;
|
|
||||||
|
|
||||||
AActor* DesiredViewTarget = OwningActor;
|
AActor* DesiredViewTarget = OwningActor;
|
||||||
|
|
||||||
if (Connection->GetPlayerController())
|
if (Connection->GetPlayerController())
|
||||||
@@ -90,42 +99,61 @@ enum class ENetDormancy : uint8_t
|
|||||||
ENetDormancy_MAX = 6
|
ENetDormancy_MAX = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FNetworkObjectInfo
|
FORCEINLINE float FRand()
|
||||||
{
|
{
|
||||||
AActor* Actor;
|
std::random_device rd;
|
||||||
/* TWeakObjectPtr<AActor> WeakActor;
|
std::mt19937 gen(rd());
|
||||||
double NextUpdateTime;
|
std::uniform_real_distribution<> dis(0, 1);
|
||||||
double LastNetReplicateTime;
|
float random_number = dis(gen);
|
||||||
float OptimalNetUpdateDelta;
|
|
||||||
float LastNetUpdateTime;
|
|
||||||
uint32 bPendingNetUpdate : 1;
|
|
||||||
uint32 bForceRelevantNextUpdate : 1;
|
|
||||||
TSet<TWeakObjectPtr<UNetConnection>> DormantConnections;
|
|
||||||
TSet<TWeakObjectPtr<UNetConnection>> RecentlyDormantConnections; */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ServerReplicateActors_BuildConsiderList(UNetDriver* NetDriver, std::vector<FNetworkObjectInfo*>& OutConsiderList)
|
return random_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define USEOBJECTLIST
|
||||||
|
|
||||||
|
void UNetDriver::ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList)
|
||||||
{
|
{
|
||||||
|
std::vector<AActor*> ActorsToRemove;
|
||||||
|
|
||||||
|
#ifdef USEOBJECTLIST
|
||||||
|
auto& ActiveObjects = GetNetworkObjectList().ActiveNetworkObjects;
|
||||||
|
#else
|
||||||
TArray<AActor*> Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass());
|
TArray<AActor*> Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass());
|
||||||
|
#endif
|
||||||
|
|
||||||
/* auto& ActiveObjects = GetNetworkObjectList(NetDriver).ActiveNetworkObjects;
|
auto World = GetWorld();
|
||||||
|
|
||||||
for (int i = 0; i < ActiveObjects.Num(); i++)
|
#ifdef USEOBJECTLIST
|
||||||
|
// for (int i = 0; i < ActiveObjects.Elements.Num(); i++)
|
||||||
|
for (const TSharedPtr<FNetworkObjectInfo>& ActorInfo : ActiveObjects)
|
||||||
{
|
{
|
||||||
auto ActorInfo = ActiveObjects.GetElements().GetData()[i].ElementData.Value.Get();
|
// auto& ActorInfo = ActiveObjects.Elements.Data.at(i).ElementData.Value;
|
||||||
auto Actor = ActorInfo->Actor; */
|
|
||||||
|
if (!ActorInfo->bPendingNetUpdate && UGameplayStatics::GetTimeSeconds(GetWorld()) <= ActorInfo->NextUpdateTime)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (IsBadReadPtr(ActorInfo, 8))
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
auto Actor = ActorInfo->Actor;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
for (int i = 0; i < Actors.Num(); i++)
|
for (int i = 0; i < Actors.Num(); i++)
|
||||||
{
|
{
|
||||||
auto Actor = Actors.at(i);
|
auto Actor = Actors.at(i);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!Actor)
|
if (!Actor)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// if (!Actor->bActorInitialized) continue;
|
if (Actor->IsPendingKillPending())
|
||||||
|
// if (Actor->IsPendingKill())
|
||||||
if (Actor->IsActorBeingDestroyed())
|
|
||||||
{
|
{
|
||||||
|
ActorsToRemove.push_back(Actor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,25 +161,93 @@ static void ServerReplicateActors_BuildConsiderList(UNetDriver* NetDriver, std::
|
|||||||
|
|
||||||
if (Actor->Get<ENetRole>(RemoteRoleOffset) == ENetRole::ROLE_None)
|
if (Actor->Get<ENetRole>(RemoteRoleOffset) == ENetRole::ROLE_None)
|
||||||
{
|
{
|
||||||
|
ActorsToRemove.push_back(Actor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We should add a NetDriverName check but I don't believe it is needed.
|
||||||
|
|
||||||
|
// We should check if the actor is initialized here.
|
||||||
|
|
||||||
|
// We should check the level stuff here.
|
||||||
|
|
||||||
static auto NetDormancyOffset = Actor->GetOffset("NetDormancy");
|
static auto NetDormancyOffset = Actor->GetOffset("NetDormancy");
|
||||||
|
|
||||||
if (Actor->Get<ENetDormancy>(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartup())
|
if (Actor->Get<ENetDormancy>(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartupActor()) // IsDormInitialStartupActor
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
// We should check NeedsLoadForClient here.
|
||||||
CallPreReplication(Actor, NetDriver);
|
// We should make sure the actor is in the same world here but I don't believe it is needed.
|
||||||
|
|
||||||
|
#ifndef USEOBJECTLIST
|
||||||
FNetworkObjectInfo* ActorInfo = new FNetworkObjectInfo;
|
FNetworkObjectInfo* ActorInfo = new FNetworkObjectInfo;
|
||||||
ActorInfo->Actor = Actor;
|
ActorInfo->Actor = Actor;
|
||||||
OutConsiderList.push_back(ActorInfo);
|
#else
|
||||||
|
auto TimeSeconds = UGameplayStatics::GetTimeSeconds(World); // Can we do this outside of the loop?
|
||||||
|
|
||||||
|
if (ActorInfo->LastNetReplicateTime == 0)
|
||||||
|
{
|
||||||
|
ActorInfo->LastNetReplicateTime = UGameplayStatics::GetTimeSeconds(World);
|
||||||
|
ActorInfo->OptimalNetUpdateDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
||||||
|
}
|
||||||
|
|
||||||
|
const float ScaleDownStartTime = 2.0f;
|
||||||
|
const float ScaleDownTimeRange = 5.0f;
|
||||||
|
|
||||||
|
const float LastReplicateDelta = TimeSeconds - ActorInfo->LastNetReplicateTime;
|
||||||
|
|
||||||
|
if (LastReplicateDelta > ScaleDownStartTime)
|
||||||
|
{
|
||||||
|
static auto MinNetUpdateFrequencyOffset = Actor->GetOffset("MinNetUpdateFrequency");
|
||||||
|
|
||||||
|
if (Actor->Get<float>(MinNetUpdateFrequencyOffset) == 0.0f)
|
||||||
|
{
|
||||||
|
Actor->Get<float>(MinNetUpdateFrequencyOffset) = 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency(); // Don't go faster than NetUpdateFrequency
|
||||||
|
const float MaxOptimalDelta = max(1.0f / Actor->GetNetUpdateFrequency(), MinOptimalDelta); // Don't go slower than MinNetUpdateFrequency (or NetUpdateFrequency if it's slower)
|
||||||
|
|
||||||
|
const float Alpha = std::clamp((LastReplicateDelta - ScaleDownStartTime) / ScaleDownTimeRange, 0.0f, 1.0f); // should we use fmath?
|
||||||
|
ActorInfo->OptimalNetUpdateDelta = std::lerp(MinOptimalDelta, MaxOptimalDelta, Alpha); // should we use fmath?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ActorInfo->bPendingNetUpdate)
|
||||||
|
{
|
||||||
|
constexpr bool bUseAdapativeNetFrequency = false;
|
||||||
|
const float NextUpdateDelta = bUseAdapativeNetFrequency ? ActorInfo->OptimalNetUpdateDelta : 1.0f / Actor->GetNetUpdateFrequency();
|
||||||
|
|
||||||
|
// then set the next update time
|
||||||
|
float ServerTickTime = 1.f / 30;
|
||||||
|
ActorInfo->NextUpdateTime = TimeSeconds + FRand() * ServerTickTime + NextUpdateDelta;
|
||||||
|
static auto TimeOffset = GetOffset("Time");
|
||||||
|
ActorInfo->LastNetUpdateTime = Get<float>(TimeOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
ActorInfo->bPendingNetUpdate = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OutConsiderList.push_back(ActorInfo.Get());
|
||||||
|
|
||||||
|
static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication);
|
||||||
|
CallPreReplication(Actor, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USEOBJECTLIST
|
||||||
Actors.Free();
|
Actors.Free();
|
||||||
|
#else
|
||||||
|
for (auto Actor : ActorsToRemove)
|
||||||
|
{
|
||||||
|
if (!Actor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* LOG_INFO(LogDev, "Removing actor: {}", Actor ? Actor->GetFullName() : "InvalidObject");
|
||||||
|
RemoveNetworkActor(Actor);
|
||||||
|
LOG_INFO(LogDev, "Finished removing actor."); */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
using UChannel = UObject;
|
using UChannel = UObject;
|
||||||
@@ -272,16 +368,21 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
}
|
}
|
||||||
else */
|
else */
|
||||||
{
|
{
|
||||||
ServerTickTime = 1.f / ServerTickTime; // 0
|
ServerTickTime = 1.f / ServerTickTime;
|
||||||
// bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime;
|
// bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<FNetworkObjectInfo*> ConsiderList;
|
std::vector<FNetworkObjectInfo*> ConsiderList;
|
||||||
// ConsiderList.reserve(GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num());
|
|
||||||
|
#ifdef USEOBJECTLIST
|
||||||
|
ConsiderList.reserve(GetNetworkObjectList().ActiveNetworkObjects.Num());
|
||||||
|
#endif
|
||||||
|
|
||||||
// std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n';
|
// std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n';
|
||||||
|
|
||||||
ServerReplicateActors_BuildConsiderList(this, ConsiderList);
|
auto World = GetWorld();
|
||||||
|
|
||||||
|
ServerReplicateActors_BuildConsiderList(ConsiderList);
|
||||||
|
|
||||||
for (int32 i = 0; i < this->GetClientConnections().Num(); i++)
|
for (int32 i = 0; i < this->GetClientConnections().Num(); i++)
|
||||||
{
|
{
|
||||||
@@ -347,15 +448,35 @@ int32 UNetDriver::ServerReplicateActors()
|
|||||||
|
|
||||||
Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1);
|
||||||
|
|
||||||
if (Channel) {
|
if (Channel)
|
||||||
|
{
|
||||||
SetChannelActor(Channel, Actor);
|
SetChannelActor(Channel, Actor);
|
||||||
// Channel->Connection = Connection;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USEOBJECTLIST
|
||||||
|
if (Actor->GetNetUpdateFrequency() < 1.0f)
|
||||||
|
{
|
||||||
|
ActorInfo->NextUpdateTime = UGameplayStatics::GetTimeSeconds(GetWorld()) + 0.2f * FRand();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Channel)
|
if (Channel)
|
||||||
ReplicateActor(Channel);
|
{
|
||||||
|
if (ReplicateActor(Channel))
|
||||||
|
{
|
||||||
|
#ifdef USEOBJECTLIST
|
||||||
|
auto TimeSeconds = UGameplayStatics::GetTimeSeconds(World);
|
||||||
|
const float MinOptimalDelta = 1.0f / Actor->GetNetUpdateFrequency();
|
||||||
|
const float MaxOptimalDelta = max(1.0f / Actor->GetMinNetUpdateFrequency(), MinOptimalDelta);
|
||||||
|
const float DeltaBetweenReplications = (TimeSeconds - ActorInfo->LastNetReplicateTime);
|
||||||
|
|
||||||
|
// Choose an optimal time, we choose 70% of the actual rate to allow frequency to go up if needed
|
||||||
|
ActorInfo->OptimalNetUpdateDelta = std::clamp(DeltaBetweenReplications * 0.7f, MinOptimalDelta, MaxOptimalDelta); // should we use fmath?
|
||||||
|
ActorInfo->LastNetReplicateTime = TimeSeconds;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,71 @@
|
|||||||
#include "NetConnection.h"
|
#include "NetConnection.h"
|
||||||
#include "Array.h"
|
#include "Array.h"
|
||||||
|
|
||||||
|
#include "WeakObjectPtrTemplates.h"
|
||||||
|
#include "Map.h"
|
||||||
|
#include "SharedPointer.h"
|
||||||
|
#include "Level.h"
|
||||||
|
|
||||||
|
struct FActorDestructionInfo
|
||||||
|
{
|
||||||
|
TWeakObjectPtr<ULevel> Level;
|
||||||
|
TWeakObjectPtr<UObject> ObjOuter;
|
||||||
|
FVector DestroyedPosition;
|
||||||
|
int32 NetGUID;
|
||||||
|
FString PathName;
|
||||||
|
FName StreamingLevelName;
|
||||||
|
};
|
||||||
|
struct FNetworkObjectInfo
|
||||||
|
{
|
||||||
|
/** Pointer to the replicated actor. */
|
||||||
|
AActor* Actor;
|
||||||
|
|
||||||
|
/** WeakPtr to actor. This is cached here to prevent constantly constructing one when needed for (things like) keys in TMaps/TSets */
|
||||||
|
TWeakObjectPtr<AActor> WeakActor;
|
||||||
|
|
||||||
|
/** Next time to consider replicating the actor. Based on FPlatformTime::Seconds(). */
|
||||||
|
double NextUpdateTime;
|
||||||
|
|
||||||
|
/** Last absolute time in seconds since actor actually sent something during replication */
|
||||||
|
double LastNetReplicateTime;
|
||||||
|
|
||||||
|
/** Optimal delta between replication updates based on how frequently actor properties are actually changing */
|
||||||
|
float OptimalNetUpdateDelta;
|
||||||
|
|
||||||
|
/** Last time this actor was updated for replication via NextUpdateTime
|
||||||
|
* @warning: internal net driver time, not related to WorldSettings.TimeSeconds */
|
||||||
|
float LastNetUpdateTime;
|
||||||
|
|
||||||
|
/** Is this object still pending a full net update due to clients that weren't able to replicate the actor at the time of LastNetUpdateTime */
|
||||||
|
uint32 bPendingNetUpdate : 1;
|
||||||
|
|
||||||
|
/** Force this object to be considered relevant for at least one update */
|
||||||
|
uint32 bForceRelevantNextUpdate : 1;
|
||||||
|
|
||||||
|
/** List of connections that this actor is dormant on */
|
||||||
|
TSet<TWeakObjectPtr<UNetConnection>> DormantConnections;
|
||||||
|
|
||||||
|
/** A list of connections that this actor has recently been dormant on, but the actor doesn't have a channel open yet.
|
||||||
|
* These need to be differentiated from actors that the client doesn't know about, but there's no explicit list for just those actors.
|
||||||
|
* (this list will be very transient, with connections being moved off the DormantConnections list, onto this list, and then off once the actor has a channel again)
|
||||||
|
*/
|
||||||
|
TSet<TWeakObjectPtr<UNetConnection>> RecentlyDormantConnections;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FNetworkObjectList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef TSet<TSharedPtr<FNetworkObjectInfo>> FNetworkObjectSet;
|
||||||
|
|
||||||
|
FNetworkObjectSet AllNetworkObjects;
|
||||||
|
FNetworkObjectSet ActiveNetworkObjects;
|
||||||
|
FNetworkObjectSet ObjectsDormantOnAllConnections;
|
||||||
|
|
||||||
|
TMap<TWeakObjectPtr<UNetConnection>, int32> NumDormantObjectsPerConnection;
|
||||||
|
|
||||||
|
void Remove(AActor* const Actor);
|
||||||
|
};
|
||||||
|
|
||||||
class UWorld;
|
class UWorld;
|
||||||
|
|
||||||
struct FURL // idk where this actually goes
|
struct FURL // idk where this actually goes
|
||||||
@@ -37,7 +102,10 @@ public:
|
|||||||
return Get<TArray<UNetConnection*>>(ClientConnectionsOffset);
|
return Get<TArray<UNetConnection*>>(ClientConnectionsOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveNetworkActor(AActor* Actor);
|
||||||
bool InitListen(FNetworkNotify* InNotify, FURL& ListenURL, bool bReuseAddressAndPort, FString& Error) { return InitListenOriginal(this, InNotify, ListenURL, bReuseAddressAndPort, Error); }
|
bool InitListen(FNetworkNotify* InNotify, FURL& ListenURL, bool bReuseAddressAndPort, FString& Error) { return InitListenOriginal(this, InNotify, ListenURL, bReuseAddressAndPort, Error); }
|
||||||
void SetWorld(UWorld* World) { return SetWorldOriginal(this, World); }
|
void SetWorld(UWorld* World) { return SetWorldOriginal(this, World); }
|
||||||
int32 ServerReplicateActors();
|
int32 ServerReplicateActors();
|
||||||
|
void ServerReplicateActors_BuildConsiderList(std::vector<FNetworkObjectInfo*>& OutConsiderList);
|
||||||
|
FNetworkObjectList& GetNetworkObjectList();
|
||||||
};
|
};
|
||||||
107
Project Reboot 3.0/NetworkObjectList.cpp
Normal file
107
Project Reboot 3.0/NetworkObjectList.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "NetDriver.h"
|
||||||
|
|
||||||
|
void FNetworkObjectList::Remove(AActor* const Actor)
|
||||||
|
{
|
||||||
|
if (Actor == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TSharedPtr<FNetworkObjectInfo>* NetworkObjectInfoPtr = nullptr;
|
||||||
|
|
||||||
|
for (int i = 0; i < AllNetworkObjects.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& CurrentNetworkObject = AllNetworkObjects[i];
|
||||||
|
|
||||||
|
if (CurrentNetworkObject->Actor == Actor)
|
||||||
|
{
|
||||||
|
NetworkObjectInfoPtr = &CurrentNetworkObject;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NetworkObjectInfoPtr == nullptr)
|
||||||
|
{
|
||||||
|
// Sanity check that we're not on the other lists either
|
||||||
|
// check(!ActiveNetworkObjects.Contains(Actor));
|
||||||
|
// check(!ObjectsDormantOnAllConnections.Contains(Actor));
|
||||||
|
// check((ActiveNetworkObjects.Num() + ObjectsDormantOnAllConnections.Num()) == AllNetworkObjects.Num());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FNetworkObjectInfo* NetworkObjectInfo = NetworkObjectInfoPtr->Get();
|
||||||
|
|
||||||
|
for (int i = 0; i < NetworkObjectInfo->DormantConnections.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& ConnectionIt = NetworkObjectInfo->DormantConnections[i];
|
||||||
|
|
||||||
|
UNetConnection* Connection = ConnectionIt.Get();
|
||||||
|
|
||||||
|
if (Connection == nullptr) // || Connection->State == USOCK_Closed)
|
||||||
|
{
|
||||||
|
NetworkObjectInfo->DormantConnections.Remove(i);
|
||||||
|
// ConnectionIt.RemoveCurrent();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32* NumDormantObjectsPerConnectionRef = nullptr;
|
||||||
|
|
||||||
|
for (int z = 0; z < NumDormantObjectsPerConnection.Pairs.Num(); z++)
|
||||||
|
{
|
||||||
|
auto& Pair = NumDormantObjectsPerConnection.Pairs[z];
|
||||||
|
|
||||||
|
if (Pair.First.ObjectIndex == Connection->InternalIndex)
|
||||||
|
{
|
||||||
|
NumDormantObjectsPerConnectionRef = &Pair.Second;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NumDormantObjectsPerConnectionRef)
|
||||||
|
{
|
||||||
|
// We should add here TODO MILXNOR
|
||||||
|
}
|
||||||
|
|
||||||
|
// check(NumDormantObjectsPerConnectionRef > 0);
|
||||||
|
|
||||||
|
if (NumDormantObjectsPerConnectionRef)
|
||||||
|
(*NumDormantObjectsPerConnectionRef)--;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove this object from all lists
|
||||||
|
|
||||||
|
for (int i = 0; i < AllNetworkObjects.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& CurrentNetworkObject = AllNetworkObjects[i];
|
||||||
|
|
||||||
|
if (CurrentNetworkObject->Actor == Actor)
|
||||||
|
{
|
||||||
|
AllNetworkObjects.Remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ActiveNetworkObjects.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& CurrentActiveNetworkObject = ActiveNetworkObjects[i];
|
||||||
|
|
||||||
|
if (CurrentActiveNetworkObject->Actor == Actor)
|
||||||
|
{
|
||||||
|
ActiveNetworkObjects.Remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < ObjectsDormantOnAllConnections.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& CurrentDormantObject = ObjectsDormantOnAllConnections[i];
|
||||||
|
|
||||||
|
if (CurrentDormantObject->Actor == Actor)
|
||||||
|
{
|
||||||
|
ObjectsDormantOnAllConnections.Remove(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check((ActiveNetworkObjects.Num() + ObjectsDormantOnAllConnections.Num()) == AllNetworkObjects.Num());
|
||||||
|
}
|
||||||
@@ -132,4 +132,9 @@ bool UObject::IsValidLowLevel()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ChunkedObjects ? ChunkedObjects->IsValid(this) : UnchunkedObjects ? UnchunkedObjects->IsValid(this) : false;
|
return ChunkedObjects ? ChunkedObjects->IsValid(this) : UnchunkedObjects ? UnchunkedObjects->IsValid(this) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE bool UObject::IsPendingKill() const
|
||||||
|
{
|
||||||
|
return ChunkedObjects ? ChunkedObjects->GetItemByIndex(InternalIndex)->IsPendingKill() : UnchunkedObjects ? UnchunkedObjects->GetItemByIndex(InternalIndex)->IsPendingKill() : false;
|
||||||
}
|
}
|
||||||
@@ -90,6 +90,25 @@ public:
|
|||||||
|
|
||||||
void AddToRoot();
|
void AddToRoot();
|
||||||
bool IsValidLowLevel();
|
bool IsValidLowLevel();
|
||||||
|
FORCEINLINE bool IsPendingKill() const;
|
||||||
|
|
||||||
// static class UClass* StaticClass();
|
// static class UClass* StaticClass();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* struct FInternalUObjectBaseUtilityIsValidFlagsChecker
|
||||||
|
{
|
||||||
|
FORCEINLINE static bool CheckObjectValidBasedOnItsFlags(const UObject* Test)
|
||||||
|
{
|
||||||
|
// Here we don't really check if the flags match but if the end result is the same
|
||||||
|
checkSlow(GUObjectArray.IndexToObject(Test->InternalIndex)->HasAnyFlags(EInternalObjectFlags::PendingKill | EInternalObjectFlags::Garbage) == Test->HasAnyFlags(RF_InternalPendingKill | RF_InternalGarbage));
|
||||||
|
return !Test->HasAnyFlags(RF_InternalPendingKill | RF_InternalGarbage);
|
||||||
|
}
|
||||||
|
}; */
|
||||||
|
|
||||||
|
FORCEINLINE bool IsValidChecked(const UObject* Test)
|
||||||
|
{
|
||||||
|
// if (!Test)
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
return true; // FInternalUObjectBaseUtilityIsValidFlagsChecker::CheckObjectValidBasedOnItsFlags(Test);
|
||||||
|
}
|
||||||
@@ -50,6 +50,7 @@ enum class EInternalObjectFlags : int
|
|||||||
AsyncLoading = 1 << 27, ///< Object is being asynchronously loaded.
|
AsyncLoading = 1 << 27, ///< Object is being asynchronously loaded.
|
||||||
Unreachable = 1 << 28, ///< Object is not reachable on the object graph.
|
Unreachable = 1 << 28, ///< Object is not reachable on the object graph.
|
||||||
// PendingKill UE_DEPRECATED(5.0, "PendingKill flag should no longer be used. Use Garbage flag instead.") = 1 << 29, ///< Objects that are pending destruction (invalid for gameplay but valid objects). This flag is mirrored in EObjectFlags as RF_PendingKill for performance
|
// PendingKill UE_DEPRECATED(5.0, "PendingKill flag should no longer be used. Use Garbage flag instead.") = 1 << 29, ///< Objects that are pending destruction (invalid for gameplay but valid objects). This flag is mirrored in EObjectFlags as RF_PendingKill for performance
|
||||||
|
PendingKill = 1 << 29,
|
||||||
RootSet = 1 << 30, ///< Object will not be garbage collected, even if unreferenced.
|
RootSet = 1 << 30, ///< Object will not be garbage collected, even if unreferenced.
|
||||||
PendingConstruction = 1 << 31 ///< Object didn't have its class constructor called yet (only the UObjectBase one to initialize its most basic members)
|
PendingConstruction = 1 << 31 ///< Object didn't have its class constructor called yet (only the UObjectBase one to initialize its most basic members)
|
||||||
|
|
||||||
|
|||||||
@@ -209,10 +209,12 @@
|
|||||||
<ClCompile Include="InventoryManagementLibrary.cpp" />
|
<ClCompile Include="InventoryManagementLibrary.cpp" />
|
||||||
<ClCompile Include="KismetMathLibrary.cpp" />
|
<ClCompile Include="KismetMathLibrary.cpp" />
|
||||||
<ClCompile Include="KismetStringLibrary.cpp" />
|
<ClCompile Include="KismetStringLibrary.cpp" />
|
||||||
|
<ClCompile Include="Level.cpp" />
|
||||||
<ClCompile Include="LevelActor.cpp" />
|
<ClCompile Include="LevelActor.cpp" />
|
||||||
<ClCompile Include="NameTypes.cpp" />
|
<ClCompile Include="NameTypes.cpp" />
|
||||||
<ClCompile Include="NetConnection.h" />
|
<ClCompile Include="NetConnection.h" />
|
||||||
<ClCompile Include="NetDriver.cpp" />
|
<ClCompile Include="NetDriver.cpp" />
|
||||||
|
<ClCompile Include="NetworkObjectList.cpp" />
|
||||||
<ClCompile Include="Object.cpp" />
|
<ClCompile Include="Object.cpp" />
|
||||||
<ClCompile Include="PlayerController.cpp" />
|
<ClCompile Include="PlayerController.cpp" />
|
||||||
<ClCompile Include="PlayerState.cpp" />
|
<ClCompile Include="PlayerState.cpp" />
|
||||||
@@ -295,6 +297,7 @@
|
|||||||
<ClInclude Include="KismetMathLibrary.h" />
|
<ClInclude Include="KismetMathLibrary.h" />
|
||||||
<ClInclude Include="KismetStringLibrary.h" />
|
<ClInclude Include="KismetStringLibrary.h" />
|
||||||
<ClInclude Include="KismetSystemLibrary.h" />
|
<ClInclude Include="KismetSystemLibrary.h" />
|
||||||
|
<ClInclude Include="Level.h" />
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
<ClInclude Include="Map.h" />
|
<ClInclude Include="Map.h" />
|
||||||
<ClInclude Include="MegaStormManager.h" />
|
<ClInclude Include="MegaStormManager.h" />
|
||||||
@@ -315,6 +318,7 @@
|
|||||||
<ClInclude Include="Rotator.h" />
|
<ClInclude Include="Rotator.h" />
|
||||||
<ClInclude Include="ScriptInterface.h" />
|
<ClInclude Include="ScriptInterface.h" />
|
||||||
<ClInclude Include="Set.h" />
|
<ClInclude Include="Set.h" />
|
||||||
|
<ClInclude Include="SharedPointer.h" />
|
||||||
<ClInclude Include="SoftObjectPath.h" />
|
<ClInclude Include="SoftObjectPath.h" />
|
||||||
<ClInclude Include="SoftObjectPtr.h" />
|
<ClInclude Include="SoftObjectPtr.h" />
|
||||||
<ClInclude Include="SparseArray.h" />
|
<ClInclude Include="SparseArray.h" />
|
||||||
@@ -328,6 +332,7 @@
|
|||||||
<ClInclude Include="Vector.h" />
|
<ClInclude Include="Vector.h" />
|
||||||
<ClInclude Include="vehicles.h" />
|
<ClInclude Include="vehicles.h" />
|
||||||
<ClInclude Include="WeakObjectPtr.h" />
|
<ClInclude Include="WeakObjectPtr.h" />
|
||||||
|
<ClInclude Include="WeakObjectPtrTemplates.h" />
|
||||||
<ClInclude Include="World.h" />
|
<ClInclude Include="World.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -167,6 +167,12 @@
|
|||||||
<ClCompile Include="FortPlayerStateAthena.cpp">
|
<ClCompile Include="FortPlayerStateAthena.cpp">
|
||||||
<Filter>FortniteGame\Source\FortniteGame\Private\Player</Filter>
|
<Filter>FortniteGame\Source\FortniteGame\Private\Player</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Level.cpp">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="NetworkObjectList.cpp">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
@@ -482,6 +488,15 @@
|
|||||||
<ClInclude Include="FortQuickBars.h">
|
<ClInclude Include="FortQuickBars.h">
|
||||||
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
|
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="WeakObjectPtrTemplates.h">
|
||||||
|
<Filter>Engine\Source\Runtime\CoreUObject\Public\UObject</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SharedPointer.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Level.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Engine\Classes\Engine</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Engine">
|
<Filter Include="Engine">
|
||||||
@@ -628,9 +643,6 @@
|
|||||||
<Filter Include="Engine\Source\Runtime\GameplayTags\Classes">
|
<Filter Include="Engine\Source\Runtime\GameplayTags\Classes">
|
||||||
<UniqueIdentifier>{247d4c62-23f7-4964-8879-5a0d65c44a73}</UniqueIdentifier>
|
<UniqueIdentifier>{247d4c62-23f7-4964-8879-5a0d65c44a73}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="Engine\Source\Runtime\Core\Public\Templates">
|
|
||||||
<UniqueIdentifier>{31a7f342-8b7c-4594-a24d-c4dd5c9d230d}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
<Filter Include="FortniteGame\Source\FortniteGame\Public\Weapons">
|
<Filter Include="FortniteGame\Source\FortniteGame\Public\Weapons">
|
||||||
<UniqueIdentifier>{bcb0d983-0b85-4ca6-9fac-6567c7d79921}</UniqueIdentifier>
|
<UniqueIdentifier>{bcb0d983-0b85-4ca6-9fac-6567c7d79921}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
@@ -667,6 +679,9 @@
|
|||||||
<Filter Include="Engine\Source\Runtime\CoreUObject\Public\Misc">
|
<Filter Include="Engine\Source\Runtime\CoreUObject\Public\Misc">
|
||||||
<UniqueIdentifier>{915f7622-6003-445e-a43f-04d5c7e13b49}</UniqueIdentifier>
|
<UniqueIdentifier>{915f7622-6003-445e-a43f-04d5c7e13b49}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Engine\Source\Runtime\Core\Public\Templates">
|
||||||
|
<UniqueIdentifier>{31a7f342-8b7c-4594-a24d-c4dd5c9d230d}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="UnrealEngine.cpp">
|
<None Include="UnrealEngine.cpp">
|
||||||
|
|||||||
@@ -32,7 +32,173 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename InElementType> //, typename KeyFuncs, typename Allocator>
|
template <typename SetType>
|
||||||
|
class TSet
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
friend TSparseArray;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef TSetElement<SetType> ElementType;
|
||||||
|
typedef TSparseArrayElementOrListLink<ElementType> ArrayElementType;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TSparseArray<ElementType> Elements;
|
||||||
|
|
||||||
|
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
||||||
|
mutable int32 HashSize;
|
||||||
|
|
||||||
|
public:
|
||||||
|
class FBaseIterator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
TSet<SetType>& IteratedSet;
|
||||||
|
TSparseArray<ElementType>::FBaseIterator ElementIt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE FBaseIterator(const TSet<SetType>& InSet, TSparseArray<TSetElement<SetType>>::FBaseIterator InElementIt)
|
||||||
|
: IteratedSet(const_cast<TSet<SetType>&>(InSet))
|
||||||
|
, ElementIt(InElementIt)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
|
{
|
||||||
|
return (bool)ElementIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE TSet<SetType>::FBaseIterator& operator++()
|
||||||
|
{
|
||||||
|
++ElementIt;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator==(const TSet<SetType>::FBaseIterator& OtherIt) const
|
||||||
|
{
|
||||||
|
return ElementIt == OtherIt.ElementIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator!=(const TSet<SetType>::FBaseIterator& OtherIt) const
|
||||||
|
{
|
||||||
|
return ElementIt != OtherIt.ElementIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE TSet<SetType>::FBaseIterator& operator=(TSet<SetType>::FBaseIterator& OtherIt)
|
||||||
|
{
|
||||||
|
return ElementIt = OtherIt.ElementIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE SetType& operator*()
|
||||||
|
{
|
||||||
|
return (*ElementIt).Value;
|
||||||
|
}
|
||||||
|
FORCEINLINE const SetType& operator*() const
|
||||||
|
{
|
||||||
|
return &((*ElementIt).Value);
|
||||||
|
}
|
||||||
|
FORCEINLINE SetType* operator->()
|
||||||
|
{
|
||||||
|
return &((*ElementIt).Value);
|
||||||
|
}
|
||||||
|
FORCEINLINE const SetType* operator->() const
|
||||||
|
{
|
||||||
|
return &(*ElementIt).Value;
|
||||||
|
}
|
||||||
|
FORCEINLINE const int32 GetIndex() const
|
||||||
|
{
|
||||||
|
return ElementIt.GetIndex();
|
||||||
|
}
|
||||||
|
FORCEINLINE ElementType& GetSetElement()
|
||||||
|
{
|
||||||
|
return *ElementIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE const ElementType& GetSetElement() const
|
||||||
|
{
|
||||||
|
return *ElementIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool IsElementValid() const
|
||||||
|
{
|
||||||
|
return ElementIt.IsElementValid();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE TSet<SetType>::FBaseIterator begin()
|
||||||
|
{
|
||||||
|
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
|
||||||
|
}
|
||||||
|
FORCEINLINE const TSet<SetType>::FBaseIterator begin() const
|
||||||
|
{
|
||||||
|
return TSet<SetType>::FBaseIterator(*this, Elements.begin());
|
||||||
|
}
|
||||||
|
FORCEINLINE TSet<SetType>::FBaseIterator end()
|
||||||
|
{
|
||||||
|
return TSet<SetType>::FBaseIterator(*this, Elements.end());
|
||||||
|
}
|
||||||
|
FORCEINLINE const TSet<SetType>::FBaseIterator end() const
|
||||||
|
{
|
||||||
|
return TSet<SetType>::FBaseIterator(*this, Elements.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE SetType& operator[](int Index)
|
||||||
|
{
|
||||||
|
return Elements[Index].ElementData.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 Num() const
|
||||||
|
{
|
||||||
|
return Elements.Num();
|
||||||
|
}
|
||||||
|
FORCEINLINE bool IsValid() const
|
||||||
|
{
|
||||||
|
return Elements.Data.Data != nullptr && Elements.AllocationFlags.MaxBits > 0;
|
||||||
|
}
|
||||||
|
FORCEINLINE TSparseArray<ElementType>& GetElements()
|
||||||
|
{
|
||||||
|
return Elements;
|
||||||
|
}
|
||||||
|
FORCEINLINE const TSparseArray<ElementType>& GetElements() const
|
||||||
|
{
|
||||||
|
return Elements;
|
||||||
|
}
|
||||||
|
FORCEINLINE const TBitArray& GetAllocationFlags() const
|
||||||
|
{
|
||||||
|
return Elements.GetAllocationFlags();
|
||||||
|
}
|
||||||
|
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
||||||
|
{
|
||||||
|
return Elements.IsIndexValid(IndexToCheck);
|
||||||
|
}
|
||||||
|
FORCEINLINE const bool Contains(const SetType& ElementToLookFor) const
|
||||||
|
{
|
||||||
|
if (Num() <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (SetType Element : *this)
|
||||||
|
{
|
||||||
|
if (Element == ElementToLookFor)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
FORCEINLINE const int32 Find(const SetType& ElementToLookFor) const
|
||||||
|
{
|
||||||
|
for (auto It = this->begin(); It != this->end(); ++It)
|
||||||
|
{
|
||||||
|
if (*It == ElementToLookFor)
|
||||||
|
{
|
||||||
|
return It.GetIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool Remove(const SetType& ElementToRemove)
|
||||||
|
{
|
||||||
|
return Elements.RemoveAt(Find(ElementToRemove));
|
||||||
|
}
|
||||||
|
FORCEINLINE bool Remove(int Index)
|
||||||
|
{
|
||||||
|
return Elements.RemoveAt(Index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* template<typename InElementType> //, typename KeyFuncs, typename Allocator>
|
||||||
class TSet
|
class TSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -43,4 +209,4 @@ public:
|
|||||||
|
|
||||||
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
mutable TInlineAllocator<1>::ForElementType<int> Hash;
|
||||||
mutable int32 HashSize;
|
mutable int32 HashSize;
|
||||||
};
|
}; */
|
||||||
36
Project Reboot 3.0/SharedPointer.h
Normal file
36
Project Reboot 3.0/SharedPointer.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
template< class ObjectType>
|
||||||
|
class TSharedPtr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ObjectType* Object;
|
||||||
|
|
||||||
|
int32 SharedReferenceCount;
|
||||||
|
int32 WeakReferenceCount;
|
||||||
|
|
||||||
|
FORCEINLINE ObjectType* Get()
|
||||||
|
{
|
||||||
|
return Object;
|
||||||
|
}
|
||||||
|
FORCEINLINE ObjectType* Get() const
|
||||||
|
{
|
||||||
|
return Object;
|
||||||
|
}
|
||||||
|
FORCEINLINE ObjectType& operator*()
|
||||||
|
{
|
||||||
|
return *Object;
|
||||||
|
}
|
||||||
|
FORCEINLINE const ObjectType& operator*() const
|
||||||
|
{
|
||||||
|
return *Object;
|
||||||
|
}
|
||||||
|
FORCEINLINE ObjectType* operator->()
|
||||||
|
{
|
||||||
|
return Object;
|
||||||
|
}
|
||||||
|
FORCEINLINE ObjectType* operator->() const
|
||||||
|
{
|
||||||
|
return Object;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -50,6 +50,86 @@ public:
|
|||||||
int32 FirstFreeIndex;
|
int32 FirstFreeIndex;
|
||||||
int32 NumFreeIndices;
|
int32 NumFreeIndices;
|
||||||
|
|
||||||
|
FORCEINLINE int32 Num() const
|
||||||
|
{
|
||||||
|
return Data.Num() - NumFreeIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FBaseIterator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
TSparseArray<ArrayType>& IteratedArray;
|
||||||
|
TBitArray::FSetBitIterator BitArrayIt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE FBaseIterator(const TSparseArray<ArrayType>& Array, const TBitArray::FSetBitIterator BitIterator)
|
||||||
|
: IteratedArray(const_cast<TSparseArray<ArrayType>&>(Array))
|
||||||
|
, BitArrayIt(const_cast<TBitArray::FSetBitIterator&>(BitIterator))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE explicit operator bool() const
|
||||||
|
{
|
||||||
|
return (bool)BitArrayIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator& operator++()
|
||||||
|
{
|
||||||
|
++BitArrayIt;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FORCEINLINE ArrayType& operator*()
|
||||||
|
{
|
||||||
|
return IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
||||||
|
}
|
||||||
|
FORCEINLINE const ArrayType& operator*() const
|
||||||
|
{
|
||||||
|
return IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
||||||
|
}
|
||||||
|
FORCEINLINE ArrayType* operator->()
|
||||||
|
{
|
||||||
|
return &IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
||||||
|
}
|
||||||
|
FORCEINLINE const ArrayType* operator->() const
|
||||||
|
{
|
||||||
|
return &IteratedArray[BitArrayIt.GetIndex()].ElementData;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator==(const TSparseArray<ArrayType>::FBaseIterator& Other) const
|
||||||
|
{
|
||||||
|
return BitArrayIt == Other.BitArrayIt;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool operator!=(const TSparseArray<ArrayType>::FBaseIterator& Other) const
|
||||||
|
{
|
||||||
|
return BitArrayIt != Other.BitArrayIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE int32 GetIndex() const
|
||||||
|
{
|
||||||
|
return BitArrayIt.GetIndex();
|
||||||
|
}
|
||||||
|
FORCEINLINE bool IsElementValid() const
|
||||||
|
{
|
||||||
|
return *BitArrayIt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator begin()
|
||||||
|
{
|
||||||
|
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags, 0));
|
||||||
|
}
|
||||||
|
FORCEINLINE const TSparseArray<ArrayType>::FBaseIterator begin() const
|
||||||
|
{
|
||||||
|
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags, 0));
|
||||||
|
}
|
||||||
|
FORCEINLINE TSparseArray<ArrayType>::FBaseIterator end()
|
||||||
|
{
|
||||||
|
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags));
|
||||||
|
}
|
||||||
|
FORCEINLINE const TSparseArray<ArrayType>::FBaseIterator end() const
|
||||||
|
{
|
||||||
|
return TSparseArray<ArrayType>::FBaseIterator(*this, TBitArray::FSetBitIterator(AllocationFlags));
|
||||||
|
}
|
||||||
|
|
||||||
FORCEINLINE FSparseArrayElement& operator[](uint32 Index)
|
FORCEINLINE FSparseArrayElement& operator[](uint32 Index)
|
||||||
{
|
{
|
||||||
return *(FSparseArrayElement*)&Data.at(Index).ElementData;
|
return *(FSparseArrayElement*)&Data.at(Index).ElementData;
|
||||||
@@ -58,9 +138,62 @@ public:
|
|||||||
{
|
{
|
||||||
return *(const FSparseArrayElement*)&Data.at(Index).ElementData;
|
return *(const FSparseArrayElement*)&Data.at(Index).ElementData;
|
||||||
}
|
}
|
||||||
|
FORCEINLINE int32 GetNumFreeIndices() const
|
||||||
FORCEINLINE int32 Num() const
|
|
||||||
{
|
{
|
||||||
return Data.Num() - NumFreeIndices;
|
return NumFreeIndices;
|
||||||
|
}
|
||||||
|
FORCEINLINE int32 GetFirstFreeIndex() const
|
||||||
|
{
|
||||||
|
return FirstFreeIndex;
|
||||||
|
}
|
||||||
|
FORCEINLINE const TArray<FSparseArrayElement>& GetData() const
|
||||||
|
{
|
||||||
|
return Data;
|
||||||
|
}
|
||||||
|
FORCEINLINE const TBitArray& GetAllocationFlags() const
|
||||||
|
{
|
||||||
|
return AllocationFlags;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool IsIndexValid(int32 IndexToCheck) const
|
||||||
|
{
|
||||||
|
return AllocationFlags.IsSet(IndexToCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE bool RemoveAt(const int32 IndexToRemove)
|
||||||
|
{
|
||||||
|
if (IndexToRemove >= 0 && IndexToRemove < Data.Num() && AllocationFlags.IsSet(IndexToRemove))
|
||||||
|
{
|
||||||
|
int32 PreviousFreeIndex = -1;
|
||||||
|
int32 NextFreeIndex = -1;
|
||||||
|
|
||||||
|
if (NumFreeIndices == 0)
|
||||||
|
{
|
||||||
|
FirstFreeIndex = IndexToRemove;
|
||||||
|
Data.at(IndexToRemove) = { -1, -1 };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto It = AllocationFlags.begin(); It != AllocationFlags.end(); ++It)
|
||||||
|
{
|
||||||
|
if (!It)
|
||||||
|
{
|
||||||
|
if (It.GetIndex() < IndexToRemove)
|
||||||
|
{
|
||||||
|
Data.at(IndexToRemove).PrevFreeIndex = It.GetIndex();
|
||||||
|
}
|
||||||
|
else if (It.GetIndex() > IndexToRemove)
|
||||||
|
{
|
||||||
|
Data.at(IndexToRemove).NextFreeIndex = It.GetIndex();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AllocationFlags.Set(IndexToRemove, false);
|
||||||
|
NumFreeIndices++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -12,6 +12,11 @@ struct FUObjectItem
|
|||||||
int32 ClusterRootIndex;
|
int32 ClusterRootIndex;
|
||||||
int32 SerialNumber;
|
int32 SerialNumber;
|
||||||
|
|
||||||
|
FORCEINLINE bool IsPendingKill() const
|
||||||
|
{
|
||||||
|
return !!(Flags & int32(EInternalObjectFlags::PendingKill));
|
||||||
|
}
|
||||||
|
|
||||||
FORCEINLINE void SetFlag(EInternalObjectFlags FlagToSet)
|
FORCEINLINE void SetFlag(EInternalObjectFlags FlagToSet)
|
||||||
{
|
{
|
||||||
// static_assert(sizeof(int32) == sizeof(Flags), "Flags must be 32-bit for atomics.");
|
// static_assert(sizeof(int32) == sizeof(Flags), "Flags must be 32-bit for atomics.");
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "UObjectArray.h"
|
||||||
|
|
||||||
struct FWeakObjectPtr
|
struct FWeakObjectPtr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int ObjectIndex;
|
int ObjectIndex;
|
||||||
int ObjectSerialNumber;
|
int ObjectSerialNumber;
|
||||||
|
|
||||||
|
UObject* Get()
|
||||||
|
{
|
||||||
|
return ChunkedObjects ? ChunkedObjects->GetObjectByIndex(ObjectIndex) : UnchunkedObjects ? UnchunkedObjects->GetObjectByIndex(ObjectIndex) : nullptr;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
16
Project Reboot 3.0/WeakObjectPtrTemplates.h
Normal file
16
Project Reboot 3.0/WeakObjectPtrTemplates.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "WeakObjectPtr.h"
|
||||||
|
#include "Object.h"
|
||||||
|
|
||||||
|
template<class T = UObject, class TWeakObjectPtrBase = FWeakObjectPtr>
|
||||||
|
struct TWeakObjectPtr;
|
||||||
|
|
||||||
|
template<class T, class TWeakObjectPtrBase>
|
||||||
|
struct TWeakObjectPtr : public TWeakObjectPtrBase
|
||||||
|
{
|
||||||
|
T* Get()
|
||||||
|
{
|
||||||
|
return (T*)TWeakObjectPtrBase::Get();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -395,7 +395,7 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
|
|||||||
if (Fortnite_Version > 2.5 && Engine_Version == 420)
|
if (Fortnite_Version > 2.5 && Engine_Version == 420)
|
||||||
{
|
{
|
||||||
toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 57 48 81 EC ? ? ? ? 4C 8B 82 ? ? ? ? 48 8B F9 0F 29 70 E8 0F 29 78 D8").Get()); // Pawn Overlap
|
toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 57 48 81 EC ? ? ? ? 4C 8B 82 ? ? ? ? 48 8B F9 0F 29 70 E8 0F 29 78 D8").Get()); // Pawn Overlap
|
||||||
toNull.push_back(Memcury::Scanner::FindPattern("E8 ? ? ? ? EB 26 40 38 3D ? ? ? ?").RelativeOffset(1).Get()); // collectgarbage
|
// toNull.push_back(Memcury::Scanner::FindPattern("E8 ? ? ? ? EB 26 40 38 3D ? ? ? ?").RelativeOffset(1).Get()); // collectgarbage
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Engine_Version == 421)
|
if (Engine_Version == 421)
|
||||||
|
|||||||
@@ -61,6 +61,34 @@ static __int64 DispatchRequestHook(__int64 a1, __int64* a2, int a3)
|
|||||||
return DispatchRequestOriginal(a1, a2, 3);
|
return DispatchRequestOriginal(a1, a2, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void (*ApplyHomebaseEffectsOnPlayerSetupOriginal)(
|
||||||
|
__int64* GameState,
|
||||||
|
__int64 a2,
|
||||||
|
__int64 a3,
|
||||||
|
__int64 a4,
|
||||||
|
UObject* Hero,
|
||||||
|
char a6,
|
||||||
|
unsigned __int8 a7);
|
||||||
|
|
||||||
|
void __fastcall ApplyHomebaseEffectsOnPlayerSetupHook(
|
||||||
|
__int64* GameState,
|
||||||
|
__int64 a2,
|
||||||
|
__int64 a3,
|
||||||
|
__int64 a4,
|
||||||
|
UObject* Hero,
|
||||||
|
char a6,
|
||||||
|
unsigned __int8 a7)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "Old hero: {}", Hero ? Hero->GetFullName() : "InvalidObject");
|
||||||
|
|
||||||
|
auto HeroType = FindObject<UFortItemDefinition>("/Game/Athena/Heroes/HID_030_Athena_Commando_M_Halloween.HID_030_Athena_Commando_M_Halloween");
|
||||||
|
|
||||||
|
static auto ItemDefinitionOffset = Hero->GetOffset("ItemDefinition");
|
||||||
|
Hero->Get<UFortItemDefinition*>(ItemDefinitionOffset) = HeroType;
|
||||||
|
|
||||||
|
return ApplyHomebaseEffectsOnPlayerSetupOriginal(GameState, a2, a3, a4, Hero, a6, a7);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD WINAPI Main(LPVOID)
|
DWORD WINAPI Main(LPVOID)
|
||||||
{
|
{
|
||||||
InitLogger();
|
InitLogger();
|
||||||
@@ -213,6 +241,8 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
if (func == 0)
|
if (func == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
LOG_INFO(LogDev, "Nulling 0x{:x}", func - __int64(GetModuleHandleW(0)));
|
||||||
|
|
||||||
DWORD dwProtection;
|
DWORD dwProtection;
|
||||||
VirtualProtect((PVOID)func, 1, PAGE_EXECUTE_READWRITE, &dwProtection);
|
VirtualProtect((PVOID)func, 1, PAGE_EXECUTE_READWRITE, &dwProtection);
|
||||||
|
|
||||||
@@ -228,11 +258,16 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
// Globals::bAbilitiesEnabled = Engine_Version < 500;
|
// Globals::bAbilitiesEnabled = Engine_Version < 500;
|
||||||
|
|
||||||
|
if (Fortnite_Version == 1.11)
|
||||||
|
{
|
||||||
|
auto ApplyHomebaseEffectsOnPlayerSetupAddr = Memcury::Scanner::FindPattern("40 55 53 57 41 54 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 00 4C 8B BD ? ? ? ? 49").Get();
|
||||||
|
|
||||||
|
Hooking::MinHook::Hook((PVOID)ApplyHomebaseEffectsOnPlayerSetupAddr, ApplyHomebaseEffectsOnPlayerSetupHook, (PVOID*)&ApplyHomebaseEffectsOnPlayerSetupOriginal);
|
||||||
|
}
|
||||||
|
|
||||||
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameMode.ReadyToStartMatch"), AFortGameModeAthena::Athena_ReadyToStartMatchHook,
|
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameMode.ReadyToStartMatch"), AFortGameModeAthena::Athena_ReadyToStartMatchHook,
|
||||||
(PVOID*)&AFortGameModeAthena::Athena_ReadyToStartMatchOriginal, false);
|
(PVOID*)&AFortGameModeAthena::Athena_ReadyToStartMatchOriginal, false);
|
||||||
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.SpawnDefaultPawnFor"),
|
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.SpawnDefaultPawnFor"),
|
||||||
AGameModeBase::SpawnDefaultPawnForHook, nullptr, false);
|
AGameModeBase::SpawnDefaultPawnForHook, nullptr, false);
|
||||||
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.HandleStartingNewPlayer"), AFortGameModeAthena::Athena_HandleStartingNewPlayerHook,
|
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.HandleStartingNewPlayer"), AFortGameModeAthena::Athena_HandleStartingNewPlayerHook,
|
||||||
@@ -576,6 +611,56 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
else if (GetAsyncKeyState(VK_F8) & 1)
|
else if (GetAsyncKeyState(VK_F8) & 1)
|
||||||
{
|
{
|
||||||
|
auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode();
|
||||||
|
auto GameState = GameMode->GetGameState();
|
||||||
|
|
||||||
|
if (Fortnite_Version == 1.11)
|
||||||
|
{
|
||||||
|
static auto OverrideBattleBusSkin = FindObject("/Game/Athena/Items/Cosmetics/BattleBuses/BBID_WinterBus.BBID_WinterBus");
|
||||||
|
LOG_INFO(LogDev, "OverrideBattleBusSkin: {}", __int64(OverrideBattleBusSkin));
|
||||||
|
|
||||||
|
if (OverrideBattleBusSkin)
|
||||||
|
{
|
||||||
|
static auto AssetManagerOffset = GetEngine()->GetOffset("AssetManager");
|
||||||
|
auto AssetManager = GetEngine()->Get(AssetManagerOffset);
|
||||||
|
|
||||||
|
if (AssetManager)
|
||||||
|
{
|
||||||
|
static auto AthenaGameDataOffset = AssetManager->GetOffset("AthenaGameData");
|
||||||
|
auto AthenaGameData = AssetManager->Get(AthenaGameDataOffset);
|
||||||
|
|
||||||
|
if (AthenaGameData)
|
||||||
|
{
|
||||||
|
static auto DefaultBattleBusSkinOffset = AthenaGameData->GetOffset("DefaultBattleBusSkin");
|
||||||
|
AthenaGameData->Get(DefaultBattleBusSkinOffset) = OverrideBattleBusSkin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto DefaultBattleBusOffset = GameState->GetOffset("DefaultBattleBus");
|
||||||
|
GameState->Get(DefaultBattleBusOffset) = OverrideBattleBusSkin;
|
||||||
|
|
||||||
|
static auto FortAthenaAircraftClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaAircraft");
|
||||||
|
auto AllAircrafts = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaAircraftClass);
|
||||||
|
|
||||||
|
for (int i = 0; i < AllAircrafts.Num(); i++)
|
||||||
|
{
|
||||||
|
auto Aircraft = AllAircrafts.at(i);
|
||||||
|
|
||||||
|
static auto DefaultBusSkinOffset = Aircraft->GetOffset("DefaultBusSkin");
|
||||||
|
Aircraft->Get(DefaultBusSkinOffset) = OverrideBattleBusSkin;
|
||||||
|
|
||||||
|
static auto SpawnedCosmeticActorOffset = Aircraft->GetOffset("SpawnedCosmeticActor");
|
||||||
|
auto SpawnedCosmeticActor = Aircraft->Get<AActor*>(SpawnedCosmeticActorOffset);
|
||||||
|
|
||||||
|
if (SpawnedCosmeticActor)
|
||||||
|
{
|
||||||
|
static auto ActiveSkinOffset = SpawnedCosmeticActor->GetOffset("ActiveSkin");
|
||||||
|
SpawnedCosmeticActor->Get(ActiveSkinOffset) = OverrideBattleBusSkin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float Duration = 0;
|
float Duration = 0;
|
||||||
float EarlyDuration = Duration;
|
float EarlyDuration = Duration;
|
||||||
|
|
||||||
@@ -583,9 +668,6 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
LOG_INFO(LogDev, "Starting bus!");
|
LOG_INFO(LogDev, "Starting bus!");
|
||||||
|
|
||||||
auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode();
|
|
||||||
auto GameState = GameMode->GetGameState();
|
|
||||||
|
|
||||||
GameState->Get<float>("WarmupCountdownEndTime") = 0;
|
GameState->Get<float>("WarmupCountdownEndTime") = 0;
|
||||||
GameMode->Get<float>("WarmupCountdownDuration") = 0;
|
GameMode->Get<float>("WarmupCountdownDuration") = 0;
|
||||||
|
|
||||||
@@ -603,30 +685,37 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
else if (GetAsyncKeyState(VK_F10) & 1)
|
else if (GetAsyncKeyState(VK_F10) & 1)
|
||||||
{
|
{
|
||||||
FString LevelA = Engine_Version < 424
|
if (Engine_Version < 424)
|
||||||
? L"open Athena_Terrain" : Engine_Version >= 500 ? Engine_Version >= 501
|
|
||||||
? L"open Asteria_Terrain"
|
|
||||||
: Globals::bCreative ? L"open Creative_NoApollo_Terrain"
|
|
||||||
: L"open Artemis_Terrain"
|
|
||||||
: Globals::bCreative ? L"open Creative_NoApollo_Terrain"
|
|
||||||
: L"open Apollo_Terrain";
|
|
||||||
|
|
||||||
static auto BeaconClass = FindObject<UClass>(L"/Script/FortniteGame.FortOnlineBeaconHost");
|
|
||||||
auto AllFortBeacons = UGameplayStatics::GetAllActorsOfClass(GetWorld(), BeaconClass);
|
|
||||||
|
|
||||||
for (int i = 0; i < AllFortBeacons.Num(); i++)
|
|
||||||
{
|
{
|
||||||
AllFortBeacons.at(i)->K2_DestroyActor();
|
FString LevelA = Engine_Version < 424
|
||||||
|
? L"open Athena_Terrain" : Engine_Version >= 500 ? Engine_Version >= 501
|
||||||
|
? L"open Asteria_Terrain"
|
||||||
|
: Globals::bCreative ? L"open Creative_NoApollo_Terrain"
|
||||||
|
: L"open Artemis_Terrain"
|
||||||
|
: Globals::bCreative ? L"open Creative_NoApollo_Terrain"
|
||||||
|
: L"open Apollo_Terrain";
|
||||||
|
|
||||||
|
static auto BeaconClass = FindObject<UClass>(L"/Script/FortniteGame.FortOnlineBeaconHost");
|
||||||
|
auto AllFortBeacons = UGameplayStatics::GetAllActorsOfClass(GetWorld(), BeaconClass);
|
||||||
|
|
||||||
|
for (int i = 0; i < AllFortBeacons.Num(); i++)
|
||||||
|
{
|
||||||
|
AllFortBeacons.at(i)->K2_DestroyActor();
|
||||||
|
}
|
||||||
|
|
||||||
|
AllFortBeacons.Free();
|
||||||
|
|
||||||
|
LOG_INFO(LogDev, "Switching!");
|
||||||
|
((AGameMode*)GetWorld()->GetGameMode())->RestartGame();
|
||||||
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), LevelA, nullptr);
|
||||||
|
// UGameplayStatics::OpenLevel(GetWorld(), UKismetStringLibrary::Conv_StringToName(LevelA), true, FString());
|
||||||
|
LOG_INFO(LogGame, "Restarting!");
|
||||||
|
AmountOfRestarts++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_ERROR(LogGame, "Restarting is not supported on chapter 2 and above!");
|
||||||
}
|
}
|
||||||
|
|
||||||
AllFortBeacons.Free();
|
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Switching!");
|
|
||||||
((AGameMode*)GetWorld()->GetGameMode())->RestartGame();
|
|
||||||
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), LevelA, nullptr);
|
|
||||||
// UGameplayStatics::OpenLevel(GetWorld(), UKismetStringLibrary::Conv_StringToName(LevelA), true, FString());
|
|
||||||
LOG_INFO(LogDev, "Restarting!");
|
|
||||||
AmountOfRestarts++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Sleep(1000 / 30);
|
Sleep(1000 / 30);
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ static inline uint64 FindGetPlayerViewpoint()
|
|||||||
|
|
||||||
LOG_INFO(LogDev, "GetPlayerViewpoint StringRef: 0x{:x}", __int64(Addrr) - __int64(GetModuleHandleW(0)));
|
LOG_INFO(LogDev, "GetPlayerViewpoint StringRef: 0x{:x}", __int64(Addrr) - __int64(GetModuleHandleW(0)));
|
||||||
|
|
||||||
for (int i = 0; i < 1200; i++)
|
for (int i = 0; i < 1000; i++)
|
||||||
{
|
{
|
||||||
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55)
|
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55)
|
||||||
{
|
{
|
||||||
@@ -337,8 +337,9 @@ static inline uint64 FindGetPlayerViewpoint()
|
|||||||
return Addrr - i;
|
return Addrr - i;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0xC3) // hmm
|
if (Fortnite_Version == 7.20 && *(uint8_t*)(uint8_t*)(Addrr - i) == 0xC3) // hmm scuffed lmfao
|
||||||
{
|
{
|
||||||
|
LOG_INFO(LogDev, "Hit C3!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user