mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
glorious update
work on rift tour, fix some crash and some bugs, added destroying gadgets when no more uses
This commit is contained in:
@@ -20,13 +20,3 @@ void UFortGadgetItemDefinition::UnequipGadgetData(AFortPlayerController* PlayerC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UFortGadgetItemDefinition::UpdateTrackedAttributesHook(UFortGadgetItemDefinition* GadgetItemDefinition)
|
|
||||||
{
|
|
||||||
// LOG_INFO(LogDev, "UpdateTrackedAttributesHook Return: 0x{:x}", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0)));
|
|
||||||
|
|
||||||
if (GadgetItemDefinition->ShouldDestroyGadgetWhenTrackedAttributesIsZero())
|
|
||||||
{
|
|
||||||
// PlayerState->MulticastTriggerOnGadgetTrackedAttributeDestroyedFX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -51,8 +51,6 @@ public:
|
|||||||
|
|
||||||
void UnequipGadgetData(AFortPlayerController* PlayerController, UFortItem* Item);
|
void UnequipGadgetData(AFortPlayerController* PlayerController, UFortItem* Item);
|
||||||
|
|
||||||
static void UpdateTrackedAttributesHook(UFortGadgetItemDefinition* GadgetItemDefinition);
|
|
||||||
|
|
||||||
static UClass* StaticClass()
|
static UClass* StaticClass()
|
||||||
{
|
{
|
||||||
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortGadgetItemDefinition");
|
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortGadgetItemDefinition");
|
||||||
|
|||||||
@@ -489,7 +489,19 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
|
|
||||||
LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode));
|
LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode));
|
||||||
|
|
||||||
float Duration = 100000.f;
|
bool bShouldSkipAircraft = false;
|
||||||
|
|
||||||
|
GET_PLAYLIST(GameState);
|
||||||
|
|
||||||
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto bSkipAircraftOffset = CurrentPlaylist->GetOffset("bSkipAircraft", false);
|
||||||
|
|
||||||
|
if (bSkipAircraftOffset != -1)
|
||||||
|
bShouldSkipAircraft = CurrentPlaylist->Get<bool>(bSkipAircraftOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
float Duration = bShouldSkipAircraft ? 0 : 100000;
|
||||||
float EarlyDuration = Duration;
|
float EarlyDuration = Duration;
|
||||||
|
|
||||||
float TimeSeconds = UGameplayStatics::GetTimeSeconds(GetWorld());
|
float TimeSeconds = UGameplayStatics::GetTimeSeconds(GetWorld());
|
||||||
@@ -522,8 +534,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
|
|
||||||
if (GameState_AirCraftBehaviorOffset != -1)
|
if (GameState_AirCraftBehaviorOffset != -1)
|
||||||
{
|
{
|
||||||
GET_PLAYLIST(GameState);
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
if (CurrentPlaylist)
|
||||||
{
|
{
|
||||||
static auto Playlist_AirCraftBehaviorOffset = CurrentPlaylist->GetOffset("AirCraftBehavior", false);
|
static auto Playlist_AirCraftBehaviorOffset = CurrentPlaylist->GetOffset("AirCraftBehavior", false);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "FortPlayerStateAthena.h"
|
#include "FortPlayerStateAthena.h"
|
||||||
#include "FortGameModeAthena.h"
|
#include "FortGameModeAthena.h"
|
||||||
#include "FortAthenaMutator.h"
|
#include "FortAthenaMutator.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
/* void AFortGameStateAthena::AddPlayerStateToGameMemberInfo(class AFortPlayerStateAthena* PlayerState)
|
/* void AFortGameStateAthena::AddPlayerStateToGameMemberInfo(class AFortPlayerStateAthena* PlayerState)
|
||||||
{
|
{
|
||||||
@@ -257,6 +258,9 @@ void AFortGameStateAthena::OnRep_PlayersLeft()
|
|||||||
|
|
||||||
TeamsArrayContainer* AFortGameStateAthena::GetTeamsArrayContainer()
|
TeamsArrayContainer* AFortGameStateAthena::GetTeamsArrayContainer()
|
||||||
{
|
{
|
||||||
|
if (!bEnableRebooting) // todo (milxnor) remove
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
static auto FriendlyFireTypeOffset = GetOffset("FriendlyFireType");
|
static auto FriendlyFireTypeOffset = GetOffset("FriendlyFireType");
|
||||||
static int Offset = -1;
|
static int Offset = -1;
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ struct FFortGameFeatureLootTableData
|
|||||||
TSoftObjectPtr<UDataTable> LootPackageData;
|
TSoftObjectPtr<UDataTable> LootPackageData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef EXPERIMENTAL_LOOTING
|
|
||||||
|
|
||||||
template <typename RowStructType = uint8>
|
template <typename RowStructType = uint8>
|
||||||
void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, std::map<FName, RowStructType*>* OutMap, std::function<bool(FName, RowStructType*)> Check = []() { return true; })
|
void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, std::map<FName, RowStructType*>* OutMap, std::function<bool(FName, RowStructType*)> Check = []() { return true; })
|
||||||
{
|
{
|
||||||
@@ -24,7 +22,7 @@ void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, std::map<
|
|||||||
|
|
||||||
for (UDataTable* DataTable : DataTables)
|
for (UDataTable* DataTable : DataTables)
|
||||||
{
|
{
|
||||||
if (!DataTable->IsValidLowLevel())
|
if (!Addresses::LoadAsset && !DataTable->IsValidLowLevel())
|
||||||
{
|
{
|
||||||
continue; // Remove from vector?
|
continue; // Remove from vector?
|
||||||
}
|
}
|
||||||
@@ -368,18 +366,24 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
|
|
||||||
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
|
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
|
||||||
{
|
{
|
||||||
#ifndef brudda
|
|
||||||
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
||||||
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
||||||
|
|
||||||
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
UDataTable* StrongLootTierData = nullptr;
|
||||||
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
UDataTable* StrongLootPackage = nullptr;
|
||||||
#else
|
|
||||||
auto StrongLootTierData = (UDataTable*)Assets::LoadAsset(LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName);
|
if (!Addresses::LoadAsset)
|
||||||
auto StrongLootPackage = (UDataTable*)Assets::LoadAsset(LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName);
|
{
|
||||||
#endif
|
StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StrongLootTierData = (UDataTable*)Assets::LoadAsset(LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName);
|
||||||
|
StrongLootPackage = (UDataTable*)Assets::LoadAsset(LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName);
|
||||||
|
}
|
||||||
|
|
||||||
if (StrongLootTierData && StrongLootPackage)
|
if (StrongLootTierData && StrongLootPackage)
|
||||||
{
|
{
|
||||||
@@ -393,19 +397,22 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
|
|
||||||
if (!bFoundPlaylistTable)
|
if (!bFoundPlaylistTable)
|
||||||
{
|
{
|
||||||
#ifdef brudda
|
if (Addresses::LoadAsset)
|
||||||
|
{
|
||||||
LTDTables.push_back((UDataTable*)Assets::LoadAsset(UKismetStringLibrary::Conv_StringToName(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")));
|
LTDTables.push_back((UDataTable*)Assets::LoadAsset(UKismetStringLibrary::Conv_StringToName(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")));
|
||||||
LPTables.push_back((UDataTable*)Assets::LoadAsset(UKismetStringLibrary::Conv_StringToName(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")));
|
LPTables.push_back((UDataTable*)Assets::LoadAsset(UKismetStringLibrary::Conv_StringToName(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")));
|
||||||
#else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
||||||
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
// LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
||||||
// LPTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
// LPTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
||||||
|
|
||||||
static auto FortGameFeatureDataClass = FindObject<UClass>("/Script/FortniteGame.FortGameFeatureData");
|
static auto FortGameFeatureDataClass = FindObject<UClass>(L"/Script/FortniteGame.FortGameFeatureData");
|
||||||
|
|
||||||
if (FortGameFeatureDataClass)
|
if (FortGameFeatureDataClass)
|
||||||
{
|
{
|
||||||
@@ -573,6 +580,8 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Addresses::LoadAsset)
|
||||||
|
{
|
||||||
if (Fortnite_Version <= 6 || std::floor(Fortnite_Version) == 9) // ahhh
|
if (Fortnite_Version <= 6 || std::floor(Fortnite_Version) == 9) // ahhh
|
||||||
{
|
{
|
||||||
LTDTables.clear();
|
LTDTables.clear();
|
||||||
@@ -595,8 +604,11 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
||||||
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
||||||
|
|
||||||
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
UDataTable* StrongLootTierData = nullptr;
|
||||||
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
UDataTable* StrongLootPackage = nullptr;
|
||||||
|
|
||||||
|
StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
if (StrongLootTierData && StrongLootPackage)
|
if (StrongLootTierData && StrongLootPackage)
|
||||||
{
|
{
|
||||||
@@ -615,6 +627,8 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (LTDTables.size() <= 0 || LPTables.size() <= 0)
|
if (LTDTables.size() <= 0 || LPTables.size() <= 0)
|
||||||
{
|
{
|
||||||
LOG_WARN(LogLoot, "Empty tables! ({} {})", LTDTables.size(), LPTables.size());
|
LOG_WARN(LogLoot, "Empty tables! ({} {})", LTDTables.size(), LPTables.size());
|
||||||
@@ -683,640 +697,3 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
|
|
||||||
return LootDrops;
|
return LootDrops;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
|
||||||
float GetRandomFloatForLooting(float min, float max)
|
|
||||||
{
|
|
||||||
std::random_device rd;
|
|
||||||
std::mt19937 gen(rd());
|
|
||||||
std::uniform_real_distribution<> dis(min, max);
|
|
||||||
float random_number = dis(gen);
|
|
||||||
|
|
||||||
return random_number;
|
|
||||||
|
|
||||||
return UKismetMathLibrary::RandomFloatInRange(min, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FFortLootTierData* GetLootTierData(std::vector<FFortLootTierData*>& LootTierData, float TotalWeight)
|
|
||||||
{
|
|
||||||
FFortLootTierData* SelectedItem = nullptr;
|
|
||||||
|
|
||||||
for (auto Item : LootTierData)
|
|
||||||
{
|
|
||||||
TotalWeight += Item->GetWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
float RandomNumber = GetRandomFloatForLooting(0, TotalWeight); // is -1 needed?
|
|
||||||
|
|
||||||
for (auto Item : LootTierData)
|
|
||||||
{
|
|
||||||
if (RandomNumber <= Item->GetWeight())
|
|
||||||
{
|
|
||||||
SelectedItem = Item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomNumber -= Item->GetWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SelectedItem)
|
|
||||||
return GetLootTierData(LootTierData, TotalWeight);
|
|
||||||
|
|
||||||
return SelectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FFortLootPackageData* GetLootPackage(std::vector<FFortLootPackageData*>& LootPackages, float TotalWeight)
|
|
||||||
{
|
|
||||||
FFortLootPackageData* SelectedItem = nullptr;
|
|
||||||
|
|
||||||
float RandomNumber = GetRandomFloatForLooting(0, TotalWeight); // is -1 needed?
|
|
||||||
|
|
||||||
for (auto Item : LootPackages)
|
|
||||||
{
|
|
||||||
if (RandomNumber <= Item->GetWeight())
|
|
||||||
{
|
|
||||||
SelectedItem = Item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomNumber -= Item->GetWeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SelectedItem)
|
|
||||||
return GetLootPackage(LootPackages, TotalWeight);
|
|
||||||
|
|
||||||
return SelectedItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recursive)
|
|
||||||
{
|
|
||||||
std::vector<LootDrop> LootDrops;
|
|
||||||
|
|
||||||
if (recursive > 6)
|
|
||||||
return LootDrops;
|
|
||||||
|
|
||||||
auto GameState = ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena();
|
|
||||||
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
|
|
||||||
|
|
||||||
static std::vector<UDataTable*> LTDTables;
|
|
||||||
static std::vector<UDataTable*> LPTables;
|
|
||||||
|
|
||||||
static auto CompositeDataTableClass = FindObject<UClass>(L"/Script/Engine.CompositeDataTable");
|
|
||||||
|
|
||||||
static int LastNum1 = 14915;
|
|
||||||
|
|
||||||
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
|
|
||||||
|
|
||||||
if (LastNum1 != Globals::AmountOfListens)
|
|
||||||
{
|
|
||||||
LastNum1 = Globals::AmountOfListens;
|
|
||||||
|
|
||||||
LTDTables.clear();
|
|
||||||
LPTables.clear();
|
|
||||||
|
|
||||||
bool bFoundPlaylistTable = false;
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
|
||||||
{
|
|
||||||
static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData");
|
|
||||||
auto& LootTierDataSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootTierDataOffset);
|
|
||||||
|
|
||||||
static auto LootPackagesOffset = CurrentPlaylist->GetOffset("LootPackages");
|
|
||||||
auto& LootPackagesSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootPackagesOffset);
|
|
||||||
|
|
||||||
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
|
|
||||||
{
|
|
||||||
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
|
||||||
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
|
||||||
|
|
||||||
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
|
|
||||||
if (StrongLootTierData && StrongLootPackage)
|
|
||||||
{
|
|
||||||
LTDTables.push_back(StrongLootTierData);
|
|
||||||
LPTables.push_back(StrongLootPackage);
|
|
||||||
|
|
||||||
bFoundPlaylistTable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bFoundPlaylistTable)
|
|
||||||
{
|
|
||||||
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
|
||||||
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
|
||||||
// LPTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
|
||||||
|
|
||||||
static auto FortGameFeatureDataClass = FindObject<UClass>("/Script/FortniteGame.FortGameFeatureData");
|
|
||||||
|
|
||||||
if (FortGameFeatureDataClass)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < ChunkedObjects->Num(); i++)
|
|
||||||
{
|
|
||||||
auto Object = ChunkedObjects->GetObjectByIndex(i);
|
|
||||||
|
|
||||||
if (!Object)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (Object->IsA(FortGameFeatureDataClass))
|
|
||||||
{
|
|
||||||
auto GameFeatureData = Object;
|
|
||||||
static auto DefaultLootTableDataOffset = GameFeatureData->GetOffset("DefaultLootTableData");
|
|
||||||
|
|
||||||
if (DefaultLootTableDataOffset != -1)
|
|
||||||
{
|
|
||||||
auto DefaultLootTableData = GameFeatureData->GetPtr<FFortGameFeatureLootTableData>(DefaultLootTableDataOffset);
|
|
||||||
|
|
||||||
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 : UDataTable::StaticClass(), true);
|
|
||||||
auto LootPackagePtr = DefaultLootTableData->LootPackageData.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
|
|
||||||
if (LootPackagePtr)
|
|
||||||
{
|
|
||||||
LPTables.push_back(LootPackagePtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
|
||||||
{
|
|
||||||
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
|
||||||
auto& PlaylistOverrideLootTableData = GameFeatureData->Get<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
for (auto& Value : PlaylistOverrideLootTableData)
|
|
||||||
{
|
|
||||||
auto CurrentOverrideTag = Value.First;
|
|
||||||
|
|
||||||
if (Tag.TagName == CurrentOverrideTag.TagName)
|
|
||||||
{
|
|
||||||
auto OverrideLootPackageTableStr = Value.Second.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite");
|
|
||||||
|
|
||||||
auto ptr = Value.Second.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
/* if (bOverrideIsComposite)
|
|
||||||
{
|
|
||||||
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
|
||||||
|
|
||||||
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
|
||||||
|
|
||||||
for (int z = 0; z < ParentTables->size(); z++)
|
|
||||||
{
|
|
||||||
auto ParentTable = ParentTables->At(z);
|
|
||||||
|
|
||||||
if (ParentTable)
|
|
||||||
{
|
|
||||||
LPTables.push_back(ParentTable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
LPTables.push_back(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LootTierDataPtr)
|
|
||||||
{
|
|
||||||
LTDTables.push_back(LootTierDataPtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
|
||||||
{
|
|
||||||
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
|
||||||
auto& PlaylistOverrideLootTableData = GameFeatureData->Get<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
for (auto& Value : PlaylistOverrideLootTableData)
|
|
||||||
{
|
|
||||||
auto CurrentOverrideTag = Value.First;
|
|
||||||
|
|
||||||
if (Tag.TagName == CurrentOverrideTag.TagName)
|
|
||||||
{
|
|
||||||
auto OverrideLootTierDataStr = Value.Second.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite");
|
|
||||||
|
|
||||||
auto ptr = Value.Second.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
/* if (bOverrideIsComposite)
|
|
||||||
{
|
|
||||||
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
|
||||||
|
|
||||||
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
|
||||||
|
|
||||||
for (int z = 0; z < ParentTables->size(); z++)
|
|
||||||
{
|
|
||||||
auto ParentTable = ParentTables->At(z);
|
|
||||||
|
|
||||||
if (ParentTable)
|
|
||||||
{
|
|
||||||
LTDTables.push_back(ParentTable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
LTDTables.push_back(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < LTDTables.size(); i++)
|
|
||||||
{
|
|
||||||
auto& Table = LTDTables.at(i);
|
|
||||||
|
|
||||||
if (!Table->IsValidLowLevel())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Table->AddToRoot();
|
|
||||||
LOG_INFO(LogDev, "[{}] LTD {}", i, Table->GetFullName());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < LPTables.size(); i++)
|
|
||||||
{
|
|
||||||
auto& Table = LPTables.at(i);
|
|
||||||
|
|
||||||
if (!Table->IsValidLowLevel())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Table->AddToRoot();
|
|
||||||
LOG_INFO(LogDev, "[{}] LP {}", i, Table->GetFullName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Fortnite_Version <= 6 || std::floor(Fortnite_Version) == 9) // ahhh
|
|
||||||
{
|
|
||||||
LTDTables.clear();
|
|
||||||
LPTables.clear();
|
|
||||||
|
|
||||||
bool bFoundPlaylistTable = false;
|
|
||||||
|
|
||||||
if (CurrentPlaylist)
|
|
||||||
{
|
|
||||||
static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData");
|
|
||||||
auto& LootTierDataSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootTierDataOffset);
|
|
||||||
|
|
||||||
static auto LootPackagesOffset = CurrentPlaylist->GetOffset("LootPackages");
|
|
||||||
auto& LootPackagesSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootPackagesOffset);
|
|
||||||
|
|
||||||
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
|
|
||||||
{
|
|
||||||
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
|
||||||
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
|
||||||
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
|
||||||
|
|
||||||
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
|
||||||
|
|
||||||
if (StrongLootTierData && StrongLootPackage)
|
|
||||||
{
|
|
||||||
LTDTables.push_back(StrongLootTierData);
|
|
||||||
LPTables.push_back(StrongLootPackage);
|
|
||||||
|
|
||||||
bFoundPlaylistTable = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bFoundPlaylistTable)
|
|
||||||
{
|
|
||||||
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
|
||||||
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LTDTables.size() <= 0 || LPTables.size() <= 0)
|
|
||||||
{
|
|
||||||
LOG_WARN(LogLoot, "Empty tables! ({} {})", LTDTables.size(), LPTables.size());
|
|
||||||
return LootDrops;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<FFortLootTierData*> TierGroupLTDs;
|
|
||||||
|
|
||||||
float TotalTierGroupLTDsWeight = 0;
|
|
||||||
|
|
||||||
for (int p = 0; p < LTDTables.size(); p++)
|
|
||||||
{
|
|
||||||
auto LTD = LTDTables[p];
|
|
||||||
|
|
||||||
// if (bPrint)
|
|
||||||
// LOG_INFO(LogLoot, "LTD: {}", !LTD->IsValidLowLevel() ? "BadRead" : LTD->GetFullName());
|
|
||||||
|
|
||||||
if (!LTD->IsValidLowLevel())
|
|
||||||
{
|
|
||||||
// if (bPrint)
|
|
||||||
LOG_INFO(LogLoot, "BadRead!");
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& LTDRowMap = LTD->GetRowMap();
|
|
||||||
|
|
||||||
for (auto& CurrentLTD : LTDRowMap)
|
|
||||||
{
|
|
||||||
auto TierData = (FFortLootTierData*)CurrentLTD.Value();
|
|
||||||
|
|
||||||
if (IsBadReadPtr(TierData, 8)) // this shouldn't be needed
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (TierGroupName == TierData->GetTierGroup() && TierData->GetWeight() != 0)
|
|
||||||
{
|
|
||||||
TotalTierGroupLTDsWeight += TierData->GetWeight();
|
|
||||||
TierGroupLTDs.push_back(TierData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TierGroupLTDs.size() == 0)
|
|
||||||
{
|
|
||||||
LOG_WARN(LogLoot, "Failed to find any LTD for: {}", TierGroupName.ToString());
|
|
||||||
return LootDrops;
|
|
||||||
}
|
|
||||||
|
|
||||||
FFortLootTierData* ChosenRowLootTierData = GetLootTierData(TierGroupLTDs, TotalTierGroupLTDsWeight);
|
|
||||||
|
|
||||||
if (!ChosenRowLootTierData) // Should NEVER happen
|
|
||||||
return LootDrops;
|
|
||||||
|
|
||||||
if (ChosenRowLootTierData->GetNumLootPackageDrops() <= 0)
|
|
||||||
return PickLootDrops(TierGroupName, bPrint, ++recursive); // hm
|
|
||||||
|
|
||||||
auto& LootPackageCategoryMinArray = ChosenRowLootTierData->GetLootPackageCategoryMinArray();
|
|
||||||
auto& LootPackageCategoryWeightArray = ChosenRowLootTierData->GetLootPackageCategoryWeightArray();
|
|
||||||
auto& LootPackageCategoryMaxArray = ChosenRowLootTierData->GetLootPackageCategoryMaxArray();
|
|
||||||
|
|
||||||
if (LootPackageCategoryMinArray.ArrayNum != LootPackageCategoryWeightArray.ArrayNum ||
|
|
||||||
LootPackageCategoryMinArray.ArrayNum != LootPackageCategoryMaxArray.ArrayNum)
|
|
||||||
return PickLootDrops(TierGroupName, bPrint, ++recursive); // hm
|
|
||||||
|
|
||||||
int MinimumLootDrops = 0;
|
|
||||||
|
|
||||||
static int AmountToAdd = Engine_Version >= 424 ? Engine_Version >= 500 ? 1 : 1 : 0; // fr
|
|
||||||
|
|
||||||
float NumLootPackageDrops = std::floor(ChosenRowLootTierData->GetNumLootPackageDrops() + AmountToAdd);
|
|
||||||
|
|
||||||
if (LootPackageCategoryMinArray.ArrayNum)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < LootPackageCategoryMinArray.ArrayNum; i++)
|
|
||||||
{
|
|
||||||
if (LootPackageCategoryMinArray.at(i) > 0)
|
|
||||||
{
|
|
||||||
MinimumLootDrops += LootPackageCategoryMinArray.at(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MinimumLootDrops > NumLootPackageDrops)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int SumLootPackageCategoryWeightArray = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < LootPackageCategoryWeightArray.Num(); i++)
|
|
||||||
{
|
|
||||||
auto CategoryWeight = LootPackageCategoryWeightArray.at(i);
|
|
||||||
|
|
||||||
if (CategoryWeight > 0)
|
|
||||||
{
|
|
||||||
auto CategoryMaxArray = LootPackageCategoryMaxArray.at(i);
|
|
||||||
|
|
||||||
if (CategoryMaxArray < 0)
|
|
||||||
{
|
|
||||||
SumLootPackageCategoryWeightArray += CategoryWeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int SumLootPackageCategoryMinArray = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < LootPackageCategoryMinArray.Num(); i++)
|
|
||||||
{
|
|
||||||
auto CategoryWeight = LootPackageCategoryMinArray.at(i);
|
|
||||||
|
|
||||||
if (CategoryWeight > 0)
|
|
||||||
{
|
|
||||||
auto CategoryMaxArray = LootPackageCategoryMaxArray.at(i);
|
|
||||||
|
|
||||||
if (CategoryMaxArray < 0)
|
|
||||||
{
|
|
||||||
SumLootPackageCategoryMinArray += CategoryWeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (SumLootPackageCategoryWeightArray > SumLootPackageCategoryMinArray)
|
|
||||||
// return PickLootDrops(TierGroupName, bPrint, ++recursive); // hm
|
|
||||||
|
|
||||||
std::vector<FFortLootPackageData*> TierGroupLPs;
|
|
||||||
|
|
||||||
for (int p = 0; p < LPTables.size(); p++)
|
|
||||||
{
|
|
||||||
auto LP = LPTables[p];
|
|
||||||
|
|
||||||
if (!LP->IsValidLowLevel())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto& LPRowMap = LP->GetRowMap();
|
|
||||||
|
|
||||||
for (auto& CurrentLP : LPRowMap)
|
|
||||||
{
|
|
||||||
auto LootPackage = (FFortLootPackageData*)CurrentLP.Value();
|
|
||||||
|
|
||||||
if (!LootPackage)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (LootPackage->GetLootPackageID() == ChosenRowLootTierData->GetLootPackage() && LootPackage->GetWeight() != 0 && LootPackage->GetCount() != 0)
|
|
||||||
{
|
|
||||||
TierGroupLPs.push_back(LootPackage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ChosenLootPackageName = ChosenRowLootTierData->GetLootPackage().ToString();
|
|
||||||
|
|
||||||
if (ChosenLootPackageName.contains(".Empty")) // I don't think?
|
|
||||||
{
|
|
||||||
return PickLootDrops(TierGroupName, bPrint, ++recursive);
|
|
||||||
// return LootDrops;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool bIsWorldList = ChosenLootPackageName.contains("WorldList");
|
|
||||||
|
|
||||||
if (bPrint)
|
|
||||||
{
|
|
||||||
LOG_INFO(LogLoot, "NumLootPackageDrops Floored: {}", NumLootPackageDrops);
|
|
||||||
LOG_INFO(LogLoot, "NumLootPackageDrops Original: {}", ChosenRowLootTierData->GetNumLootPackageDrops());
|
|
||||||
LOG_INFO(LogLoot, "TierGroupLPs.size(): {}", TierGroupLPs.size());
|
|
||||||
LOG_INFO(LogLoot, "ChosenLootPackageName: {}", ChosenLootPackageName);
|
|
||||||
|
|
||||||
/* float t = ChosenRowLootTierData->NumLootPackageDrops;
|
|
||||||
|
|
||||||
int b = (int)((t + t) - 0.5) >> 1;
|
|
||||||
auto c = ChosenRowLootTierData->NumLootPackageDrops - b;
|
|
||||||
|
|
||||||
b += c >= (rand() * 0.000030518509);
|
|
||||||
|
|
||||||
std::cout << "b: " << b << '\n'; */
|
|
||||||
}
|
|
||||||
|
|
||||||
LootDrops.reserve(NumLootPackageDrops);
|
|
||||||
|
|
||||||
for (float i = 0; i < NumLootPackageDrops; i++)
|
|
||||||
{
|
|
||||||
FFortLootPackageData* TierGroupLP = nullptr;
|
|
||||||
|
|
||||||
if (i >= TierGroupLPs.size())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
/* auto randomNumberFloat = UKismetMathLibrary::RandomFloatInRange(0, TierGroupLPs.size());
|
|
||||||
auto randomNumberFloored = std::floor((int)randomNumberFloat); // idk
|
|
||||||
|
|
||||||
if (bPrint)
|
|
||||||
LOG_INFO(LogLoot, "randomNumberFloat: {} randomNumberFloored: {}", randomNumberFloat, randomNumberFloored);
|
|
||||||
|
|
||||||
TierGroupLP = TierGroupLPs.at(randomNumberFloored); */
|
|
||||||
|
|
||||||
TierGroupLP = TierGroupLPs.at(i - NumLootPackageDrops); // Once we fix chapter 2 loot package drops, we can use this
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TierGroupLP = TierGroupLPs.at(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TierGroupLP)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto& LootPackageCallFStr = TierGroupLP->GetLootPackageCall();
|
|
||||||
auto TierGroupLPStr = LootPackageCallFStr.IsValid() ? LootPackageCallFStr.ToString() : "InvalidLootPackageCall.Empty";
|
|
||||||
|
|
||||||
if (bPrint)
|
|
||||||
LOG_INFO(LogLoot, "TierGroupLPStr: {}", TierGroupLPStr);
|
|
||||||
|
|
||||||
if (!bIsWorldList && TierGroupLPStr.contains(".Empty"))
|
|
||||||
{
|
|
||||||
NumLootPackageDrops++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<FFortLootPackageData*> lootPackageCalls;
|
|
||||||
float lootPackageCallsTotalWeight = 0;
|
|
||||||
|
|
||||||
if (bIsWorldList)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < TierGroupLPs.size(); j++)
|
|
||||||
{
|
|
||||||
auto& CurrentLP = TierGroupLPs.at(j);
|
|
||||||
|
|
||||||
if (CurrentLP->GetWeight() != 0)
|
|
||||||
{
|
|
||||||
lootPackageCallsTotalWeight += CurrentLP->GetWeight();
|
|
||||||
lootPackageCalls.push_back(CurrentLP);
|
|
||||||
|
|
||||||
if (bPrint)
|
|
||||||
{
|
|
||||||
// LOG_INFO(LogDev, "Adding LootPackage: {}", CurrentLP->GetAnnotation().ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int p = 0; p < LPTables.size(); p++)
|
|
||||||
{
|
|
||||||
if (!LPTables[p]->IsValidLowLevel())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
auto& LPRowMap = LPTables[p]->GetRowMap();
|
|
||||||
|
|
||||||
for (auto& CurrentLP : LPRowMap)
|
|
||||||
{
|
|
||||||
auto LootPackage = (FFortLootPackageData*)CurrentLP.Value();
|
|
||||||
|
|
||||||
if (LootPackage->GetLootPackageID().ToString() == TierGroupLPStr && LootPackage->GetWeight() != 0 && LootPackage->GetCount() != 0)
|
|
||||||
{
|
|
||||||
lootPackageCallsTotalWeight += LootPackage->GetWeight();
|
|
||||||
lootPackageCalls.push_back(LootPackage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bPrint)
|
|
||||||
LOG_INFO(LogLoot, "lootPackageCalls.size(): {}", lootPackageCalls.size());
|
|
||||||
|
|
||||||
if (lootPackageCalls.size() == 0)
|
|
||||||
{
|
|
||||||
// std::cout << "lootPackageCalls.size() == 0!\n";
|
|
||||||
NumLootPackageDrops++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
FFortLootPackageData* LootPackageCall = GetLootPackage(lootPackageCalls, lootPackageCallsTotalWeight);
|
|
||||||
|
|
||||||
if (!LootPackageCall) // Should NEVER happen
|
|
||||||
{
|
|
||||||
LOG_ERROR(LogLoot, "Failed to get any loot package call??");
|
|
||||||
NumLootPackageDrops++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ItemDef = LootPackageCall->GetItemDefinition().Get(UFortItemDefinition::StaticClass(), true);
|
|
||||||
|
|
||||||
if (!ItemDef)
|
|
||||||
{
|
|
||||||
NumLootPackageDrops++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bPrint)
|
|
||||||
{
|
|
||||||
LOG_INFO(LogLoot, "[{}] {} {} {}", i, lootPackageCalls.size(), TierGroupLPStr, ItemDef->GetName());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDef);
|
|
||||||
|
|
||||||
LootDrops.push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDef, LootPackageCall->GetCount(), WeaponDef ? WeaponDef->GetClipSize() : 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return LootDrops;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#include "SoftObjectPtr.h"
|
#include "SoftObjectPtr.h"
|
||||||
#include "FortItem.h"
|
#include "FortItem.h"
|
||||||
|
|
||||||
#define EXPERIMENTAL_LOOTING
|
|
||||||
|
|
||||||
struct FFortLootPackageData
|
struct FFortLootPackageData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ void AFortPickup::SpawnMovementComponent()
|
|||||||
AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
|
AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
|
||||||
{
|
{
|
||||||
if (PickupData.Source == -1)
|
if (PickupData.Source == -1)
|
||||||
PickupData.Source = 0;
|
PickupData.Source = -1;
|
||||||
if (PickupData.SourceType == -1)
|
if (PickupData.SourceType == -1)
|
||||||
PickupData.SourceType = -1;
|
PickupData.SourceType = -1;
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
|
|||||||
|
|
||||||
for (auto& AttributeValue : AttributeValueVector)
|
for (auto& AttributeValue : AttributeValueVector)
|
||||||
{
|
{
|
||||||
// ReplicatedEntry->GetGenericAttributeValues().Add(AttributeValue);
|
PrimaryPickupItemEntry->GetGenericAttributeValues().Add(AttributeValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "DataTableFunctionLibrary.h"
|
#include "DataTableFunctionLibrary.h"
|
||||||
#include "AthenaResurrectionComponent.h"
|
#include "AthenaResurrectionComponent.h"
|
||||||
#include "FortAthenaMutator_InventoryOverride.h"
|
#include "FortAthenaMutator_InventoryOverride.h"
|
||||||
|
#include "FortGadgetItemDefinition.h"
|
||||||
|
|
||||||
void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* Stack, void* Ret)
|
void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* Stack, void* Ret)
|
||||||
{
|
{
|
||||||
@@ -501,3 +502,88 @@ void AFortPlayerControllerAthena::ServerReadyToStartMatchHook(AFortPlayerControl
|
|||||||
|
|
||||||
return ServerReadyToStartMatchOriginal(PlayerController);
|
return ServerReadyToStartMatchOriginal(PlayerController);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AFortPlayerControllerAthena::UpdateTrackedAttributesHook(AFortPlayerControllerAthena* PlayerController)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "UpdateTrackedAttributesHook Return: 0x{:x}", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0)));
|
||||||
|
|
||||||
|
// IDK IF GADGET IS A PARAM OR WHAT
|
||||||
|
|
||||||
|
auto PlayerState = Cast<AFortPlayerStateAthena>(PlayerController->GetPlayerState()); // really we only need zone
|
||||||
|
|
||||||
|
if (!PlayerState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto ASC = PlayerState->GetAbilitySystemComponent();
|
||||||
|
|
||||||
|
if (!ASC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto WorldInventory = PlayerController->GetWorldInventory();
|
||||||
|
|
||||||
|
if (!WorldInventory)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances();
|
||||||
|
|
||||||
|
std::vector<UFortItem*> ItemInstancesToRemove;
|
||||||
|
|
||||||
|
for (int i = 0; i < ItemInstances.Num(); i++)
|
||||||
|
{
|
||||||
|
auto ItemInstance = ItemInstances.at(i);
|
||||||
|
auto GadgetItemDefinition = Cast<UFortGadgetItemDefinition>(ItemInstance->GetItemEntry()->GetItemDefinition());
|
||||||
|
|
||||||
|
if (!GadgetItemDefinition)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!GadgetItemDefinition->ShouldDestroyGadgetWhenTrackedAttributesIsZero())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool bIsTrackedAttributesZero = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < GadgetItemDefinition->GetTrackedAttributes().Num(); i++)
|
||||||
|
{
|
||||||
|
auto& CurrentTrackedAttribute = GadgetItemDefinition->GetTrackedAttributes().at(i);
|
||||||
|
|
||||||
|
int CurrentAttributeValue = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < ASC->GetSpawnedAttributes().Num(); i++)
|
||||||
|
{
|
||||||
|
auto CurrentSpawnedAttribute = ASC->GetSpawnedAttributes().at(i);
|
||||||
|
|
||||||
|
if (CurrentSpawnedAttribute->IsA(CurrentTrackedAttribute.AttributeOwner))
|
||||||
|
{
|
||||||
|
auto PropertyOffset = CurrentSpawnedAttribute->GetOffset(CurrentTrackedAttribute.GetAttributePropertyName());
|
||||||
|
|
||||||
|
if (PropertyOffset != -1)
|
||||||
|
{
|
||||||
|
if (CurrentSpawnedAttribute->GetPtr<FFortGameplayAttributeData>(PropertyOffset)->GetCurrentValue() > 0)
|
||||||
|
{
|
||||||
|
bIsTrackedAttributesZero = false;
|
||||||
|
break; // hm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bIsTrackedAttributesZero)
|
||||||
|
{
|
||||||
|
ItemInstancesToRemove.push_back(ItemInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto ItemInstanceToRemove : ItemInstancesToRemove)
|
||||||
|
{
|
||||||
|
auto GadgetItemDefinition = Cast<UFortGadgetItemDefinition>(ItemInstanceToRemove->GetItemEntry()->GetItemDefinition());
|
||||||
|
|
||||||
|
WorldInventory->RemoveItem(ItemInstanceToRemove->GetItemEntry()->GetItemGuid(), nullptr, ItemInstanceToRemove->GetItemEntry()->GetCount(), true);
|
||||||
|
|
||||||
|
static auto MulticastTriggerOnGadgetTrackedAttributeDestroyedFXFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerStateZone.MulticastTriggerOnGadgetTrackedAttributeDestroyedFX");
|
||||||
|
PlayerState->ProcessEvent(MulticastTriggerOnGadgetTrackedAttributeDestroyedFXFn, &GadgetItemDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ItemInstancesToRemove.size() > 0)
|
||||||
|
WorldInventory->Update();
|
||||||
|
}
|
||||||
@@ -186,6 +186,7 @@ public:
|
|||||||
static void ServerPlaySquadQuickChatMessageHook(AFortPlayerControllerAthena* PlayerController, __int64 ChatEntry, __int64 SenderID);
|
static void ServerPlaySquadQuickChatMessageHook(AFortPlayerControllerAthena* PlayerController, __int64 ChatEntry, __int64 SenderID);
|
||||||
static void GetPlayerViewPointHook(AFortPlayerControllerAthena* PlayerController, FVector& Location, FRotator& Rotation);
|
static void GetPlayerViewPointHook(AFortPlayerControllerAthena* PlayerController, FVector& Location, FRotator& Rotation);
|
||||||
static void ServerReadyToStartMatchHook(AFortPlayerControllerAthena* PlayerController);
|
static void ServerReadyToStartMatchHook(AFortPlayerControllerAthena* PlayerController);
|
||||||
|
static void UpdateTrackedAttributesHook(AFortPlayerControllerAthena* PlayerController);
|
||||||
|
|
||||||
static UClass* StaticClass()
|
static UClass* StaticClass()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ struct FFortGameplayEffectDeliveryInfo
|
|||||||
{
|
{
|
||||||
static UStruct* GetStruct()
|
static UStruct* GetStruct()
|
||||||
{
|
{
|
||||||
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortGameplayEffectDeliveryInfo");
|
static auto Struct = FindObject<UStruct>(L"/Script/FortniteGame.FortGameplayEffectDeliveryInfo");
|
||||||
return Struct;
|
return Struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ struct FFortAbilitySetDeliveryInfo
|
|||||||
{
|
{
|
||||||
static UStruct* GetStruct()
|
static UStruct* GetStruct()
|
||||||
{
|
{
|
||||||
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortAbilitySetDeliveryInfo");
|
static auto Struct = FindObject<UStruct>(L"/Script/FortniteGame.FortAbilitySetDeliveryInfo");
|
||||||
return Struct;
|
return Struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,6 +165,8 @@ public:
|
|||||||
if (!Actor)
|
if (!Actor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO Use the UAbilitySystemInterface or whatever
|
||||||
|
|
||||||
UAbilitySystemComponent* AbilitySystemComponent = nullptr;
|
UAbilitySystemComponent* AbilitySystemComponent = nullptr;
|
||||||
|
|
||||||
if (auto BuildingActor = Cast<ABuildingActor>(Actor))
|
if (auto BuildingActor = Cast<ABuildingActor>(Actor))
|
||||||
@@ -230,7 +232,7 @@ public:
|
|||||||
if (!CurrentGameplayEffect)
|
if (!CurrentGameplayEffect)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Giving GameplayEffect {}", CurrentGameplayEffect->GetFullName());
|
// LOG_INFO(LogDev, "Giving GameplayEffect {}", CurrentGameplayEffect->GetFullName());
|
||||||
AbilitySystemComponent->ApplyGameplayEffectToSelf(CurrentGameplayEffect, CurrentGameplayEffectInfo.Level);
|
AbilitySystemComponent->ApplyGameplayEffectToSelf(CurrentGameplayEffect, CurrentGameplayEffectInfo.Level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -562,6 +562,11 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
|
|||||||
toNull.push_back(Memcury::Scanner::FindPattern("40 55 57 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F9 74 3B 80 3D ? ? ? ? ? 0F").Get());
|
toNull.push_back(Memcury::Scanner::FindPattern("40 55 57 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F9 74 3B 80 3D ? ? ? ? ? 0F").Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (std::floor(Fortnite_Version) == 17)
|
||||||
|
{
|
||||||
|
toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 70 08 48 89 78 10 55 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 ED").Get()); // collectgarbage
|
||||||
|
}
|
||||||
|
|
||||||
if (Engine_Version == 500)
|
if (Engine_Version == 500)
|
||||||
{
|
{
|
||||||
// toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 F6 0F 29 70 A8 44 38 35").Get()); // zone
|
// toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 F6 0F 29 70 A8 44 38 35").Get()); // zone
|
||||||
|
|||||||
@@ -45,6 +45,16 @@
|
|||||||
#include "FortAthenaVehicleSpawner.h"
|
#include "FortAthenaVehicleSpawner.h"
|
||||||
#include "FortGameSessionDedicatedAthena.h"
|
#include "FortGameSessionDedicatedAthena.h"
|
||||||
|
|
||||||
|
enum class EMeshNetworkNodeType : uint8_t
|
||||||
|
{
|
||||||
|
Root = 0,
|
||||||
|
Inner = 1,
|
||||||
|
Edge = 2,
|
||||||
|
Client = 3,
|
||||||
|
Unknown = 4,
|
||||||
|
EMeshNetworkNodeType_MAX = 5
|
||||||
|
};
|
||||||
|
|
||||||
enum ENetMode
|
enum ENetMode
|
||||||
{
|
{
|
||||||
NM_Standalone,
|
NM_Standalone,
|
||||||
@@ -54,12 +64,19 @@ enum ENetMode
|
|||||||
NM_MAX,
|
NM_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static EMeshNetworkNodeType GetMeshNetworkNodeTypeHook(__int64 a1)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "GetMeshNetworkNodeTypeHook Ret: 0x{:x}", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0)));
|
||||||
|
return EMeshNetworkNodeType::Edge;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr ENetMode NetMode = ENetMode::NM_DedicatedServer;
|
constexpr ENetMode NetMode = ENetMode::NM_DedicatedServer;
|
||||||
|
|
||||||
static ENetMode GetNetModeHook() { return NetMode; }
|
static ENetMode GetNetModeHook() { return NetMode; }
|
||||||
static ENetMode GetNetModeHook2() { return NetMode; }
|
static ENetMode GetNetModeHook2() { return NetMode; }
|
||||||
|
|
||||||
static bool ReturnTrueHook() { return true; }
|
static bool ReturnTrueHook() { return true; }
|
||||||
|
static bool ReturnFalseHook() { return false; }
|
||||||
static int Return2Hook() { return 2; }
|
static int Return2Hook() { return 2; }
|
||||||
|
|
||||||
static bool NoMCPHook() { return Globals::bNoMCP; }
|
static bool NoMCPHook() { return Globals::bNoMCP; }
|
||||||
@@ -134,6 +151,56 @@ void __fastcall ApplyHomebaseEffectsOnPlayerSetupHook(
|
|||||||
return ApplyHomebaseEffectsOnPlayerSetupOriginal(GameState, a2, a3, a4, Hero, a6, a7);
|
return ApplyHomebaseEffectsOnPlayerSetupOriginal(GameState, a2, a3, a4, Hero, a6, a7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
static unsigned __int8 (*SpecialEventScript_ActivatePhaseOriginal)(UObject* SpecialEventScript, int NewPhase);
|
||||||
|
|
||||||
|
unsigned __int8 SpecialEventScript_ActivatePhaseHook(UObject* SpecialEventScript, int NewPhase)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "SpecialEventScript_ActivatePhaseHook {}!", NewPhase);
|
||||||
|
|
||||||
|
static auto ReplicatedActivePhaseIndexOffset = SpecialEventScript->GetOffset("ReplicatedActivePhaseIndex");
|
||||||
|
SpecialEventScript->Get<int32>(ReplicatedActivePhaseIndexOffset) = NewPhase;
|
||||||
|
|
||||||
|
static auto OnRep_ReplicatedActivePhaseIndexFn = FindObject<UFunction>("/Script/SpecialEventGameplayRuntime.SpecialEventScript.OnRep_ReplicatedActivePhaseIndex");
|
||||||
|
SpecialEventScript->ProcessEvent(OnRep_ReplicatedActivePhaseIndexFn);
|
||||||
|
|
||||||
|
return SpecialEventScript_ActivatePhaseOriginal(SpecialEventScript, NewPhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void (*ActivatePhaseAtIndexOriginal)(UObject* SpecialEventScript, int Index);
|
||||||
|
|
||||||
|
void ActivatePhaseAtIndexHook(UObject* SpecialEventScript, int Index)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "ActivatePhaseAtIndexHook {}!", Index);
|
||||||
|
|
||||||
|
static auto ReplicatedActivePhaseIndexOffset = SpecialEventScript->GetOffset("ReplicatedActivePhaseIndex");
|
||||||
|
SpecialEventScript->Get<int32>(ReplicatedActivePhaseIndexOffset) = Index;
|
||||||
|
|
||||||
|
static auto OnRep_ReplicatedActivePhaseIndexFn = FindObject<UFunction>("/Script/SpecialEventGameplayRuntime.SpecialEventScript.OnRep_ReplicatedActivePhaseIndex");
|
||||||
|
SpecialEventScript->ProcessEvent(OnRep_ReplicatedActivePhaseIndexFn);
|
||||||
|
|
||||||
|
return ActivatePhaseAtIndexOriginal(SpecialEventScript, Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __int64 (*FlowStep_SetPhaseToActiveOriginal)(AActor* SpecialEventPhase);
|
||||||
|
|
||||||
|
__int64 FlowStep_SetPhaseToActiveHook(AActor* SpecialEventPhase)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "FlowStep_SetPhaseToActiveHook!");
|
||||||
|
|
||||||
|
auto ret = FlowStep_SetPhaseToActiveOriginal(SpecialEventPhase); // idk if three actually is a ret
|
||||||
|
|
||||||
|
static auto OnRep_PhaseState = FindObject<UFunction>("/Script/SpecialEventGameplayRuntime.SpecialEventPhase.OnRep_PhaseState");
|
||||||
|
SpecialEventPhase->ProcessEvent(OnRep_PhaseState);
|
||||||
|
|
||||||
|
SpecialEventPhase->ForceNetUpdate();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD WINAPI Main(LPVOID)
|
DWORD WINAPI Main(LPVOID)
|
||||||
{
|
{
|
||||||
InitLogger();
|
InitLogger();
|
||||||
@@ -179,6 +246,7 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
static auto GameModeDefault = FindObject<AFortGameModeAthena>(L"/Script/FortniteGame.Default__FortGameModeAthena");
|
static auto GameModeDefault = FindObject<AFortGameModeAthena>(L"/Script/FortniteGame.Default__FortGameModeAthena");
|
||||||
static auto FortPlayerControllerZoneDefault = FindObject<AFortPlayerController>(L"/Script/FortniteGame.Default__FortPlayerControllerZone");
|
static auto FortPlayerControllerZoneDefault = FindObject<AFortPlayerController>(L"/Script/FortniteGame.Default__FortPlayerControllerZone");
|
||||||
|
static auto FortPlayerControllerDefault = FindObject<AFortPlayerController>(L"/Script/FortniteGame.Default__FortPlayerController");
|
||||||
static auto FortPlayerControllerAthenaDefault = FindObject<AFortPlayerControllerAthena>(L"/Script/FortniteGame.Default__FortPlayerControllerAthena"); // FindObject<UClass>(L"/Game/Athena/Athena_PlayerController.Default__Athena_PlayerController_C");
|
static auto FortPlayerControllerAthenaDefault = FindObject<AFortPlayerControllerAthena>(L"/Script/FortniteGame.Default__FortPlayerControllerAthena"); // FindObject<UClass>(L"/Game/Athena/Athena_PlayerController.Default__Athena_PlayerController_C");
|
||||||
static auto FortPlayerPawnAthenaDefault = FindObject<AFortPlayerPawn>(L"/Script/FortniteGame.Default__FortPlayerPawnAthena"); // FindObject<AFortPlayerPawn>(L"/Game/Athena/PlayerPawn_Athena.Default__PlayerPawn_Athena_C");
|
static auto FortPlayerPawnAthenaDefault = FindObject<AFortPlayerPawn>(L"/Script/FortniteGame.Default__FortPlayerPawnAthena"); // FindObject<AFortPlayerPawn>(L"/Game/Athena/PlayerPawn_Athena.Default__PlayerPawn_Athena_C");
|
||||||
static auto FortAbilitySystemComponentAthenaDefault = FindObject<UObject>(L"/Script/FortniteGame.Default__FortAbilitySystemComponentAthena");
|
static auto FortAbilitySystemComponentAthenaDefault = FindObject<UObject>(L"/Script/FortniteGame.Default__FortAbilitySystemComponentAthena");
|
||||||
@@ -196,10 +264,14 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortUIDirector NoLogging", nullptr);
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortUIDirector NoLogging", nullptr);
|
||||||
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogAbilitySystem VeryVerbose", nullptr);
|
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogAbilitySystem VeryVerbose", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogDataTable VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogDataTable VeryVerbose", nullptr);
|
||||||
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogMeshNetwork VeryVerbose", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFort VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFort VeryVerbose", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogGameMode VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogGameMode VeryVerbose", nullptr);
|
||||||
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogSpecialEvent VeryVerbose", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogPlayerController VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogPlayerController VeryVerbose", nullptr);
|
||||||
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogSpecialEventPhase VeryVerbose", nullptr);
|
||||||
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortCustomization VeryVerbose", nullptr);
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortCustomization VeryVerbose", nullptr);
|
||||||
|
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogSpecialEventScriptMeshActor VeryVerbose", nullptr);
|
||||||
|
|
||||||
Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr);
|
Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr);
|
||||||
Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr);
|
Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr);
|
||||||
@@ -231,9 +303,27 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
FindObject<UFunction>(L"/Script/FortniteGame.BuildingFoundation.SetDynamicFoundationEnabled"),
|
FindObject<UFunction>(L"/Script/FortniteGame.BuildingFoundation.SetDynamicFoundationEnabled"),
|
||||||
ABuildingFoundation::SetDynamicFoundationEnabledHook, (PVOID*)&ABuildingFoundation::SetDynamicFoundationEnabledOriginal, false, true); */
|
ABuildingFoundation::SetDynamicFoundationEnabledHook, (PVOID*)&ABuildingFoundation::SetDynamicFoundationEnabledOriginal, false, true); */
|
||||||
|
|
||||||
|
if (Fortnite_Version == 17.30)
|
||||||
|
{
|
||||||
|
// if (false)
|
||||||
|
{
|
||||||
|
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3E07910), (PVOID)GetMeshNetworkNodeTypeHook, nullptr);
|
||||||
|
// Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DED12C), (PVOID)ReturnTrueHook, nullptr); // 7FF7E556D12C
|
||||||
|
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DED158), (PVOID)ReturnTrueHook, nullptr); // 7FF7E556D158
|
||||||
|
}
|
||||||
|
|
||||||
|
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DECFC8), (PVOID)ReturnTrueHook, nullptr); // 7FF7E556CFC8
|
||||||
|
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DED050), (PVOID)ReturnTrueHook, nullptr); // 7FF7E556D050
|
||||||
|
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DECF40), (PVOID)ReturnFalseHook, nullptr); // 7FF7E556CF40
|
||||||
|
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DE5CE8), (PVOID)ActivatePhaseAtIndexHook, (PVOID*)&ActivatePhaseAtIndexOriginal); // 7FF7E5565CE8
|
||||||
|
// Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DE9268), (PVOID)FlowStep_SetPhaseToActiveHook, (PVOID*)&FlowStep_SetPhaseToActiveOriginal); // 7FF7E5569268
|
||||||
|
// Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DE5998), (PVOID)SpecialEventScript_ActivatePhaseHook, (PVOID*)&SpecialEventScript_ActivatePhaseOriginal); // 7FF7E5565998
|
||||||
|
}
|
||||||
|
|
||||||
if (bUseSwitchLevel)
|
if (bUseSwitchLevel)
|
||||||
{
|
{
|
||||||
static auto SwitchLevel = FindObject<UFunction>(L"/Script/Engine.PlayerController.SwitchLevel");
|
static auto SwitchLevel = FindObject<UFunction>(L"/Script/Engine.PlayerController.SwitchLevel");
|
||||||
|
|
||||||
FString Level = Engine_Version < 424
|
FString Level = Engine_Version < 424
|
||||||
? L"Athena_Terrain" : Engine_Version >= 500 ? Engine_Version >= 501
|
? L"Athena_Terrain" : Engine_Version >= 500 ? Engine_Version >= 501
|
||||||
? L"Asteria_Terrain"
|
? L"Asteria_Terrain"
|
||||||
@@ -285,13 +375,6 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
LOG_INFO(LogPlayer, "Switched level.");
|
LOG_INFO(LogPlayer, "Switched level.");
|
||||||
|
|
||||||
if (Fortnite_Version == 17.30)
|
|
||||||
{
|
|
||||||
// Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3E07910), (PVOID)Return2Hook, nullptr);
|
|
||||||
// Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DED12C), (PVOID)ReturnTrueHook, nullptr);
|
|
||||||
Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x3DED158), (PVOID)ReturnTrueHook, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bUseSwitchLevel)
|
if (bUseSwitchLevel)
|
||||||
{
|
{
|
||||||
if (!bUseRemovePlayer)
|
if (!bUseRemovePlayer)
|
||||||
@@ -436,10 +519,15 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
nullptr, false);
|
nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// HookInstruction(Addresses::UpdateTrackedAttributesLea, (PVOID)UFortGadgetItemDefinition::UpdateTrackedAttributesHook, "/Script/FortniteGame.FortPlayerController.Suicide", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
static auto ServerReturnToMainMenuFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerReturnToMainMenu");
|
||||||
|
static auto ServerReturnToMainMenuIdx = GetFunctionIdxOrPtr(ServerReturnToMainMenuFn) / 8;
|
||||||
|
auto FortServerRestartPlayer = FortPlayerControllerDefault->VFTable[ServerReturnToMainMenuIdx];
|
||||||
|
VirtualSwap(FortPlayerControllerAthenaDefault->VFTable, ServerReturnToMainMenuIdx, FortServerRestartPlayer);
|
||||||
|
|
||||||
|
HookInstruction(Addresses::UpdateTrackedAttributesLea, (PVOID)AFortPlayerControllerAthena::UpdateTrackedAttributesHook, "/Script/Engine.PlayerController.EnableCheats", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
||||||
// HookInstruction(Addresses::CombinePickupLea, (PVOID)AFortPickup::CombinePickupHook, "/Script/Engine.PlayerController.SetVirtualJoystickVisibility", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
// HookInstruction(Addresses::CombinePickupLea, (PVOID)AFortPickup::CombinePickupHook, "/Script/Engine.PlayerController.SetVirtualJoystickVisibility", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
||||||
|
|
||||||
if (false)
|
if (bEnableRebooting)
|
||||||
{
|
{
|
||||||
HookInstruction(Addresses::RebootingDelegate, (PVOID)ABuildingGameplayActorSpawnMachine::RebootingDelegateHook, "/Script/Engine.PlayerController.SetVirtualJoystickVisibility", ERelativeOffsets::LEA, FindObject("/Script/FortniteGame.Default__BuildingGameplayActorSpawnMachine"));
|
HookInstruction(Addresses::RebootingDelegate, (PVOID)ABuildingGameplayActorSpawnMachine::RebootingDelegateHook, "/Script/Engine.PlayerController.SetVirtualJoystickVisibility", ERelativeOffsets::LEA, FindObject("/Script/FortniteGame.Default__BuildingGameplayActorSpawnMachine"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -700,7 +700,7 @@ static inline void StartEvent()
|
|||||||
|
|
||||||
if (Fortnite_Version == 17.30)
|
if (Fortnite_Version == 17.30)
|
||||||
{
|
{
|
||||||
static bool (*IsServerOrSomething)(UObject * SpecialEventScript) = decltype(IsServerOrSomething)(__int64(GetModuleHandleW(0)) + 0x3DECFC8);
|
static bool (*IsServerOrSomething)(UObject* SpecialEventScript) = decltype(IsServerOrSomething)(__int64(GetModuleHandleW(0)) + 0x3DECFC8);
|
||||||
LOG_INFO(LogDev, "IsServerOrSomething {}", IsServerOrSomething(EventScripting));
|
LOG_INFO(LogDev, "IsServerOrSomething {}", IsServerOrSomething(EventScripting));
|
||||||
|
|
||||||
static auto OnRep_RootStartTimeFn = FindObject<UFunction>("/Script/SpecialEventGameplayRuntime.SpecialEventScriptMeshActor.OnRep_RootStartTime");
|
static auto OnRep_RootStartTimeFn = FindObject<UFunction>("/Script/SpecialEventGameplayRuntime.SpecialEventScriptMeshActor.OnRep_RootStartTime");
|
||||||
@@ -714,13 +714,17 @@ static inline void StartEvent()
|
|||||||
|
|
||||||
if (SpecialEventScriptMeshActor)
|
if (SpecialEventScriptMeshActor)
|
||||||
{
|
{
|
||||||
static bool (*sub_7FF7E556D158)(UObject * MeshScriptActor) = decltype(sub_7FF7E556D158)(__int64(GetModuleHandleW(0)) + 0x3DED158);
|
static bool (*sub_7FF7E556D158)(UObject* MeshScriptActor) = decltype(sub_7FF7E556D158)(__int64(GetModuleHandleW(0)) + 0x3DED158);
|
||||||
LOG_INFO(LogDev, "sub_7FF7E556D158 {}", sub_7FF7E556D158(SpecialEventScriptMeshActor));
|
LOG_INFO(LogDev, "sub_7FF7E556D158 {}", sub_7FF7E556D158(SpecialEventScriptMeshActor));
|
||||||
|
|
||||||
|
// if (false)
|
||||||
|
{
|
||||||
SpecialEventScriptMeshActor->ProcessEvent(MeshRootStartEventFn);
|
SpecialEventScriptMeshActor->ProcessEvent(MeshRootStartEventFn);
|
||||||
SpecialEventScriptMeshActor->ProcessEvent(OnRep_RootStartTimeFn);
|
SpecialEventScriptMeshActor->ProcessEvent(OnRep_RootStartTimeFn);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_ERROR(LogEvent, "Failed to find SpecialEventScriptMeshActor");
|
LOG_ERROR(LogEvent, "Failed to find SpecialEventScriptMeshActor");
|
||||||
|
|||||||
@@ -186,9 +186,20 @@ static inline uint64 FindFinishResurrection()
|
|||||||
|
|
||||||
static inline uint64 FindGetSquadIdForCurrentPlayer()
|
static inline uint64 FindGetSquadIdForCurrentPlayer()
|
||||||
{
|
{
|
||||||
auto addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 40 48 8D 99 ? ? ? ? 48 8B FA 4C 8B C2 48 8B CB").Get();
|
auto Addrr = Memcury::Scanner::FindStringRef(L"GetSquadIdForCurrentPlayer failed to find a squad id for player %s").Get();
|
||||||
|
|
||||||
return addr;
|
if (!Addrr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2000; i++)
|
||||||
|
{
|
||||||
|
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0x5C)
|
||||||
|
{
|
||||||
|
return Addrr - i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint64 FindRebootingDelegate()
|
static inline uint64 FindRebootingDelegate()
|
||||||
@@ -196,7 +207,21 @@ static inline uint64 FindRebootingDelegate()
|
|||||||
if (Fortnite_Version < 8.3)
|
if (Fortnite_Version < 8.3)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto addr = Memcury::Scanner::FindPattern("48 8D 05 ? ? ? ? 33 F6 48 89 44 24 ? 49 8B CE 49 8B 06 89 74 24 60 FF 90 ? ? ? ? 4C 8B A4 24 ? ? ? ? 48 8B 88 ? ? ? ? 48 85 C9").Get();
|
auto ServerOnAttemptInteractAddr = Memcury::Scanner::FindStringRef(L"[SCM] ABuildingGameplayActorSpawnMachine::ServerOnAttemptInteract - Start Rebooting").Get();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10000; i++)
|
||||||
|
{
|
||||||
|
if ((*(uint8_t*)(uint8_t*)(ServerOnAttemptInteractAddr + i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerOnAttemptInteractAddr + i + 1) == 0x8D
|
||||||
|
&& *(uint8_t*)(uint8_t*)(ServerOnAttemptInteractAddr + i + 2) == 0x05))
|
||||||
|
{
|
||||||
|
auto loadAddress = Memcury::Scanner(ServerOnAttemptInteractAddr + i).RelativeOffset(3).Get();
|
||||||
|
|
||||||
|
if (IsNullSub(loadAddress)) // Safety
|
||||||
|
return ServerOnAttemptInteractAddr + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto addr = 0; // Memcury::Scanner::FindPattern("48 8D 05 ? ? ? ? 33 F6 48 89 44 24 ? 49 8B CE 49 8B 06 89 74 24 60 FF 90 ? ? ? ? 4C 8B A4 24 ? ? ? ? 48 8B 88 ? ? ? ? 48 85 C9").Get();
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
@@ -231,6 +256,8 @@ static inline uint64 FindCreateNetDriver()
|
|||||||
|
|
||||||
static inline uint64 FindLoadAsset()
|
static inline uint64 FindLoadAsset()
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
|
|
||||||
auto Addrr = Memcury::Scanner::FindStringRef(L"Loaded delay-load asset %s").Get();
|
auto Addrr = Memcury::Scanner::FindStringRef(L"Loaded delay-load asset %s").Get();
|
||||||
|
|
||||||
for (int i = 0; i < 2000; i++)
|
for (int i = 0; i < 2000; i++)
|
||||||
@@ -687,7 +714,7 @@ static inline uint64 FindUpdateTrackedAttributesLea() // kill me
|
|||||||
|
|
||||||
// So we keep going until we find a lea with nullsub..
|
// So we keep going until we find a lea with nullsub..
|
||||||
|
|
||||||
uint64 ApplyGadgetAttributesAddr = 0;
|
uint64 ApplyGadgetAttributesAddr = Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 55 41 54 41 55 41 57 48 8D 6C 24").Get();
|
||||||
|
|
||||||
if (!ApplyGadgetAttributesAddr)
|
if (!ApplyGadgetAttributesAddr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace Globals
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern inline std::string PlaylistName =
|
extern inline std::string PlaylistName =
|
||||||
// "/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo";
|
"/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo";
|
||||||
// "/Game/Athena/Playlists/gg/Playlist_Gg_Reverse.Playlist_Gg_Reverse";
|
// "/Game/Athena/Playlists/gg/Playlist_Gg_Reverse.Playlist_Gg_Reverse";
|
||||||
"/Game/Athena/Playlists/Playlist_DefaultDuo.Playlist_DefaultDuo";
|
// "/Game/Athena/Playlists/Playlist_DefaultDuo.Playlist_DefaultDuo";
|
||||||
// "/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground";
|
// "/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground";
|
||||||
// "/Game/Athena/Playlists/Carmine/Playlist_Carmine.Playlist_Carmine";
|
// "/Game/Athena/Playlists/Carmine/Playlist_Carmine.Playlist_Carmine";
|
||||||
// "/Game/Athena/Playlists/Fill/Playlist_Fill_Solo.Playlist_Fill_Solo";
|
// "/Game/Athena/Playlists/Fill/Playlist_Fill_Solo.Playlist_Fill_Solo";
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ static inline void StaticUI()
|
|||||||
|
|
||||||
#ifndef PROD
|
#ifndef PROD
|
||||||
ImGui::Checkbox("Log ProcessEvent", &Globals::bLogProcessEvent);
|
ImGui::Checkbox("Log ProcessEvent", &Globals::bLogProcessEvent);
|
||||||
ImGui::InputInt("Amount of bots to spawn", &AmountOfBotsToSpawn);
|
// ImGui::InputInt("Amount of bots to spawn", &AmountOfBotsToSpawn);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ImGui::Checkbox("Infinite Ammo", &Globals::bInfiniteAmmo);
|
ImGui::Checkbox("Infinite Ammo", &Globals::bInfiniteAmmo);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
UObject* Assets::LoadAsset(FName Name, bool ShowDelayTimes)
|
UObject* Assets::LoadAsset(FName Name, bool ShowDelayTimes)
|
||||||
{
|
{
|
||||||
static UObject* (*LoadAssetOriginal)(FName a1, bool a2);
|
static UObject* (*LoadAssetOriginal)(FName a1, bool a2) = decltype(LoadAssetOriginal)(Assets::LoadAsset);
|
||||||
|
|
||||||
return LoadAssetOriginal(Name, ShowDelayTimes);
|
return LoadAssetOriginal(Name, ShowDelayTimes);
|
||||||
}
|
}
|
||||||
|
|||||||
7
vendor/memcury.h
vendored
7
vendor/memcury.h
vendored
@@ -1417,7 +1417,12 @@
|
|||||||
// Finds a string ref, then goes searches xref of the function that it's in and returns that address.
|
// Finds a string ref, then goes searches xref of the function that it's in and returns that address.
|
||||||
inline uintptr_t FindFunctionCall(const wchar_t* Name, const std::vector<uint8_t>& Bytes = std::vector<uint8_t>{ 0x48, 0x89, 0x5C }, int skip = 0) // credit ender & me
|
inline uintptr_t FindFunctionCall(const wchar_t* Name, const std::vector<uint8_t>& Bytes = std::vector<uint8_t>{ 0x48, 0x89, 0x5C }, int skip = 0) // credit ender & me
|
||||||
{
|
{
|
||||||
auto FunctionPtr = Memcury::Scanner::FindStringRef(Name, true, skip).ScanFor({ 0x48, 0x8D, 0x0D }).RelativeOffset(3).GetAs<void*>();
|
auto StringRef = Memcury::Scanner::FindStringRef(Name, true, skip);
|
||||||
|
|
||||||
|
if (!StringRef.Get())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
auto FunctionPtr = StringRef.ScanFor({ 0x48, 0x8D, 0x0D }).RelativeOffset(3).GetAs<void*>();
|
||||||
|
|
||||||
auto PtrRef = Memcury::Scanner::FindPointerRef(FunctionPtr);
|
auto PtrRef = Memcury::Scanner::FindPointerRef(FunctionPtr);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user