mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
a good update
Added a very useful debugging tool, made looting even more proper
This commit is contained in:
@@ -43,7 +43,7 @@ static inline void SpawnBGAs() // hahah not "proper", there's a function that we
|
||||
static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup");
|
||||
auto& SpawnLootTierGroup = BGAConsumableSpawner->Get<FName>(SpawnLootTierGroupOffset);
|
||||
|
||||
auto LootDrops = PickLootDrops(SpawnLootTierGroup);
|
||||
auto LootDrops = PickLootDrops(SpawnLootTierGroup, GameState->GetWorldLevel());
|
||||
|
||||
for (int z = 0; z < LootDrops.size(); z++)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
||||
{
|
||||
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
FVector LocationToSpawnLoot = this->GetActorLocation() + this->GetActorRightVector() * 70.f + FVector{ 0, 0, 50 };
|
||||
|
||||
static auto SearchLootTierGroupOffset = this->GetOffset("SearchLootTierGroup");
|
||||
@@ -14,18 +16,16 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
||||
|
||||
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
|
||||
|
||||
auto LootDrops = PickLootDrops(RedirectedLootTier, -1, bDebugPrintLooting);
|
||||
auto LootDrops = PickLootDrops(RedirectedLootTier, GameState->GetWorldLevel(), -1, bDebugPrintLooting);
|
||||
|
||||
// LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
|
||||
|
||||
for (int i = 0; i < LootDrops.size(); i++)
|
||||
for (auto& LootDrop : LootDrops)
|
||||
{
|
||||
auto& lootDrop = LootDrops.at(i);
|
||||
|
||||
PickupCreateData CreateData{};
|
||||
CreateData.bToss = true;
|
||||
// CreateData.PawnOwner = Pawn;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(lootDrop->GetItemDefinition(), lootDrop->GetCount(), lootDrop->GetLoadedAmmo());
|
||||
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||
CreateData.SpawnLocation = LocationToSpawnLoot;
|
||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetContainerValue();
|
||||
CreateData.bRandomRotation = true;
|
||||
@@ -34,5 +34,17 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
||||
auto NewPickup = AFortPickup::SpawnPickup(CreateData);
|
||||
}
|
||||
|
||||
static auto SearchAnimationCountOffset = FindOffsetStruct("/Script/FortniteGame.FortSearchBounceData", "SearchAnimationCount");
|
||||
static auto SearchBounceDataOffset = this->GetOffset("SearchBounceData");
|
||||
|
||||
auto SearchBounceData = this->GetPtr<void>(SearchBounceDataOffset);
|
||||
|
||||
(*(int*)(__int64(SearchBounceData) + SearchAnimationCountOffset))++;
|
||||
|
||||
static auto OnRep_bAlreadySearchedFn = FindObject<UFunction>(L"/Script/FortniteGame.BuildingContainer.OnRep_bAlreadySearched");
|
||||
this->ProcessEvent(OnRep_bAlreadySearchedFn);
|
||||
|
||||
// Now there is some function called here but idk what it is, it calls OnLoot though.
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Object.h"
|
||||
#include "reboot.h"
|
||||
|
||||
#include "Map.h"
|
||||
|
||||
struct FTableRowBase
|
||||
{
|
||||
unsigned char UnknownData00[0x8]; // this is actually structural padding
|
||||
};
|
||||
|
||||
class UDataTable : public UObject
|
||||
{
|
||||
public:
|
||||
@@ -40,4 +46,63 @@ struct FDataTableCategoryHandle
|
||||
UDataTable* DataTable; // 0x0000(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
FName ColumnName; // 0x0008(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
FName RowContents; // 0x0010(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
|
||||
template <class T>
|
||||
void GetRows(std::vector<T*>& OutRows, const FString& ContextString) const
|
||||
{
|
||||
OutRows.clear();
|
||||
|
||||
if (DataTable == nullptr)
|
||||
{
|
||||
if (RowContents.ComparisonIndex.Value != 0)
|
||||
{
|
||||
// UE_LOG(LogDataTable, Warning, TEXT("FDataTableCategoryHandle::FindRow : No DataTable for row %s (%s)."), *RowContents.ToString(), *ContextString);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (ColumnName.ComparisonIndex.Value == 0)
|
||||
{
|
||||
if (RowContents.ComparisonIndex.Value != 0)
|
||||
{
|
||||
// UE_LOG(LogDataTable, Warning, TEXT("FDataTableCategoryHandle::FindRow : No Column selected for row %s (%s)."), *RowContents.ToString(), *ContextString);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
// unreal trippin
|
||||
|
||||
/*
|
||||
// Find the property that matches the desired column (ColumnName)
|
||||
UProperty* Property = DataTable->FindTableProperty(ColumnName);
|
||||
if (Property == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// check each row to see if the value in the Property element is the one we're looking for (RowContents). If it is, add the row to OutRows
|
||||
FString RowContentsAsString = RowContents.ToString();
|
||||
|
||||
for (auto RowIt = DataTable->RowMap.CreateConstIterator(); RowIt; ++RowIt)
|
||||
{
|
||||
uint8* RowData = RowIt.Value();
|
||||
|
||||
FString PropertyValue(TEXT(""));
|
||||
|
||||
Property->ExportText_InContainer(0, PropertyValue, RowData, RowData, nullptr, PPF_None);
|
||||
|
||||
if (RowContentsAsString == PropertyValue)
|
||||
{
|
||||
OutRows.Add((T*)RowData);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -6,18 +6,49 @@
|
||||
#include "FortWorldItemDefinition.h"
|
||||
#include "FortInventory.h"
|
||||
|
||||
enum class ERespawnRequirements : uint8_t
|
||||
{
|
||||
RespawnOnly = 0,
|
||||
NoRespawnOnly = 1,
|
||||
Both = 2,
|
||||
ERespawnRequirements_MAX = 3
|
||||
};
|
||||
|
||||
struct FItemsToDropOnDeath
|
||||
{
|
||||
UFortWorldItemDefinition* ItemToDrop; // 0x0000(0x0008) (Edit, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
FScalableFloat NumberToDrop; // 0x0008(0x0020) (Edit, NativeAccessSpecifierPublic)
|
||||
static UStruct* GetStruct()
|
||||
{
|
||||
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.ItemsToDropOnDeath");
|
||||
return Struct;
|
||||
}
|
||||
|
||||
static int GetStructSize() { return GetStruct()->GetPropertiesSize(); }
|
||||
|
||||
UFortWorldItemDefinition*& GetItemToDrop()
|
||||
{
|
||||
static auto ItemToDropOffset = FindOffsetStruct("/Script/FortniteGame.ItemsToDropOnDeath", "ItemToDrop");
|
||||
return *(UFortWorldItemDefinition**)(__int64(this) + ItemToDropOffset);
|
||||
}
|
||||
|
||||
FScalableFloat* GetNumberToDrop()
|
||||
{
|
||||
static auto NumberToDropOffset = FindOffsetStruct("/Script/FortniteGame.ItemsToDropOnDeath", "NumberToDrop");
|
||||
return (FScalableFloat*)(__int64(this) + NumberToDropOffset);
|
||||
}
|
||||
};
|
||||
|
||||
class AFortAthenaMutator_ItemDropOnDeath : public AFortAthenaMutator
|
||||
{
|
||||
public:
|
||||
ERespawnRequirements/*&*/ GetRespawnRequirements()
|
||||
{
|
||||
static auto RespawnRequirementsOffset = GetOffset("RespawnRequirements");
|
||||
return Get<ERespawnRequirements>(RespawnRequirementsOffset);
|
||||
}
|
||||
|
||||
TArray<FItemsToDropOnDeath>& GetItemsToDrop()
|
||||
{
|
||||
static auto ItemsToDropOffset = GetOffset("ItemsToDrop");
|
||||
return Get<TArray<FItemsToDropOnDeath>>(ItemsToDropoOffset);
|
||||
return Get<TArray<FItemsToDropOnDeath>>(ItemsToDropOffset);
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "FortGameMode.h"
|
||||
|
||||
void AFortGameMode::SetCurrentPlaylistName(UObject* Playlist) // Techinally it takes in a fname
|
||||
void AFortGameMode::SetCurrentPlaylistName(UFortPlaylist* Playlist) // Techinally it takes in a fname
|
||||
{
|
||||
if (!Playlist)
|
||||
{
|
||||
@@ -9,11 +9,10 @@ void AFortGameMode::SetCurrentPlaylistName(UObject* Playlist) // Techinally it t
|
||||
}
|
||||
|
||||
static auto PlaylistNameOffset = Playlist->GetOffset("PlaylistName");
|
||||
static auto PlaylistIdOffset = Playlist->GetOffset("PlaylistId");
|
||||
|
||||
static auto CurrentPlaylistNameOffset = GetOffset("CurrentPlaylistName");
|
||||
static auto CurrentPlaylistIdOffset = GetOffset("CurrentPlaylistId");
|
||||
|
||||
Get<FName>(CurrentPlaylistNameOffset) = Playlist->Get<FName>(PlaylistNameOffset);
|
||||
Get<int>(CurrentPlaylistIdOffset) = Playlist->Get<int>(PlaylistIdOffset);
|
||||
Get<int>(CurrentPlaylistIdOffset) = Playlist->GetPlaylistId();
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "GameMode.h"
|
||||
#include "FortPlaylist.h"
|
||||
|
||||
class AFortGameMode : public AGameMode
|
||||
{
|
||||
public:
|
||||
void SetCurrentPlaylistName(UObject* Playlist); // Techinally it takes in a fname
|
||||
void SetCurrentPlaylistName(UFortPlaylist* Playlist); // Techinally it takes in a fname
|
||||
};
|
||||
@@ -161,21 +161,12 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
(*(int*)(__int64(CurrentPlaylistInfo) + PlaylistReplicationKeyOffset))++;
|
||||
CurrentPlaylistInfo->MarkArrayDirty();
|
||||
|
||||
auto aeuh = *(UObject**)(__int64(CurrentPlaylistInfo) + BasePlaylistOffset);
|
||||
auto currentBasePlaylist = *(UFortPlaylist**)(__int64(CurrentPlaylistInfo) + BasePlaylistOffset);
|
||||
|
||||
if (aeuh)
|
||||
if (currentBasePlaylist)
|
||||
{
|
||||
GameMode->SetCurrentPlaylistName(aeuh);
|
||||
|
||||
/* if (Fortnite_Version >= 13)
|
||||
{
|
||||
static auto LastSafeZoneIndexOffset = aeuh->GetOffset("LastSafeZoneIndex");
|
||||
|
||||
if (LastSafeZoneIndexOffset != -1)
|
||||
{
|
||||
*(int*)(__int64(aeuh) + LastSafeZoneIndexOffset) = 0;
|
||||
}
|
||||
} */
|
||||
GameMode->SetCurrentPlaylistName(currentBasePlaylist);
|
||||
GameState->SetPlaylistId(currentBasePlaylist);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -183,7 +174,15 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
|
||||
|
||||
if (CurrentPlaylistDataOffset != -1)
|
||||
{
|
||||
GameState->Get(CurrentPlaylistDataOffset) = Playlist;
|
||||
|
||||
if (GameState->Get(CurrentPlaylistDataOffset))
|
||||
{
|
||||
GameMode->SetCurrentPlaylistName(GameState->Get<UFortPlaylist*>(CurrentPlaylistDataOffset));
|
||||
GameState->SetPlaylistId(GameState->Get<UFortPlaylist*>(CurrentPlaylistDataOffset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bOnRep)
|
||||
@@ -550,13 +549,23 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
LastNum3 = AmountOfRestarts;
|
||||
++Globals::AmountOfListens;
|
||||
|
||||
LOG_INFO(LogNet, "Attempting to listen!");
|
||||
// LOG_INFO(LogNet, "Attempting to listen!");
|
||||
|
||||
GetWorld()->Listen();
|
||||
|
||||
LOG_INFO(LogDev, "WorldLevel: {}", GameState->GetWorldLevel());
|
||||
|
||||
SetupAIDirector();
|
||||
SetupServerBotManager();
|
||||
|
||||
bool bPrintCommonObjectPaths = true;
|
||||
|
||||
if (bPrintCommonObjectPaths)
|
||||
{
|
||||
LOG_INFO(LogGame, "GameState PathName: {}", GetWorld()->GetGameState()->GetPathName());
|
||||
LOG_INFO(LogGame, "GameMode PathName: {}", GetWorld()->GetGameMode()->GetPathName());
|
||||
}
|
||||
|
||||
if (AmountOfBotsToSpawn != 0)
|
||||
{
|
||||
Bots::SpawnBotsAtPlayerStarts(AmountOfBotsToSpawn);
|
||||
@@ -968,13 +977,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
||||
auto Location = CurrentActor->GetActorLocation();
|
||||
Location.Z += UpZ;
|
||||
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, -1, bPrintWarmup);
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, GameState->GetWorldLevel(), -1, bPrintWarmup);
|
||||
|
||||
for (auto& LootDrop : LootDrops)
|
||||
{
|
||||
PickupCreateData CreateData;
|
||||
CreateData.bToss = true;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
||||
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||
CreateData.SpawnLocation = Location;
|
||||
CreateData.SourceType = SpawnFlag;
|
||||
CreateData.bRandomRotation = true;
|
||||
@@ -998,13 +1007,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
||||
auto Location = CurrentActor->GetActorLocation();
|
||||
Location.Z += UpZ;
|
||||
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, -1, bPrint);
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, GameState->GetWorldLevel(), -1, bPrint);
|
||||
|
||||
for (auto& LootDrop : LootDrops)
|
||||
{
|
||||
PickupCreateData CreateData;
|
||||
CreateData.bToss = true;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
||||
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||
CreateData.SpawnLocation = Location;
|
||||
CreateData.SourceType = SpawnFlag;
|
||||
CreateData.bRandomRotation = true;
|
||||
|
||||
@@ -81,7 +81,7 @@ static void SetFoundationTransform(AActor* BuildingFoundation, const FTransform&
|
||||
|
||||
static inline UFortAbilitySet* GetPlayerAbilitySet()
|
||||
{
|
||||
// There are some variables that contain this but it changes through versions soo..
|
||||
// There are some variables that contain this but it changes through versions soo.. // GenericPlayerAbilitySet and PlayerAbilitySetBR
|
||||
|
||||
static auto GameplayAbilitySet = (UFortAbilitySet*)(Fortnite_Version >= 8.30
|
||||
? LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer", UFortAbilitySet::StaticClass())
|
||||
|
||||
@@ -80,6 +80,12 @@ UFortPlaylist*& AFortGameStateAthena::GetCurrentPlaylist()
|
||||
return *(UFortPlaylist**)(__int64(CurrentPlaylistInfo) + BasePlaylistOffset);
|
||||
}
|
||||
|
||||
void AFortGameStateAthena::SetPlaylistId(UFortPlaylist* Playlist)
|
||||
{
|
||||
static auto CurrentPlaylistIdOffset = GetOffset("CurrentPlaylistId");
|
||||
this->Get<int>(CurrentPlaylistIdOffset) = Playlist->GetPlaylistId();
|
||||
}
|
||||
|
||||
int AFortGameStateAthena::GetAircraftIndex(AFortPlayerState* PlayerState)
|
||||
{
|
||||
// The function has a string in it but we can just remake lol
|
||||
|
||||
@@ -68,6 +68,12 @@ public:
|
||||
return Get<EAthenaGamePhase>(GamePhaseOffset);
|
||||
}
|
||||
|
||||
int& GetWorldLevel() // Actually in AFortGameState
|
||||
{
|
||||
static auto WorldLevelOffset = GetOffset("WorldLevel");
|
||||
return Get<int>(WorldLevelOffset);
|
||||
}
|
||||
|
||||
UBuildingStructuralSupportSystem* GetStructuralSupportSystem() // actually in FortGameModeZone
|
||||
{
|
||||
static auto StructuralSupportSystemOffset = GetOffset("StructuralSupportSystem");
|
||||
@@ -99,6 +105,7 @@ public:
|
||||
|
||||
// void AddPlayerStateToGameMemberInfo(class AFortPlayerStateAthena* PlayerState);
|
||||
|
||||
void SetPlaylistId(UFortPlaylist* Playlist);
|
||||
int GetAircraftIndex(AFortPlayerState* PlayerState);
|
||||
bool IsRespawningAllowed(AFortPlayerState* PlayerState); // actually in zone
|
||||
bool IsPlayerBuildableClass(UClass* Class);
|
||||
|
||||
@@ -25,7 +25,7 @@ void FFortItemEntry::SetStateValue(EFortItemEntryState StateType, int IntValue)
|
||||
// ItemEntry->bIsDirty = true;
|
||||
}
|
||||
|
||||
FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability)
|
||||
FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability, int Level)
|
||||
{
|
||||
auto Entry = Alloc<FFortItemEntry>(GetStructSize(), bUseFMemoryRealloc);
|
||||
|
||||
@@ -40,7 +40,7 @@ FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinitio
|
||||
LoadedAmmo = 0;
|
||||
}
|
||||
|
||||
Entry->MostRecentArrayReplicationKey = -1; // idk if we need to set this
|
||||
Entry->MostRecentArrayReplicationKey = -1; // idk if we need to set this one
|
||||
Entry->ReplicationID = -1;
|
||||
Entry->ReplicationKey = -1;
|
||||
|
||||
@@ -50,6 +50,7 @@ FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinitio
|
||||
Entry->GetDurability() = Durability;
|
||||
Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1);
|
||||
Entry->GetParentInventory().ObjectIndex = -1;
|
||||
Entry->GetLevel() = Level;
|
||||
// We want to add StateValues.Add(DurabilityInitialized); orwnatefc erwgearf yk
|
||||
// CoCreateGuid((GUID*)&Entry->GetItemGuid());
|
||||
// Entry->DoesUpdateStatsOnCollection() = true; // I think fortnite does this?
|
||||
|
||||
@@ -143,18 +143,12 @@ struct FFortItemEntry : FFastArraySerializerItem
|
||||
|
||||
FGuid OldGuid = this->GetItemGuid();
|
||||
|
||||
if (false)
|
||||
{
|
||||
CopyStruct(this, OtherItemEntry, FFortItemEntry::GetStructSize(), FFortItemEntry::GetStruct());
|
||||
}
|
||||
else
|
||||
{
|
||||
this->GetItemDefinition() = OtherItemEntry->GetItemDefinition();
|
||||
this->GetCount() = OtherItemEntry->GetCount();
|
||||
this->GetItemDefinition() = OtherItemEntry->GetItemDefinition();
|
||||
this->GetDurability() = OtherItemEntry->GetDurability();
|
||||
this->GetLevel() = OtherItemEntry->GetLevel();
|
||||
this->GetLoadedAmmo() = OtherItemEntry->GetLoadedAmmo();
|
||||
this->GetItemGuid() = OtherItemEntry->GetItemGuid();
|
||||
this->GetLevel() = OtherItemEntry->GetLevel();
|
||||
}
|
||||
|
||||
if (!bCopyGuid)
|
||||
this->GetItemGuid() = OldGuid;
|
||||
@@ -189,7 +183,7 @@ struct FFortItemEntry : FFastArraySerializerItem
|
||||
return StructSize;
|
||||
}
|
||||
|
||||
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000);
|
||||
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000, int Level = 0);
|
||||
|
||||
// We need to find a better way for below... Especially since we can't do either method for season 5 or 6.
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "FortPickup.h"
|
||||
#include "FortLootPackage.h"
|
||||
#include "AbilitySystemComponent.h"
|
||||
#include "FortGameStateAthena.h"
|
||||
|
||||
UFortResourceItemDefinition* UFortKismetLibrary::K2_GetResourceItemDefinition(EFortResourceType ResourceType)
|
||||
{
|
||||
@@ -601,13 +602,15 @@ bool UFortKismetLibrary::PickLootDropsHook(UObject* Context, FFrame& Stack, bool
|
||||
|
||||
LOG_INFO(LogDev, "Picking loot for {}.", TierGroupName.ComparisonIndex.Value ? TierGroupName.ToString() : "InvalidName");
|
||||
|
||||
auto LootDrops = PickLootDrops(TierGroupName, -1, true);
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
auto LootDrops = PickLootDrops(TierGroupName, GameState->GetWorldLevel(), -1, true);
|
||||
|
||||
for (int i = 0; i < LootDrops.size(); i++)
|
||||
{
|
||||
auto& LootDrop = LootDrops.at(i);
|
||||
|
||||
auto NewEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
||||
auto NewEntry = LootDrop.ItemEntry;
|
||||
|
||||
OutLootToDrop.AddPtr(NewEntry, FFortItemEntry::GetStructSize());
|
||||
}
|
||||
|
||||
71
Project Reboot 3.0/FortLootLevel.cpp
Normal file
71
Project Reboot 3.0/FortLootLevel.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "FortLootLevel.h"
|
||||
#include "FortWorldItemDefinition.h"
|
||||
|
||||
int UFortLootLevel::GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel)
|
||||
{
|
||||
// OMG IM GONNA DIE
|
||||
|
||||
// we should use GetRows but L
|
||||
|
||||
auto DataTable = LootLevelData.DataTable;
|
||||
|
||||
if (!DataTable)
|
||||
return 0;
|
||||
|
||||
if (!LootLevelData.ColumnName.ComparisonIndex.Value)
|
||||
return 0;
|
||||
|
||||
if (!LootLevelData.RowContents.ComparisonIndex.Value)
|
||||
return 0;
|
||||
|
||||
std::vector<FFortLootLevelData*> OurLootLevelDatas;
|
||||
|
||||
for (auto& LootLevelDataPair : LootLevelData.DataTable->GetRowMap<FFortLootLevelData>())
|
||||
{
|
||||
if (LootLevelDataPair.Second->Category != LootLevelData.RowContents)
|
||||
continue;
|
||||
|
||||
OurLootLevelDatas.push_back(LootLevelDataPair.Second);
|
||||
}
|
||||
|
||||
if (OurLootLevelDatas.size() > 0)
|
||||
{
|
||||
int PickedIndex = -1;
|
||||
int PickedLootLevel = 0;
|
||||
|
||||
for (int i = 0; i < OurLootLevelDatas.size(); i++)
|
||||
{
|
||||
auto CurrentLootLevelData = OurLootLevelDatas.at(i);
|
||||
|
||||
if (CurrentLootLevelData->LootLevel <= WorldLevel && CurrentLootLevelData->LootLevel > PickedLootLevel)
|
||||
{
|
||||
PickedLootLevel = CurrentLootLevelData->LootLevel;
|
||||
PickedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (PickedIndex != -1)
|
||||
{
|
||||
auto PickedLootLevelData = OurLootLevelDatas.at(PickedIndex);
|
||||
|
||||
const auto PickedMinItemLevel = PickedLootLevelData->MinItemLevel;
|
||||
const auto PickedMaxItemLevel = PickedLootLevelData->MaxItemLevel;
|
||||
auto v15 = PickedMaxItemLevel - PickedMinItemLevel;
|
||||
|
||||
if (v15 + 1 <= 0)
|
||||
{
|
||||
v15 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v16 = (int)(float)((float)((float)rand() * 0.000030518509) * (float)(v15 + 1));
|
||||
if (v16 <= v15)
|
||||
v15 = v16;
|
||||
}
|
||||
|
||||
return v15 + PickedMinItemLevel;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
class UFortLootLevel
|
||||
{
|
||||
int GetItemLevel(FDataTableCategoryHandle LootLevelData, int WorldLevel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public:
|
||||
static int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel);
|
||||
};
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "UObjectArray.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "FortGameModeAthena.h"
|
||||
#include "FortLootLevel.h"
|
||||
|
||||
struct FFortGameFeatureLootTableData
|
||||
{
|
||||
@@ -51,11 +52,6 @@ void CollectDataTablesRows(std::vector<UDataTable*> DataTables, std::map<FName,
|
||||
}
|
||||
}
|
||||
|
||||
int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops)
|
||||
{
|
||||
if (LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryWeightArray().Num()
|
||||
@@ -183,7 +179,7 @@ FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& LTDTables, F
|
||||
return ChosenRowLootTierData;
|
||||
}
|
||||
|
||||
void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, const FName& LootPackageName, std::vector<LootDrop>* OutEntries, int LootPackageCategory = -1, bool bPrint = false)
|
||||
void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, const FName& LootPackageName, std::vector<LootDrop>* OutEntries, int LootPackageCategory = -1, int WorldLevel = 0, bool bPrint = false)
|
||||
{
|
||||
if (!OutEntries)
|
||||
return;
|
||||
@@ -201,14 +197,16 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
return false;
|
||||
}
|
||||
|
||||
/* if (WorldLevel >= 0)
|
||||
// todo add required tag?
|
||||
|
||||
if (WorldLevel >= 0)
|
||||
{
|
||||
if (LootPackage->MaxWorldLevel >= 0 && WorldLevel > LootPackage->MaxWorldLevel)
|
||||
if (LootPackage->GetMaxWorldLevel() >= 0 && WorldLevel > LootPackage->GetMaxWorldLevel())
|
||||
return 0;
|
||||
|
||||
if (LootPackage->MinWorldLevel >= 0 && WorldLevel < LootPackage->MinWorldLevel)
|
||||
if (LootPackage->GetMinWorldLevel() >= 0 && WorldLevel < LootPackage->GetMinWorldLevel())
|
||||
return 0;
|
||||
} */
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
@@ -242,7 +240,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
|
||||
PickLootDropsFromLootPackage(LPTables,
|
||||
PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0),
|
||||
OutEntries, LootPackageCategoryToUseForLPCall, bPrint
|
||||
OutEntries, LootPackageCategoryToUseForLPCall, WorldLevel, bPrint
|
||||
);
|
||||
|
||||
v9++;
|
||||
@@ -260,15 +258,15 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
return;
|
||||
}
|
||||
|
||||
int ItemLevel = 0;
|
||||
|
||||
auto WeaponItemDefinition = Cast<UFortWeaponItemDefinition>(ItemDefinition);
|
||||
int LoadedAmmo = WeaponItemDefinition ? WeaponItemDefinition->GetClipSize() : 0; // we shouldnt set loaded ammo here techinally
|
||||
|
||||
if (auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemDefinition))
|
||||
{
|
||||
ItemLevel = 0; // GetItemLevel(WorldItemDefinition->LootLevelData, 0);
|
||||
}
|
||||
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemDefinition);
|
||||
|
||||
if (!WorldItemDefinition) // hahahah not proper!!
|
||||
return;
|
||||
|
||||
int ItemLevel = UFortLootLevel::GetItemLevel(WorldItemDefinition->GetLootLevelData(), WorldLevel);
|
||||
|
||||
int CountMultiplier = 1;
|
||||
int FinalCount = CountMultiplier * PickedPackage->GetCount();
|
||||
@@ -282,15 +280,30 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
|
||||
while (FinalCount > 0)
|
||||
{
|
||||
int CurrentCountForEntry = PickedPackage->GetCount(); // Idk calls some itemdefinition vfunc
|
||||
int MaxStackSize = ItemDefinition->GetMaxStackSize();
|
||||
|
||||
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo)));
|
||||
int CurrentCountForEntry = MaxStackSize;
|
||||
|
||||
if (FinalCount <= MaxStackSize)
|
||||
CurrentCountForEntry = FinalCount;
|
||||
|
||||
if (CurrentCountForEntry <= 0)
|
||||
CurrentCountForEntry = 0;
|
||||
|
||||
auto ActualItemLevel = WorldItemDefinition->PickLevel(FinalItemLevel);
|
||||
|
||||
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo, 0x3F800000, ActualItemLevel)));
|
||||
|
||||
/* if (bPrint)
|
||||
{
|
||||
LOG_INFO(LogDev, "ActualItemLevel: {} FinalItemLevel: {} ItemLevel: {}", ActualItemLevel, FinalItemLevel, ItemLevel);
|
||||
} */
|
||||
|
||||
if (Engine_Version >= 424)
|
||||
{
|
||||
/*
|
||||
|
||||
Alright, so Fortnite literally doesn't reference the first loot package category for chests and floor loot (didnt check rest).
|
||||
Alright, so Fortnite literally doesn't reference the first loot package category for chests and floor loot on chapter two and above (didnt check rest).
|
||||
Usually the first loot package category in our case is ammo, so this is quite weird.
|
||||
I have no clue how Fortnite would actually add the ammo.
|
||||
|
||||
@@ -306,7 +319,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
|
||||
if (AmmoData)
|
||||
{
|
||||
int AmmoCount = AmmoData->GetDropCount(); // idk about this one
|
||||
int AmmoCount = AmmoData->GetDropCount(); // uhh???
|
||||
|
||||
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(AmmoData, AmmoCount)));
|
||||
}
|
||||
@@ -323,7 +336,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, bool bPrint, int recursive)
|
||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier, bool bPrint, int recursive)
|
||||
{
|
||||
std::vector<LootDrop> LootDrops;
|
||||
|
||||
@@ -659,7 +672,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
||||
|
||||
int LootPackageCategory = i;
|
||||
|
||||
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, bPrint);
|
||||
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, WorldLevel, bPrint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,18 @@ public:
|
||||
return *(int*)(__int64(this) + CountOffset);
|
||||
}
|
||||
|
||||
int& GetMinWorldLevel()
|
||||
{
|
||||
static auto MinWorldLevelOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "MinWorldLevel");
|
||||
return *(int*)(__int64(this) + MinWorldLevelOffset);
|
||||
}
|
||||
|
||||
int& GetMaxWorldLevel()
|
||||
{
|
||||
static auto MaxWorldLevelOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "MaxWorldLevel");
|
||||
return *(int*)(__int64(this) + MaxWorldLevelOffset);
|
||||
}
|
||||
|
||||
int& GetLootPackageCategory()
|
||||
{
|
||||
static auto LootPackageCategoryOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "LootPackageCategory");
|
||||
@@ -183,4 +195,4 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map<KeyType, ValueTy
|
||||
return ValueType();
|
||||
}
|
||||
|
||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0);
|
||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0);
|
||||
@@ -34,7 +34,7 @@ AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
|
||||
if (PickupData.Source == -1)
|
||||
PickupData.Source = 0;
|
||||
if (PickupData.SourceType == -1)
|
||||
PickupData.SourceType = -1;
|
||||
PickupData.SourceType = 0;
|
||||
|
||||
/* if (PickupData.bToss)
|
||||
{
|
||||
|
||||
@@ -430,26 +430,18 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
||||
FVector LocationToSpawnLoot = ReceivingActor->GetActorLocation() + ReceivingActor->GetActorRightVector() * 70.f + FVector{ 0, 0, 50 };
|
||||
|
||||
static auto FortAthenaVehicleClass = FindObject<UClass>(L"/Script/FortniteGame.FortAthenaVehicle");
|
||||
static auto SearchAnimationCountOffset = FindOffsetStruct("/Script/FortniteGame.FortSearchBounceData", "SearchAnimationCount");
|
||||
|
||||
if (auto BuildingContainer = Cast<ABuildingContainer>(ReceivingActor))
|
||||
{
|
||||
static auto bAlreadySearchedOffset = BuildingContainer->GetOffset("bAlreadySearched");
|
||||
static auto SearchBounceDataOffset = BuildingContainer->GetOffset("SearchBounceData");
|
||||
static auto bAlreadySearchedFieldMask = GetFieldMask(BuildingContainer->GetProperty("bAlreadySearched"));
|
||||
|
||||
auto SearchBounceData = BuildingContainer->GetPtr<void>(SearchBounceDataOffset);
|
||||
|
||||
if (BuildingContainer->ReadBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask))
|
||||
return;
|
||||
|
||||
// LOG_INFO(LogInteraction, "bAlreadySearchedFieldMask: {}", bAlreadySearchedFieldMask);
|
||||
|
||||
BuildingContainer->SetBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask, true);
|
||||
(*(int*)(__int64(SearchBounceData) + SearchAnimationCountOffset))++;
|
||||
|
||||
static auto OnRep_bAlreadySearchedFn = FindObject<UFunction>(L"/Script/FortniteGame.BuildingContainer.OnRep_bAlreadySearched");
|
||||
BuildingContainer->ProcessEvent(OnRep_bAlreadySearchedFn);
|
||||
|
||||
BuildingContainer->SpawnLoot(PlayerController->GetMyFortPawn());
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ void AFortPlayerPawn::ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup*
|
||||
|
||||
static auto bPickedUpOffset = Pickup->GetOffset("bPickedUp");
|
||||
|
||||
LOG_INFO(LogDev, "InFlyTime: {}", InFlyTime);
|
||||
// LOG_INFO(LogDev, "InFlyTime: {}", InFlyTime);
|
||||
|
||||
if (Pickup->Get<bool>(bPickedUpOffset))
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "BuildingActor.h"
|
||||
#include "FortPlayerPawnAthena.h"
|
||||
#include "GameplayAbilityTypes.h"
|
||||
#include "FortPlayerState.h"
|
||||
|
||||
struct FGameplayTagRequirements
|
||||
{
|
||||
@@ -275,6 +276,12 @@ struct FWinConditionScoreData
|
||||
class UFortPlaylist : public UObject
|
||||
{
|
||||
public:
|
||||
int& GetPlaylistId()
|
||||
{
|
||||
static auto PlaylistIdOffset = GetOffset("PlaylistId");
|
||||
return Get<int>(PlaylistIdOffset);
|
||||
}
|
||||
|
||||
TArray<TSoftObjectPtr<UFortGameplayModifierItemDefinition>>& GetModifierList()
|
||||
{
|
||||
static auto ModifierListOffset = this->GetOffset("ModifierList");
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "FortItemDefinition.h"
|
||||
#include "DataTable.h"
|
||||
|
||||
enum class EWorldItemDropBehavior : uint8_t
|
||||
{
|
||||
@@ -10,6 +11,16 @@ enum class EWorldItemDropBehavior : uint8_t
|
||||
EWorldItemDropBehavior_MAX = 3
|
||||
};
|
||||
|
||||
struct FFortLootLevelData : public FTableRowBase
|
||||
{
|
||||
public:
|
||||
FName Category; // 0x8(0x8)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
int32 LootLevel; // 0x10(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
int32 MinItemLevel; // 0x14(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
int32 MaxItemLevel; // 0x18(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
uint8 Pad_B94[0x4]; // Fixing Size Of Struct [ Dumper-7 ]
|
||||
};
|
||||
|
||||
class UFortWorldItemDefinition : public UFortItemDefinition
|
||||
{
|
||||
public:
|
||||
@@ -20,6 +31,35 @@ public:
|
||||
return ReadBitfieldValue(bCanBeDroppedOffset, bCanBeDroppedFieldMask);
|
||||
}
|
||||
|
||||
int PickLevel(int PreferredLevel) // well min level and maxlevel is sometimes in ufortowrlditemdeifnit9 then on older versions ufortitemdefinitoj so idk wher tyo put this
|
||||
{
|
||||
static auto MinLevelOffset = GetOffset("MinLevel");
|
||||
static auto MaxLevelOffset = GetOffset("MaxLevel");
|
||||
|
||||
const int MinLevel = Get<int>(MinLevelOffset);
|
||||
const int MaxLevel = Get<int>(MaxLevelOffset);
|
||||
|
||||
int PickedLevel = 0;
|
||||
|
||||
if (PreferredLevel >= MinLevel)
|
||||
PickedLevel = PreferredLevel;
|
||||
|
||||
if (MaxLevel >= 0)
|
||||
{
|
||||
if (PickedLevel <= MaxLevel)
|
||||
return PickedLevel;
|
||||
return MaxLevel;
|
||||
}
|
||||
|
||||
return PickedLevel;
|
||||
}
|
||||
|
||||
FDataTableCategoryHandle& GetLootLevelData()
|
||||
{
|
||||
static auto LootLevelDataOffset = GetOffset("LootLevelData");
|
||||
return Get<FDataTableCategoryHandle>(LootLevelDataOffset);
|
||||
}
|
||||
|
||||
int& GetDropCount()
|
||||
{
|
||||
static auto DropCountOffset = GetOffset("DropCount");
|
||||
|
||||
@@ -214,6 +214,7 @@
|
||||
<ClCompile Include="FortItem.cpp" />
|
||||
<ClCompile Include="FortItemDefinition.cpp" />
|
||||
<ClCompile Include="FortKismetLibrary.cpp" />
|
||||
<ClCompile Include="FortLootLevel.cpp" />
|
||||
<ClCompile Include="FortLootPackage.cpp" />
|
||||
<ClCompile Include="FortMinigame.cpp" />
|
||||
<ClCompile Include="FortOctopusVehicle.cpp" />
|
||||
@@ -287,6 +288,7 @@
|
||||
<ClInclude Include="Channel.h" />
|
||||
<ClInclude Include="CheatManager.h" />
|
||||
<ClInclude Include="Class.h" />
|
||||
<ClInclude Include="objectviewer.h" />
|
||||
<ClInclude Include="commands.h" />
|
||||
<ClInclude Include="ContainerAllocationPolicies.h" />
|
||||
<ClInclude Include="Controller.h" />
|
||||
|
||||
@@ -271,6 +271,9 @@
|
||||
<ClCompile Include="inc.cpp">
|
||||
<Filter>Reboot\Private</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FortLootLevel.cpp">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Private\Items</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="log.h" />
|
||||
@@ -859,6 +862,9 @@
|
||||
<ClInclude Include="inc.h">
|
||||
<Filter>Reboot\Public</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="objectviewer.h">
|
||||
<Filter>Reboot\Public</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Engine">
|
||||
|
||||
@@ -85,7 +85,7 @@ void UWorld::Listen()
|
||||
*(UNetDriver**)(__int64(LevelCollections.AtPtr(0, LevelCollectionSize)) + 0x10) = NewNetDriver;
|
||||
*(UNetDriver**)(__int64(LevelCollections.AtPtr(1, LevelCollectionSize)) + 0x10) = NewNetDriver;
|
||||
|
||||
LOG_INFO(LogNet, "Listening on port {}!", Port + Globals::AmountOfListens - 1);
|
||||
LOG_INFO(LogNet, "Listening on port {}{}!", Port + Globals::AmountOfListens - 1, Engine_Version <= 419 ? " (Wait like 10 seconds before joining though)" : "");
|
||||
}
|
||||
|
||||
AWorldSettings* UWorld::GetWorldSettings(const bool bCheckStreamingPersistent, const bool bChecked) const
|
||||
|
||||
@@ -386,6 +386,9 @@ void Offsets::FindAll()
|
||||
Engine_Version == 424 ? (Fortnite_Version >= 11.00 && Fortnite_Version <= 11.10 ? 0x57 :
|
||||
(Fortnite_Version == 11.30 || Fortnite_Version == 11.31 ? 0x59 : 0x5A)) : 0x56;
|
||||
|
||||
if (Engine_Version == 421)
|
||||
Offsets::PropertyClass = 0x70;
|
||||
|
||||
// ^ I know this makes no sense, 7.40-8.40 is 0x57, other 7-10 is 0x56, 11.00-11.10 = 0x57, 11.30-11.31 = 0x59, other S11 is 0x5A
|
||||
|
||||
else if (std::floor(Fortnite_Version) == 12 || std::floor(Fortnite_Version) == 13)
|
||||
@@ -437,18 +440,23 @@ void Offsets::FindAll()
|
||||
}
|
||||
|
||||
Offsets::IsNetRelevantFor = FindIsNetRelevantForOffset();
|
||||
Offsets::UnderlyingType = Offsets::PropertyClass;
|
||||
}
|
||||
|
||||
void Offsets::Print()
|
||||
{
|
||||
LOG_INFO(LogDev, "Offset_Internal: 0x{:x}", Offset_Internal);
|
||||
LOG_INFO(LogDev, "SuperStruct: 0x{:x}", SuperStruct);
|
||||
LOG_INFO(LogDev, "Children: 0x{:x}", Children);
|
||||
LOG_INFO(LogDev, "PropertiesSize: 0x{:x}", PropertiesSize);
|
||||
LOG_INFO(LogDev, "Func: 0x{:x}", Func);
|
||||
LOG_INFO(LogDev, "PropertiesSize: 0x{:x}", PropertiesSize);
|
||||
LOG_INFO(LogDev, "Children: 0x{:x}", Children);
|
||||
LOG_INFO(LogDev, "SuperStruct: 0x{:x}", SuperStruct);
|
||||
LOG_INFO(LogDev, "PropertyClass: 0x{:x}", PropertyClass);
|
||||
LOG_INFO(LogDev, "UnderlyingType: 0x{:x}", UnderlyingType);
|
||||
LOG_INFO(LogDev, "Offset_Internal: 0x{:x}", Offset_Internal);
|
||||
LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors);
|
||||
LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame);
|
||||
LOG_INFO(LogDev, "IsNetRelevantFor: 0x{:x}", IsNetRelevantFor);
|
||||
LOG_INFO(LogDev, "NetworkObjectList: 0x{:x}", NetworkObjectList);
|
||||
LOG_INFO(LogDev, "ClientWorldPackageName: 0x{:x}", ClientWorldPackageName);
|
||||
}
|
||||
|
||||
void Addresses::Init()
|
||||
|
||||
@@ -84,6 +84,8 @@ namespace Offsets
|
||||
extern inline uint64 PropertiesSize = 0;
|
||||
extern inline uint64 Children = 0;
|
||||
extern inline uint64 SuperStruct = 0;
|
||||
extern inline uint64 PropertyClass = 0;
|
||||
extern inline uint64 UnderlyingType = 0;
|
||||
extern inline uint64 Offset_Internal = 0;
|
||||
extern inline uint64 ServerReplicateActors = 0;
|
||||
extern inline uint64 ReplicationFrame = 0;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "builder.h"
|
||||
#include "FortLootPackage.h"
|
||||
#include "bots.h"
|
||||
#include "FortLootLevel.h"
|
||||
|
||||
bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController)
|
||||
{
|
||||
@@ -200,6 +201,12 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
||||
if (bShouldUpdate)
|
||||
WorldInventory->Update();
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
auto ItemLevel = UFortLootLevel::GetItemLevel(WID->GetLootLevelData(), GameState->GetWorldLevel());
|
||||
|
||||
LOG_INFO(LogDev, "ItemLevel: {}", ItemLevel);
|
||||
LOG_INFO(LogDev, "PickLevel: {}", WID->PickLevel(ItemLevel));
|
||||
SendMessageToConsole(PlayerController, L"Granted item!");
|
||||
}
|
||||
else if (Command == "printsimulatelootdrops")
|
||||
@@ -211,8 +218,9 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
||||
}
|
||||
|
||||
auto& lootTierGroup = Arguments[1];
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
auto LootDrops = PickLootDrops(UKismetStringLibrary::Conv_StringToName(std::wstring(lootTierGroup.begin(), lootTierGroup.end()).c_str()), -1, true);
|
||||
auto LootDrops = PickLootDrops(UKismetStringLibrary::Conv_StringToName(std::wstring(lootTierGroup.begin(), lootTierGroup.end()).c_str()), GameState->GetWorldLevel(), -1, true);
|
||||
|
||||
for (int i = 0; i < LootDrops.size(); i++)
|
||||
{
|
||||
|
||||
@@ -81,6 +81,20 @@ static __int64 DispatchRequestHook(__int64 a1, __int64* a2, int a3)
|
||||
return DispatchRequestOriginal(a1, a2, 3);
|
||||
}
|
||||
|
||||
static inline bool (*CanCreateInCurrentContextOriginal)(UObject* Template);
|
||||
|
||||
bool CanCreateInCurrentContextHook(UObject* Template)
|
||||
{
|
||||
auto Original = CanCreateInCurrentContextOriginal(Template);
|
||||
|
||||
if (!Original)
|
||||
{
|
||||
LOG_INFO(LogDev, "CanCreateInCurrentContext returned false, but we will return true.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void (*ApplyHomebaseEffectsOnPlayerSetupOriginal)(
|
||||
__int64* GameState,
|
||||
__int64 a2,
|
||||
@@ -426,6 +440,8 @@ DWORD WINAPI Main(LPVOID)
|
||||
nullptr, false);
|
||||
}
|
||||
|
||||
// Hooking::MinHook::Hook(FortPlayerControllerZoneDefault->VFTable[0xD0 / 8], CanCreateInCurrentContextHook, (PVOID*)&CanCreateInCurrentContextOriginal);
|
||||
|
||||
HookInstruction(Addresses::UpdateTrackedAttributesLea, (PVOID)UFortGadgetItemDefinition::UpdateTrackedAttributesHook, "/Script/FortniteGame.FortPlayerController.Suicide", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
||||
HookInstruction(Addresses::CombinePickupLea, (PVOID)AFortPickup::CombinePickupHook, "/Script/Engine.PlayerController.SetVirtualJoystickVisibility", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
||||
|
||||
|
||||
@@ -144,6 +144,8 @@ static inline uint64 FindObjectArray()
|
||||
|
||||
static inline uint64 FindPickupInitialize()
|
||||
{
|
||||
if (Engine_Version == 419)
|
||||
return Memcury::Scanner::FindPattern("48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 80 B9 ? ? ? ? ? 41 0F B6 E9").Get(); // 1.11
|
||||
if (Engine_Version == 420)
|
||||
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 41 56 48 83 EC 20 80 B9 ? ? ? ? ? 45 0F B6 F1 49 8B E8").Get(); // 4.1
|
||||
if (Engine_Version == 421)
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "events.h"
|
||||
#include "FortAthenaMutator_Heist.h"
|
||||
#include "BGA.h"
|
||||
#include "objectviewer.h"
|
||||
|
||||
#define GAME_TAB 1
|
||||
#define PLAYERS_TAB 2
|
||||
@@ -283,7 +284,7 @@ static inline void StaticUI()
|
||||
|
||||
#ifndef PROD
|
||||
ImGui::Checkbox("Log ProcessEvent", &Globals::bLogProcessEvent);
|
||||
ImGui::InputInt("Amount of bots to spawn", &AmountOfBotsToSpawn);
|
||||
// ImGui::InputInt("Amount of bots to spawn", &AmountOfBotsToSpawn);
|
||||
#endif
|
||||
|
||||
ImGui::Checkbox("Infinite Ammo", &Globals::bInfiniteAmmo);
|
||||
@@ -480,40 +481,6 @@ static inline void MainUI()
|
||||
SpawnBGAs();
|
||||
}
|
||||
|
||||
/*
|
||||
if (ImGui::Button("New"))
|
||||
{
|
||||
static auto NextFn = FindObject<UFunction>("/Game/Athena/Prototype/Blueprints/Cube/CUBE.CUBE_C.Next");
|
||||
static auto NewFn = FindObject<UFunction>("/Game/Athena/Prototype/Blueprints/Cube/CUBE.CUBE_C.New");
|
||||
auto Loader = GetEventLoader("/Game/Athena/Prototype/Blueprints/Cube/CUBE.CUBE_C");
|
||||
|
||||
LOG_INFO(LogDev, "Loader: {}", __int64(Loader));
|
||||
|
||||
if (Loader)
|
||||
{
|
||||
int32 NewParam = 1;
|
||||
// Loader->ProcessEvent(NextFn, &NewParam);
|
||||
Loader->ProcessEvent(NewFn, &NewParam);
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui::Button("Next"))
|
||||
{
|
||||
static auto NextFn = FindObject<UFunction>("/Game/Athena/Prototype/Blueprints/Cube/CUBE.CUBE_C.Next");
|
||||
static auto NewFn = FindObject<UFunction>("/Game/Athena/Prototype/Blueprints/Cube/CUBE.CUBE_C.New");
|
||||
auto Loader = GetEventLoader("/Game/Athena/Prototype/Blueprints/Cube/CUBE.CUBE_C");
|
||||
|
||||
LOG_INFO(LogDev, "Loader: {}", __int64(Loader));
|
||||
|
||||
if (Loader)
|
||||
{
|
||||
int32 NewParam = 1;
|
||||
Loader->ProcessEvent(NextFn, &NewParam);
|
||||
// Loader->ProcessEvent(NewFn, &NewParam);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!bIsInAutoRestart && (Engine_Version < 424 && ImGui::Button("Restart")))
|
||||
{
|
||||
if (Engine_Version < 424)
|
||||
@@ -526,45 +493,6 @@ static inline void MainUI()
|
||||
LOG_ERROR(LogGame, "Restarting is not supported on chapter 2 and above!");
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (ImGui::Button("TEST"))
|
||||
{
|
||||
auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode();
|
||||
auto GameState = GameMode->GetGameState();
|
||||
|
||||
static auto mutatorClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaMutator");
|
||||
auto AllMutators = UGameplayStatics::GetAllActorsOfClass(GetWorld(), mutatorClass);
|
||||
|
||||
for (int i = 0; i < AllMutators.Num(); i++)
|
||||
{
|
||||
auto Mutator = AllMutators.at(i);
|
||||
|
||||
LOG_INFO(LogDev, "[{}] Mutator: {}", i, Mutator->GetFullName());
|
||||
|
||||
if (auto DiscoMutator = Cast<AFortAthenaMutator_Disco>(Mutator))
|
||||
{
|
||||
auto& ControlPointSpawnData = DiscoMutator->GetControlPointSpawnData();
|
||||
|
||||
LOG_INFO(LogDev, "ControlPointSpawnData.Num(): {}", ControlPointSpawnData.Num());
|
||||
}
|
||||
else if (auto HeistMutator = Cast<AFortAthenaMutator_Heist>(Mutator))
|
||||
{
|
||||
auto& HeistExitCraftSpawnData = HeistMutator->GetHeistExitCraftSpawnData();
|
||||
|
||||
LOG_INFO(LogDev, "HeistExitCraftSpawnData.Num(): {}", HeistExitCraftSpawnData.Num());
|
||||
|
||||
for (int j = 0; j < HeistExitCraftSpawnData.Num(); j++)
|
||||
{
|
||||
auto& CurrentHeistExitCraftSpawnData = HeistExitCraftSpawnData.at(j);
|
||||
auto CurveTable = CurrentHeistExitCraftSpawnData.SpawnDelayTime.GetCurve().CurveTable;
|
||||
|
||||
// LOG_INFO(LogDev, "{} {}", CurveTable ? CurveTable->GetFullName() : "InvalidTable",
|
||||
// CurrentHeistExitCraftSpawnData.SpawnDelayTime.GetCurve().RowName.IsValid() ? CurrentHeistExitCraftSpawnData.SpawnDelayTime.GetCurve().RowName.ToString() : "InvalidName");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (!bStartedBus)
|
||||
{
|
||||
@@ -905,13 +833,29 @@ static inline void MainUI()
|
||||
{
|
||||
static std::string ClassNameToDump;
|
||||
static std::string FunctionNameToDump;
|
||||
static std::string ObjectToDump;
|
||||
static std::string FileNameToDumpTo;
|
||||
static bool bExcludeUnhandled;
|
||||
|
||||
ImGui::Checkbox("Fill Vending Machines", &Globals::bFillVendingMachines);
|
||||
ImGui::Checkbox("Enable Bot Tick", &bEnableBotTick);
|
||||
ImGui::Checkbox("Enable Combine Pickup", &bEnableCombinePickup);
|
||||
ImGui::InputText("Class Name to mess with", &ClassNameToDump);
|
||||
|
||||
ImGui::InputText("Object to dump", &ObjectToDump);
|
||||
ImGui::InputText("Function Name to mess with", &FunctionNameToDump);
|
||||
ImGui::InputText("File name to dump to", &FileNameToDumpTo);
|
||||
ImGui::Checkbox("Exclude unhandled", &bExcludeUnhandled);
|
||||
|
||||
if (ImGui::Button("Dump Object Info"))
|
||||
{
|
||||
auto Object = FindObject(ObjectToDump);
|
||||
|
||||
LOG_INFO(LogDev, "r: {}", __int64(Object));
|
||||
|
||||
// null check is already handled
|
||||
|
||||
ObjectViewer::DumpContentsToFile(Object, FileNameToDumpTo, bExcludeUnhandled);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Print Class VFT"))
|
||||
{
|
||||
|
||||
@@ -83,6 +83,7 @@ inline void InitLogger()
|
||||
MakeLogger("LogVehicles");
|
||||
MakeLogger("LogBots");
|
||||
MakeLogger("LogCosmetics");
|
||||
MakeLogger("LogObjectViewer");
|
||||
}
|
||||
|
||||
#define LOG_DEBUG(loggerName, ...) \
|
||||
|
||||
193
Project Reboot 3.0/objectviewer.h
Normal file
193
Project Reboot 3.0/objectviewer.h
Normal file
@@ -0,0 +1,193 @@
|
||||
#pragma once
|
||||
|
||||
#include "reboot.h"
|
||||
#include <fstream>
|
||||
|
||||
static inline FName* GetNamePrivateOfProperty(void* Property)
|
||||
{
|
||||
FName* NamePrivate = nullptr;
|
||||
|
||||
if (Engine_Version >= 425)
|
||||
NamePrivate = (FName*)(__int64(Property) + 0x28);
|
||||
else
|
||||
NamePrivate = &((UField*)Property)->NamePrivate;
|
||||
|
||||
return NamePrivate;
|
||||
};
|
||||
|
||||
static inline bool IsPropertyA(void* Property, UClass* Class)
|
||||
{
|
||||
if (Engine_Version < 425)
|
||||
{
|
||||
if (((UField*)Property)->IsA(Class))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace ObjectViewer
|
||||
{
|
||||
static inline void DumpContentsToFile(UObject* Object, const std::string& FileName, bool bExcludeUnhandled = false)
|
||||
{
|
||||
if (!Object/*->IsValidLowLevel()*/)
|
||||
{
|
||||
LOG_ERROR(LogObjectViewer, "Invalid object passed into DumpContentsToFile!");
|
||||
return;
|
||||
}
|
||||
|
||||
static auto ClassClass = FindObject<UClass>(L"/Script/CoreUObject.Class");
|
||||
|
||||
if (Object->IsA(ClassClass))
|
||||
{
|
||||
LOG_ERROR(LogObjectViewer, "Object passed into DumpContentsToFile was a class!");
|
||||
return;
|
||||
}
|
||||
|
||||
static auto BytePropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ByteProperty");
|
||||
static auto ObjectPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ObjectProperty");
|
||||
static auto ClassPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ClassProperty");
|
||||
static auto DoublePropertyClass = FindObject<UClass>(L"/Script/CoreUObject.DoubleProperty");
|
||||
static auto FloatPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.FloatProperty");
|
||||
static auto Int8PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.Int8Property");
|
||||
static auto EnumPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.EnumProperty");
|
||||
static auto ArrayPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.ArrayProperty");
|
||||
static auto Int64PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.Int64Property");
|
||||
static auto UInt16PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.UInt16Property");
|
||||
static auto BoolPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.BoolProperty");
|
||||
static auto NamePropertyClass = FindObject<UClass>(L"/Script/CoreUObject.NameProperty");
|
||||
static auto UInt32PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.UInt32Property");
|
||||
static auto FunctionClass = FindObject<UClass>(L"/Script/CoreUObject.Function");
|
||||
static auto IntPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.IntProperty");
|
||||
static auto UInt64PropertyClass = FindObject<UClass>(L"/Script/CoreUObject.UInt64Property");
|
||||
static auto StrPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.StrProperty");
|
||||
static auto SoftObjectPropertyClass = FindObject<UClass>(L"/Script/CoreUObject.SoftObjectProperty");
|
||||
|
||||
std::ofstream Stream(FileName);
|
||||
|
||||
if (!Stream.is_open())
|
||||
{
|
||||
LOG_ERROR(LogObjectViewer, "Failed to open file {}!", FileName);
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto CurrentClass = Object->ClassPrivate; CurrentClass; CurrentClass = CurrentClass->GetSuperStruct())
|
||||
{
|
||||
void* Property = *(void**)(__int64(CurrentClass) + Offsets::Children);
|
||||
|
||||
while (Property)
|
||||
{
|
||||
std::string PropertyName = GetNamePrivateOfProperty(Property)->ToString();
|
||||
int Offset = *(int*)(__int64(Property) + Offsets::Offset_Internal);
|
||||
|
||||
if (Offsets::PropertyClass)
|
||||
{
|
||||
if (IsPropertyA(Property, ObjectPropertyClass))
|
||||
{
|
||||
auto PropertyClass = *(UClass**)(__int64(Property) + Offsets::PropertyClass);
|
||||
|
||||
if (PropertyClass->IsValidLowLevel())
|
||||
Stream << std::format("{} Object: {}\n", PropertyName, PropertyClass->GetPathName());
|
||||
}
|
||||
|
||||
/*
|
||||
else if (IsPropertyA(Property, SoftObjectPropertyClass))
|
||||
{
|
||||
auto PropertyClass = *(UClass**)(__int64(Property) + Offsets::PropertyClass);
|
||||
|
||||
if (PropertyClass->IsValidLowLevel())
|
||||
{
|
||||
auto SoftObjectPtr = *(TSoftObjectPtr<UObject>*)(__int64(Object) + Offset);
|
||||
auto SoftObjectPtrObject = SoftObjectPtr.Get(PropertyClass);
|
||||
Stream << std::format("{} SoftObjectPtr (type: {}): {}\n", PropertyName, PropertyClass->GetName(), SoftObjectPtrObject ? SoftObjectPtrObject->GetPathName() : "BadRead");
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (IsPropertyA(Property, BytePropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Byte: {}\n", PropertyName, *(uint8*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, DoublePropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Double: {}\n", PropertyName, *(double*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, UInt16PropertyClass))
|
||||
{
|
||||
Stream << std::format("{} UInt16: {}\n", PropertyName, *(uint16*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, Int8PropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Int8: {}\n", PropertyName, *(int8*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, NamePropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Name: {}\n", PropertyName, (*(FName*)(__int64(Object) + Offset)).ToString());
|
||||
}
|
||||
else if (IsPropertyA(Property, StrPropertyClass))
|
||||
{
|
||||
Stream << std::format("{} String: {}\n", PropertyName, (*(FString*)(__int64(Object) + Offset)).ToString());
|
||||
}
|
||||
else if (IsPropertyA(Property, FloatPropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Float: {}\n", PropertyName, *(float*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, BoolPropertyClass))
|
||||
{
|
||||
auto FieldMask = GetFieldMask(Property);
|
||||
|
||||
Stream << std::format("{} Bool: {}\n", PropertyName, ReadBitfield((PlaceholderBitfield*)(__int64(Object) + Offset), FieldMask));
|
||||
}
|
||||
else if (IsPropertyA(Property, IntPropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Int32: {}\n", PropertyName, *(int*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, UInt32PropertyClass))
|
||||
{
|
||||
Stream << std::format("{} UInt32: {}\n", PropertyName, *(uint32*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, UInt64PropertyClass))
|
||||
{
|
||||
Stream << std::format("{} UInt64: {}\n", PropertyName, *(uint64*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, Int64PropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Int64: {}\n", PropertyName, *(int64*)(__int64(Object) + Offset));
|
||||
}
|
||||
else if (IsPropertyA(Property, ArrayPropertyClass))
|
||||
{
|
||||
Stream << std::format("{} Array\n", PropertyName);
|
||||
}
|
||||
else if (IsPropertyA(Property, EnumPropertyClass))
|
||||
{
|
||||
using UNumericProperty = UObject;
|
||||
|
||||
auto EnumValueIg = *(uint8*)(__int64(Property) + Offset);
|
||||
auto UnderlyingType = *(UNumericProperty**)(__int64(Property) + Offsets::UnderlyingType);
|
||||
// Stream << std::format("{} Enum: {}\n", PropertyName, (int)EnumValueIg);
|
||||
Stream << std::format("{} Enum\n", PropertyName);
|
||||
}
|
||||
else if (IsPropertyA(Property, FunctionClass))
|
||||
{
|
||||
|
||||
}
|
||||
else if (!bExcludeUnhandled)
|
||||
{
|
||||
// Stream << std::format("{}: {}\n", PropertyName, "UNHANDLED");
|
||||
Stream << std::format("{}: {} {}\n", PropertyName, "UNHANDLED", ""/*, ((UObject*)Property)->GetName()*/);
|
||||
}
|
||||
|
||||
Property = Engine_Version >= 425 ? *(void**)(__int64(Property) + 0x20) : ((UField*)Property)->Next;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void DumpContentsToFile(const std::string& ObjectName, const std::string& FileName, bool bExcludeUnhandled = false) { return DumpContentsToFile(FindObject(ObjectName), FileName, bExcludeUnhandled); }
|
||||
}
|
||||
@@ -124,7 +124,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
||||
|
||||
constexpr bool bPrint = false;
|
||||
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(LootTierGroup, LootTier, bPrint);
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(LootTierGroup, GameState->GetWorldLevel(), LootTier, bPrint);
|
||||
|
||||
if (LootDrops.size() == 0)
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user