mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
level
level showing up on items now, fix s19, improve performance, fix big issue on s5
This commit is contained in:
@@ -37,6 +37,8 @@ public:
|
|||||||
inline InElementType& at(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
inline InElementType& at(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
||||||
inline InElementType* AtPtr(int i, size_t Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
inline InElementType* AtPtr(int i, size_t Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
|
||||||
|
|
||||||
|
bool IsValidIndex(int i) { return i > 0 && i < ArrayNum; }
|
||||||
|
|
||||||
ElementAllocatorType& GetData() const { return Data; }
|
ElementAllocatorType& GetData() const { return Data; }
|
||||||
ElementAllocatorType& GetData() { return Data; }
|
ElementAllocatorType& GetData() { return Data; }
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ static inline void SpawnBGAs() // hahah not "proper", there's a function that we
|
|||||||
static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup");
|
static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup");
|
||||||
auto& SpawnLootTierGroup = BGAConsumableSpawner->Get<FName>(SpawnLootTierGroupOffset);
|
auto& SpawnLootTierGroup = BGAConsumableSpawner->Get<FName>(SpawnLootTierGroupOffset);
|
||||||
|
|
||||||
auto LootDrops = PickLootDrops(SpawnLootTierGroup);
|
auto LootDrops = PickLootDrops(SpawnLootTierGroup, GameState->GetWorldLevel());
|
||||||
|
|
||||||
for (int z = 0; z < LootDrops.size(); z++)
|
for (int z = 0; z < LootDrops.size(); z++)
|
||||||
{
|
{
|
||||||
@@ -63,11 +63,7 @@ static inline void SpawnBGAs() // hahah not "proper", there's a function that we
|
|||||||
|
|
||||||
bool bDeferConstruction = true; // hm?
|
bool bDeferConstruction = true; // hm?
|
||||||
|
|
||||||
FActorSpawnParameters SpawnParameters{};
|
auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, bDeferConstruction));
|
||||||
// SpawnParameters.ObjectFlags = RF_Transactional; // idk fortnite does this i think // i think its acutally suppsoed to be |= RF_Transient
|
|
||||||
SpawnParameters.bDeferConstruction = bDeferConstruction;
|
|
||||||
|
|
||||||
auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnTransform, SpawnParameters);
|
|
||||||
|
|
||||||
if (ConsumableActor)
|
if (ConsumableActor)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
|||||||
|
|
||||||
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
|
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
|
||||||
|
|
||||||
auto LootDrops = PickLootDrops(RedirectedLootTier, -1, bDebugPrintLooting);
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
|
auto LootDrops = PickLootDrops(RedirectedLootTier, GameState->GetWorldLevel(), -1, bDebugPrintLooting);
|
||||||
|
|
||||||
// LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
|
// LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
|
||||||
|
|
||||||
@@ -25,7 +27,7 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
|||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.bToss = true;
|
CreateData.bToss = true;
|
||||||
// CreateData.PawnOwner = Pawn;
|
// CreateData.PawnOwner = Pawn;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(lootDrop->GetItemDefinition(), lootDrop->GetCount(), lootDrop->GetLoadedAmmo());
|
CreateData.ItemEntry = lootDrop.ItemEntry;
|
||||||
CreateData.SpawnLocation = LocationToSpawnLoot;
|
CreateData.SpawnLocation = LocationToSpawnLoot;
|
||||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetContainerValue();
|
CreateData.SourceType = EFortPickupSourceTypeFlag::GetContainerValue();
|
||||||
CreateData.bRandomRotation = true;
|
CreateData.bRandomRotation = true;
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ public:
|
|||||||
AActor* GetViewTarget();
|
AActor* GetViewTarget();
|
||||||
void Possess(class APawn* Pawn);
|
void Possess(class APawn* Pawn);
|
||||||
|
|
||||||
|
FName& GetStateName()
|
||||||
|
{
|
||||||
|
static auto StateNameOffset = GetOffset("StateName");
|
||||||
|
return Get<FName>(StateNameOffset);
|
||||||
|
}
|
||||||
|
|
||||||
class APawn*& GetPawn()
|
class APawn*& GetPawn()
|
||||||
{
|
{
|
||||||
static auto PawnOffset = this->GetOffset("Pawn");
|
static auto PawnOffset = this->GetOffset("Pawn");
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Object.h"
|
#include "Object.h"
|
||||||
|
#include "reboot.h"
|
||||||
|
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
|
||||||
|
struct FTableRowBase
|
||||||
|
{
|
||||||
|
unsigned char UnknownData00[0x8]; // this is actually structural padding
|
||||||
|
};
|
||||||
|
|
||||||
class UDataTable : public UObject
|
class UDataTable : public UObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -17,7 +23,7 @@ public:
|
|||||||
|
|
||||||
static UClass* StaticClass()
|
static UClass* StaticClass()
|
||||||
{
|
{
|
||||||
static auto Class = FindObject<UClass>("/Script/Engine.DataTable");
|
static auto Class = FindObject<UClass>(L"/Script/Engine.DataTable");
|
||||||
return Class;
|
return Class;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,11 +63,8 @@ void AFortAthenaMapInfo::SpawnLlamas()
|
|||||||
InitialSpawnTransform.Rotation = RandomYawRotator.Quaternion();
|
InitialSpawnTransform.Rotation = RandomYawRotator.Quaternion();
|
||||||
InitialSpawnTransform.Scale3D = FVector(1, 1, 1);
|
InitialSpawnTransform.Scale3D = FVector(1, 1, 1);
|
||||||
|
|
||||||
FActorSpawnParameters SpawnParameters{};
|
auto LlamaStart = GetWorld()->SpawnActor<AFortAthenaSupplyDrop>(GetLlamaClass(), InitialSpawnTransform,
|
||||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, true));
|
||||||
SpawnParameters.bDeferConstruction = true;
|
|
||||||
|
|
||||||
auto LlamaStart = GetWorld()->SpawnActor<AFortAthenaSupplyDrop>(GetLlamaClass(), InitialSpawnTransform, SpawnParameters);
|
|
||||||
|
|
||||||
// LOG_INFO(LogDev, "LlamaStart: {}", __int64(LlamaStart));
|
// LOG_INFO(LogDev, "LlamaStart: {}", __int64(LlamaStart));
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#include "FortAthenaSupplyDrop.h"
|
#include "FortAthenaSupplyDrop.h"
|
||||||
|
#include "FortGameStateAthena.h"
|
||||||
|
|
||||||
FVector AFortAthenaSupplyDrop::FindGroundLocationAt(FVector InLocation)
|
FVector AFortAthenaSupplyDrop::FindGroundLocationAt(FVector InLocation)
|
||||||
{
|
{
|
||||||
static auto FindGroundLocationAtFn = FindObject<UFunction>("/Script/FortniteGame.FortAthenaSupplyDrop.FindGroundLocationAt");
|
static auto FindGroundLocationAtFn = FindObject<UFunction>(L"/Script/FortniteGame.FortAthenaSupplyDrop.FindGroundLocationAt");
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@@ -44,12 +45,15 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnGameModePickupHook(UObject* Context, FF
|
|||||||
|
|
||||||
LOG_INFO(LogDev, "Spawning GameModePickup with ItemDefinition: {}", ItemDefinition->GetFullName());
|
LOG_INFO(LogDev, "Spawning GameModePickup with ItemDefinition: {}", ItemDefinition->GetFullName());
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.SpawnLocation = Position;
|
CreateData.SpawnLocation = Position;
|
||||||
CreateData.PawnOwner = TriggeringPawn;
|
CreateData.PawnOwner = TriggeringPawn;
|
||||||
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
|
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
|
||||||
CreateData.OverrideClass = PickupClass;
|
CreateData.OverrideClass = PickupClass;
|
||||||
|
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||||
|
|
||||||
*Ret = AFortPickup::SpawnPickup(CreateData);
|
*Ret = AFortPickup::SpawnPickup(CreateData);
|
||||||
return *Ret;
|
return *Ret;
|
||||||
@@ -74,8 +78,10 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnPickupHook(UObject* Context, FFrame& St
|
|||||||
if (!ItemDefinition)
|
if (!ItemDefinition)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.SpawnLocation = Position;
|
CreateData.SpawnLocation = Position;
|
||||||
CreateData.PawnOwner = TriggeringPawn;
|
CreateData.PawnOwner = TriggeringPawn;
|
||||||
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
|
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
|
||||||
|
|||||||
@@ -652,6 +652,8 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
|||||||
|
|
||||||
GetWorld()->Listen();
|
GetWorld()->Listen();
|
||||||
|
|
||||||
|
LOG_INFO(LogNet, "WorldLevel {}", GameState->GetWorldLevel());
|
||||||
|
|
||||||
if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer())
|
if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer())
|
||||||
{
|
{
|
||||||
TeamsArrayContainer->TeamIndexesArray.Free();
|
TeamsArrayContainer->TeamIndexesArray.Free();
|
||||||
@@ -889,6 +891,8 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
|
|||||||
bShouldSpreadTeams = bIsLargeTeamGame;
|
bShouldSpreadTeams = bIsLargeTeamGame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bShouldSpreadTeams = true;
|
||||||
|
|
||||||
static int CurrentTeamMembers = 0; // bad
|
static int CurrentTeamMembers = 0; // bad
|
||||||
static int Current = DefaultFirstTeam;
|
static int Current = DefaultFirstTeam;
|
||||||
static int NextTeamIndex = DefaultFirstTeam;
|
static int NextTeamIndex = DefaultFirstTeam;
|
||||||
@@ -986,11 +990,14 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
|
|||||||
{
|
{
|
||||||
if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer())
|
if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer())
|
||||||
{
|
{
|
||||||
auto& TeamArray = TeamsArrayContainer->TeamsArray.at(NextTeamIndex);
|
TArray<TWeakObjectPtr<AFortPlayerStateAthena>>* TeamArray = TeamsArrayContainer->TeamsArray.IsValidIndex(NextTeamIndex) ? TeamsArrayContainer->TeamsArray.AtPtr(NextTeamIndex) : nullptr;
|
||||||
LOG_INFO(LogDev, "TeamsArrayContainer->TeamsArray.Num(): {}", TeamsArrayContainer->TeamsArray.Num());
|
LOG_INFO(LogDev, "TeamsArrayContainer->TeamsArray.Num(): {}", TeamsArrayContainer->TeamsArray.Num());
|
||||||
LOG_INFO(LogDev, "TeamArray.Num(): {}", TeamArray.Num());
|
|
||||||
|
|
||||||
TeamArray.Add(WeakPlayerState);
|
if (TeamArray)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogDev, "TeamArray.Num(): {}", TeamArray->Num());
|
||||||
|
TeamArray->Add(WeakPlayerState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,13 +1137,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
auto Location = CurrentActor->GetActorLocation();
|
auto Location = CurrentActor->GetActorLocation();
|
||||||
Location.Z += UpZ;
|
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)
|
for (auto& LootDrop : LootDrops)
|
||||||
{
|
{
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.bToss = true;
|
CreateData.bToss = true;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||||
CreateData.SpawnLocation = Location;
|
CreateData.SpawnLocation = Location;
|
||||||
CreateData.SourceType = SpawnFlag;
|
CreateData.SourceType = SpawnFlag;
|
||||||
CreateData.bRandomRotation = true;
|
CreateData.bRandomRotation = true;
|
||||||
@@ -1160,13 +1167,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
auto Location = CurrentActor->GetActorLocation();
|
auto Location = CurrentActor->GetActorLocation();
|
||||||
Location.Z += UpZ;
|
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)
|
for (auto& LootDrop : LootDrops)
|
||||||
{
|
{
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.bToss = true;
|
CreateData.bToss = true;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||||
CreateData.SpawnLocation = Location;
|
CreateData.SpawnLocation = Location;
|
||||||
CreateData.SourceType = SpawnFlag;
|
CreateData.SourceType = SpawnFlag;
|
||||||
CreateData.bRandomRotation = true;
|
CreateData.bRandomRotation = true;
|
||||||
|
|||||||
@@ -105,6 +105,12 @@ public:
|
|||||||
return this->Get<bool>(bSafeZonePausedOffset);
|
return this->Get<bool>(bSafeZonePausedOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int& GetWorldLevel() // Actually in AFortGameState
|
||||||
|
{
|
||||||
|
static auto WorldLevelOffset = GetOffset("WorldLevel");
|
||||||
|
return Get<int>(WorldLevelOffset);
|
||||||
|
}
|
||||||
|
|
||||||
EAthenaGamePhase& GetGamePhase()
|
EAthenaGamePhase& GetGamePhase()
|
||||||
{
|
{
|
||||||
static auto GamePhaseOffset = GetOffset("GamePhase");
|
static auto GamePhaseOffset = GetOffset("GamePhase");
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
|||||||
return std::make_pair(NewItemInstances, ModifiedItemInstances);
|
return std::make_pair(NewItemInstances, ModifiedItemInstances);
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1, MAX_DURABILITY/* level */);
|
||||||
CreateData.SpawnLocation = Pawn->GetActorLocation();
|
CreateData.SpawnLocation = Pawn->GetActorLocation();
|
||||||
CreateData.PawnOwner = Cast<AFortPawn>(Pawn);
|
CreateData.PawnOwner = Cast<AFortPawn>(Pawn);
|
||||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
|
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ void FFortItemEntry::SetStateValue(EFortItemEntryState StateType, int IntValue)
|
|||||||
// ItemEntry->bIsDirty = true;
|
// 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);
|
auto Entry = Alloc<FFortItemEntry>(GetStructSize(), bUseFMemoryRealloc);
|
||||||
|
|
||||||
@@ -50,6 +50,7 @@ FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinitio
|
|||||||
Entry->GetDurability() = Durability;
|
Entry->GetDurability() = Durability;
|
||||||
Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1);
|
Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1);
|
||||||
Entry->GetParentInventory().ObjectIndex = -1;
|
Entry->GetParentInventory().ObjectIndex = -1;
|
||||||
|
Entry->GetLevel() = Level;
|
||||||
// We want to add StateValues.Add(DurabilityInitialized); orwnatefc erwgearf yk
|
// We want to add StateValues.Add(DurabilityInitialized); orwnatefc erwgearf yk
|
||||||
// CoCreateGuid((GUID*)&Entry->GetItemGuid());
|
// CoCreateGuid((GUID*)&Entry->GetItemGuid());
|
||||||
// Entry->DoesUpdateStatsOnCollection() = true; // I think fortnite does this?
|
// Entry->DoesUpdateStatsOnCollection() = true; // I think fortnite does this?
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ enum class EFortItemEntryState : uint8_t // this changes but its fineee
|
|||||||
EFortItemEntryState_MAX = 15
|
EFortItemEntryState_MAX = 15
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_DURABILITY 0x3F800000
|
||||||
|
|
||||||
struct FFortItemEntryStateValue
|
struct FFortItemEntryStateValue
|
||||||
{
|
{
|
||||||
static UStruct* GetStruct()
|
static UStruct* GetStruct()
|
||||||
@@ -189,7 +191,7 @@ struct FFortItemEntry : FFastArraySerializerItem
|
|||||||
return StructSize;
|
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 = MAX_DURABILITY, 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.
|
// We need to find a better way for below... Especially since we can't do either method for season 5 or 6.
|
||||||
|
|
||||||
|
|||||||
@@ -137,8 +137,10 @@ void UFortKismetLibrary::SpawnItemVariantPickupInWorldHook(UObject* Context, FFr
|
|||||||
|
|
||||||
LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z);
|
LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z);
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, ParamsPtr->GetNumberToSpawn(), -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, ParamsPtr->GetNumberToSpawn(), -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.SourceType = ParamsPtr->GetSourceType();
|
CreateData.SourceType = ParamsPtr->GetSourceType();
|
||||||
CreateData.Source = ParamsPtr->GetSource();
|
CreateData.Source = ParamsPtr->GetSource();
|
||||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||||
@@ -172,8 +174,10 @@ bool UFortKismetLibrary::SpawnInstancedPickupInWorldHook(UObject* Context, FFram
|
|||||||
Stack.StepCompiledIn(&bRandomRotation);
|
Stack.StepCompiledIn(&bRandomRotation);
|
||||||
Stack.StepCompiledIn(&bBlockedFromAutoPickup);
|
Stack.StepCompiledIn(&bBlockedFromAutoPickup);
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.SpawnLocation = Position;
|
CreateData.SpawnLocation = Position;
|
||||||
CreateData.bToss = bToss;
|
CreateData.bToss = bToss;
|
||||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||||
@@ -226,8 +230,10 @@ void UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHo
|
|||||||
if (!AmmoDefinition)
|
if (!AmmoDefinition)
|
||||||
return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret);
|
return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret);
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(AmmoDefinition, Count, 0);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(AmmoDefinition, Count, 0, MAX_DURABILITY, AmmoDefinition->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.SourceType = SourceTypeFlag;
|
CreateData.SourceType = SourceTypeFlag;
|
||||||
CreateData.Source = SpawnSource;
|
CreateData.Source = SpawnSource;
|
||||||
CreateData.SpawnLocation = Location;
|
CreateData.SpawnLocation = Location;
|
||||||
@@ -508,8 +514,10 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con
|
|||||||
|
|
||||||
LOG_INFO(LogDev, __FUNCTION__);
|
LOG_INFO(LogDev, __FUNCTION__);
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, ItemDefinition->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.Source = Source;
|
CreateData.Source = Source;
|
||||||
CreateData.SourceType = SourceType;
|
CreateData.SourceType = SourceType;
|
||||||
CreateData.OverrideClass = PickupClass;
|
CreateData.OverrideClass = PickupClass;
|
||||||
@@ -591,8 +599,10 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr
|
|||||||
|
|
||||||
auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr;
|
auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr;
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, GameState->GetWorldLevel());
|
||||||
CreateData.SpawnLocation = Position;
|
CreateData.SpawnLocation = Position;
|
||||||
CreateData.bToss = bToss;
|
CreateData.bToss = bToss;
|
||||||
CreateData.bRandomRotation = bRandomRotation;
|
CreateData.bRandomRotation = bRandomRotation;
|
||||||
@@ -628,9 +638,11 @@ bool UFortKismetLibrary::PickLootDropsHook(UObject* Context, FFrame& Stack, bool
|
|||||||
|
|
||||||
FFortItemEntry::FreeArrayOfEntries(OutLootToDropTempBuf);
|
FFortItemEntry::FreeArrayOfEntries(OutLootToDropTempBuf);
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Picking loot for {}.", TierGroupName.ComparisonIndex.Value ? TierGroupName.ToString() : "InvalidName");
|
LOG_INFO(LogDev, "Picking loot for {}.", TierGroupName.ComparisonIndex.Value ? TierGroupName.ToString() : "InvalidName");
|
||||||
|
|
||||||
auto LootDrops = PickLootDrops(TierGroupName, -1, true);
|
auto LootDrops = PickLootDrops(TierGroupName, GameState->GetWorldLevel(), -1, true);
|
||||||
|
|
||||||
for (int i = 0; i < LootDrops.size(); i++)
|
for (int i = 0; i < LootDrops.size(); i++)
|
||||||
{
|
{
|
||||||
|
|||||||
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
|
class UFortLootLevel
|
||||||
{
|
{
|
||||||
int GetItemLevel(FDataTableCategoryHandle LootLevelData, int WorldLevel)
|
public:
|
||||||
{
|
static int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "UObjectArray.h"
|
#include "UObjectArray.h"
|
||||||
#include "GameplayTagContainer.h"
|
#include "GameplayTagContainer.h"
|
||||||
#include "FortGameModeAthena.h"
|
#include "FortGameModeAthena.h"
|
||||||
|
#include "FortLootLevel.h"
|
||||||
|
|
||||||
struct FFortGameFeatureLootTableData
|
struct FFortGameFeatureLootTableData
|
||||||
{
|
{
|
||||||
@@ -13,8 +14,10 @@ struct FFortGameFeatureLootTableData
|
|||||||
TSoftObjectPtr<UDataTable> LootPackageData;
|
TSoftObjectPtr<UDataTable> LootPackageData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define LOOTING_MAP_TYPE std::map // uhhh // TODO (Milxnor) switch bad to map
|
||||||
|
|
||||||
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, LOOTING_MAP_TYPE<FName, RowStructType*>* OutMap, std::function<bool(FName, RowStructType*)> Check = []() { return true; })
|
||||||
{
|
{
|
||||||
std::vector<UDataTable*> DataTablesToIterate;
|
std::vector<UDataTable*> DataTablesToIterate;
|
||||||
|
|
||||||
@@ -32,8 +35,8 @@ void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, std::map<
|
|||||||
{
|
{
|
||||||
auto CompositeDataTable = DataTable;
|
auto CompositeDataTable = DataTable;
|
||||||
|
|
||||||
static auto ParentTablesOffset = DataTable->GetOffset("ParentTables");
|
static auto ParentTablesOffset = CompositeDataTable->GetOffset("ParentTables");
|
||||||
auto& ParentTables = DataTable->Get<TArray<UDataTable*>>(ParentTablesOffset);
|
auto& ParentTables = CompositeDataTable->Get<TArray<UDataTable*>>(ParentTablesOffset);
|
||||||
|
|
||||||
for (int i = 0; i < ParentTables.Num(); i++)
|
for (int i = 0; i < ParentTables.Num(); i++)
|
||||||
{
|
{
|
||||||
@@ -49,16 +52,14 @@ void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, std::map<
|
|||||||
for (auto& CurrentPair : CurrentDataTable->GetRowMap())
|
for (auto& CurrentPair : CurrentDataTable->GetRowMap())
|
||||||
{
|
{
|
||||||
if (Check(CurrentPair.Key(), (RowStructType*)CurrentPair.Value()))
|
if (Check(CurrentPair.Key(), (RowStructType*)CurrentPair.Value()))
|
||||||
|
{
|
||||||
|
// LOG_INFO(LogDev, "row: {} comp {} num: {} passed check!", CurrentPair.Key().ToString(), CurrentPair.Key().ComparisonIndex.Value, CurrentPair.Key().Number);
|
||||||
(*OutMap)[CurrentPair.Key()] = (RowStructType*)CurrentPair.Value();
|
(*OutMap)[CurrentPair.Key()] = (RowStructType*)CurrentPair.Value();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops)
|
float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops)
|
||||||
{
|
{
|
||||||
if (LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryWeightArray().Num()
|
if (LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryWeightArray().Num()
|
||||||
@@ -145,7 +146,7 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina
|
|||||||
std::vector<FFortItemEntry> ItemEntries;
|
std::vector<FFortItemEntry> ItemEntries;
|
||||||
}; */
|
}; */
|
||||||
|
|
||||||
FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& LTDTables, FName LootTierGroup, int WorldLevel = 0, int ForcedLootTier = -1, FName* OutRowName = nullptr) // Fortnite returns the row name and then finds the tier data again, but I really don't see the point of this.
|
FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& LTDTables, FName LootTierGroup, int ForcedLootTier = -1, FName* OutRowName = nullptr) // Fortnite returns the row name and then finds the tier data again, but I really don't see the point of this.
|
||||||
{
|
{
|
||||||
// This like isn't right, at all.
|
// This like isn't right, at all.
|
||||||
|
|
||||||
@@ -153,45 +154,47 @@ FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& LTDTables, F
|
|||||||
|
|
||||||
if (LootTier == -1)
|
if (LootTier == -1)
|
||||||
{
|
{
|
||||||
// LootTier = 0;
|
// LootTier = ??
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// buncha code im too lazy to reverse
|
// buncha code im too lazy to reverse
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDIakuuyg8712u091fj120gvik
|
|
||||||
|
|
||||||
// if (fabs(LootTier) <= 0.0000000099999999)
|
// if (fabs(LootTier) <= 0.0000000099999999)
|
||||||
// return 0;
|
// return 0;
|
||||||
|
|
||||||
std::map<FName, FFortLootTierData*> TierGroupLTDs;
|
int Multiplier = 1; // LootTier == -1 ? 1 : 1 LootTier // Idk i think we need to fill out the code above for this to work properly
|
||||||
|
|
||||||
|
LOOTING_MAP_TYPE<FName, FFortLootTierData*> TierGroupLTDs;
|
||||||
|
|
||||||
CollectDataTablesRows<FFortLootTierData>(LTDTables, &TierGroupLTDs, [&](FName RowName, FFortLootTierData* TierData) -> bool {
|
CollectDataTablesRows<FFortLootTierData>(LTDTables, &TierGroupLTDs, [&](FName RowName, FFortLootTierData* TierData) -> bool {
|
||||||
if (LootTierGroup == TierData->GetTierGroup() && (LootTier == -1 ? true : LootTier == TierData->GetLootTier()))
|
if (LootTierGroup == TierData->GetTierGroup())
|
||||||
{
|
{
|
||||||
return true;
|
if ((LootTier == -1 ? true : LootTier == TierData->GetLootTier()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// LOG_INFO(LogDev, "TierGroupLTDs.size(): {}", TierGroupLTDs.size());
|
||||||
|
|
||||||
FFortLootTierData* ChosenRowLootTierData = PickWeightedElement<FName, FFortLootTierData*>(TierGroupLTDs,
|
FFortLootTierData* ChosenRowLootTierData = PickWeightedElement<FName, FFortLootTierData*>(TierGroupLTDs,
|
||||||
[](FFortLootTierData* LootTierData) -> float { return LootTierData->GetWeight(); }, RandomFloatForLoot, -1,
|
[](FFortLootTierData* LootTierData) -> float { return LootTierData->GetWeight(); }, RandomFloatForLoot, -1,
|
||||||
true, LootTier == -1 ? 1 : LootTier, OutRowName);
|
true, Multiplier, OutRowName);
|
||||||
|
|
||||||
if (!ChosenRowLootTierData)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return ChosenRowLootTierData;
|
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)
|
if (!OutEntries)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::map<FName, FFortLootPackageData*> LootPackageIDMap;
|
LOOTING_MAP_TYPE<FName, FFortLootPackageData*> LootPackageIDMap;
|
||||||
|
|
||||||
CollectDataTablesRows<FFortLootPackageData>(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool {
|
CollectDataTablesRows<FFortLootPackageData>(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool {
|
||||||
if (LootPackage->GetLootPackageID() != LootPackageName)
|
if (LootPackage->GetLootPackageID() != LootPackageName)
|
||||||
@@ -204,14 +207,14 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if (WorldLevel >= 0)
|
if (WorldLevel >= 0)
|
||||||
{
|
{
|
||||||
if (LootPackage->MaxWorldLevel >= 0 && WorldLevel > LootPackage->MaxWorldLevel)
|
if (LootPackage->GetMaxWorldLevel() >= 0 && WorldLevel > LootPackage->GetMaxWorldLevel())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (LootPackage->MinWorldLevel >= 0 && WorldLevel < LootPackage->MinWorldLevel)
|
if (LootPackage->GetMinWorldLevel() >= 0 && WorldLevel < LootPackage->GetMinWorldLevel())
|
||||||
return 0;
|
return 0;
|
||||||
} */
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@@ -245,7 +248,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
|||||||
|
|
||||||
PickLootDropsFromLootPackage(LPTables,
|
PickLootDropsFromLootPackage(LPTables,
|
||||||
PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0),
|
PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0),
|
||||||
OutEntries, LootPackageCategoryToUseForLPCall, bPrint
|
OutEntries, LootPackageCategoryToUseForLPCall, WorldLevel, bPrint
|
||||||
);
|
);
|
||||||
|
|
||||||
v9++;
|
v9++;
|
||||||
@@ -263,15 +266,15 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ItemLevel = 0;
|
|
||||||
|
|
||||||
auto WeaponItemDefinition = Cast<UFortWeaponItemDefinition>(ItemDefinition);
|
auto WeaponItemDefinition = Cast<UFortWeaponItemDefinition>(ItemDefinition);
|
||||||
int LoadedAmmo = WeaponItemDefinition ? WeaponItemDefinition->GetClipSize() : 0; // we shouldnt set loaded ammo here techinally
|
int LoadedAmmo = WeaponItemDefinition ? WeaponItemDefinition->GetClipSize() : 0; // we shouldnt set loaded ammo here techinally
|
||||||
|
|
||||||
if (auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemDefinition))
|
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemDefinition);
|
||||||
{
|
|
||||||
ItemLevel = 0; // GetItemLevel(WorldItemDefinition->LootLevelData, 0);
|
if (!WorldItemDefinition) // hahahah not proper!!
|
||||||
}
|
return;
|
||||||
|
|
||||||
|
int ItemLevel = UFortLootLevel::GetItemLevel(WorldItemDefinition->GetLootLevelData(), WorldLevel);
|
||||||
|
|
||||||
int CountMultiplier = 1;
|
int CountMultiplier = 1;
|
||||||
int FinalCount = CountMultiplier * PickedPackage->GetCount();
|
int FinalCount = CountMultiplier * PickedPackage->GetCount();
|
||||||
@@ -285,9 +288,19 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
|||||||
|
|
||||||
while (FinalCount > 0)
|
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 (Engine_Version >= 424)
|
if (Engine_Version >= 424)
|
||||||
{
|
{
|
||||||
@@ -328,7 +341,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
|||||||
|
|
||||||
// #define brudda
|
// #define brudda
|
||||||
|
|
||||||
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;
|
std::vector<LootDrop> LootDrops;
|
||||||
|
|
||||||
@@ -636,10 +649,11 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
FName LootTierRowName;
|
FName LootTierRowName;
|
||||||
auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, 0, ForcedLootTier, &LootTierRowName);
|
auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, ForcedLootTier, &LootTierRowName);
|
||||||
|
|
||||||
if (!ChosenRowLootTierData)
|
if (!ChosenRowLootTierData)
|
||||||
{
|
{
|
||||||
|
LOG_INFO(LogLoot, "Failed to find LootTierData row for {} with loot tier {}", TierGroupName.ToString(), ForcedLootTier);
|
||||||
return LootDrops;
|
return LootDrops;
|
||||||
}
|
}
|
||||||
else if (bPrint)
|
else if (bPrint)
|
||||||
@@ -690,7 +704,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
|||||||
|
|
||||||
int LootPackageCategory = i;
|
int LootPackageCategory = i;
|
||||||
|
|
||||||
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, bPrint);
|
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, WorldLevel, bPrint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -49,6 +50,18 @@ public:
|
|||||||
return *(int*)(__int64(this) + LootPackageCategoryOffset);
|
return *(int*)(__int64(this) + LootPackageCategoryOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
FString& GetAnnotation()
|
FString& GetAnnotation()
|
||||||
{
|
{
|
||||||
static auto AnnotationOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "Annotation");
|
static auto AnnotationOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "Annotation");
|
||||||
@@ -140,9 +153,12 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map<KeyType, ValueTy
|
|||||||
TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<KeyType, ValueType>& p) {
|
TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<KeyType, ValueType>& p) {
|
||||||
auto Weight = GetWeightFn(p.second);
|
auto Weight = GetWeightFn(p.second);
|
||||||
|
|
||||||
if (bPrint && Weight != 0)
|
if (bPrint)
|
||||||
{
|
{
|
||||||
LOG_INFO(LogLoot, "Adding weight: {}", Weight);
|
// if (Weight != 0)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "Adding weight {}", Weight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc + Weight;
|
return acc + Weight;
|
||||||
@@ -154,7 +170,7 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map<KeyType, ValueTy
|
|||||||
|
|
||||||
if (bPrint)
|
if (bPrint)
|
||||||
{
|
{
|
||||||
LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {}", RandomNumber, TotalWeight);
|
LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {} Elements.size(): {}", RandomNumber, TotalWeight, Elements.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& Element : Elements)
|
for (auto& Element : Elements)
|
||||||
@@ -181,4 +197,62 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map<KeyType, ValueTy
|
|||||||
return ValueType();
|
return ValueType();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0);
|
|
||||||
|
template <typename KeyType, typename ValueType>
|
||||||
|
FORCEINLINE static ValueType PickWeightedElement(const std::unordered_map<KeyType, ValueType>& Elements,
|
||||||
|
std::function<float(ValueType)> GetWeightFn,
|
||||||
|
std::function<float(float)> RandomFloatGenerator = RandomFloatForLoot,
|
||||||
|
float TotalWeightParam = -1, bool bCheckIfWeightIsZero = false, int RandMultiplier = 1, KeyType* OutName = nullptr, bool bPrint = false, bool bKeepGoingUntilWeGetValue = false)
|
||||||
|
{
|
||||||
|
float TotalWeight = TotalWeightParam;
|
||||||
|
|
||||||
|
if (TotalWeight == -1)
|
||||||
|
{
|
||||||
|
TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<KeyType, ValueType>& p) {
|
||||||
|
auto Weight = GetWeightFn(p.second);
|
||||||
|
|
||||||
|
if (bPrint)
|
||||||
|
{
|
||||||
|
// if (Weight != 0)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "Adding weight {}", Weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc + Weight;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
float RandomNumber = // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight);
|
||||||
|
RandMultiplier * RandomFloatGenerator(TotalWeight);
|
||||||
|
|
||||||
|
if (bPrint)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {} Elements.size(): {}", RandomNumber, TotalWeight, Elements.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& Element : Elements)
|
||||||
|
{
|
||||||
|
float Weight = GetWeightFn(Element.second);
|
||||||
|
|
||||||
|
if (bCheckIfWeightIsZero && Weight == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (RandomNumber <= Weight)
|
||||||
|
{
|
||||||
|
if (OutName)
|
||||||
|
*OutName = Element.first;
|
||||||
|
|
||||||
|
return Element.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
RandomNumber -= Weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bKeepGoingUntilWeGetValue)
|
||||||
|
return PickWeightedElement<KeyType, ValueType>(Elements, GetWeightFn, RandomFloatGenerator, TotalWeightParam, bCheckIfWeightIsZero, RandMultiplier, OutName, bPrint, bKeepGoingUntilWeGetValue);
|
||||||
|
|
||||||
|
return ValueType();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0);
|
||||||
@@ -44,10 +44,7 @@ AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
|
|||||||
static auto FortPickupAthenaClass = FindObject<UClass>(L"/Script/FortniteGame.FortPickupAthena");
|
static auto FortPickupAthenaClass = FindObject<UClass>(L"/Script/FortniteGame.FortPickupAthena");
|
||||||
auto PlayerState = PickupData.PawnOwner ? Cast<AFortPlayerState>(PickupData.PawnOwner->GetPlayerState()) : nullptr;
|
auto PlayerState = PickupData.PawnOwner ? Cast<AFortPlayerState>(PickupData.PawnOwner->GetPlayerState()) : nullptr;
|
||||||
|
|
||||||
FActorSpawnParameters SpawnParameters{};
|
auto Pickup = GetWorld()->SpawnActor<AFortPickup>(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1));
|
||||||
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
|
||||||
|
|
||||||
auto Pickup = GetWorld()->SpawnActor<AFortPickup>(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1), SpawnParameters);
|
|
||||||
|
|
||||||
if (!Pickup)
|
if (!Pickup)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -270,7 +267,7 @@ void AFortPickup::CombinePickupHook(AFortPickup* Pickup)
|
|||||||
auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner();
|
auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner();
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, OverStackCount, 0);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, OverStackCount, 0, MAX_DURABILITY, Pickup->GetPrimaryPickupItemEntry()->GetLevel());
|
||||||
CreateData.SpawnLocation = PickupToCombineInto->GetActorLocation();
|
CreateData.SpawnLocation = PickupToCombineInto->GetActorLocation();
|
||||||
CreateData.PawnOwner = ItemOwner;
|
CreateData.PawnOwner = ItemOwner;
|
||||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
|
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
|
||||||
@@ -380,8 +377,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped && ItemDefGoingInPrimary) // swap
|
if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped && ItemDefGoingInPrimary) // swap
|
||||||
{
|
{
|
||||||
auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc,
|
auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc, EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn);
|
||||||
EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn);
|
|
||||||
|
|
||||||
auto CurrentWeapon = Pawn->GetCurrentWeapon();
|
auto CurrentWeapon = Pawn->GetCurrentWeapon();
|
||||||
|
|
||||||
|
|||||||
@@ -592,7 +592,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
|||||||
auto Entry = ItemCollection->GetOutputItemEntry()->AtPtr(z, FFortItemEntry::GetStructSize());
|
auto Entry = ItemCollection->GetOutputItemEntry()->AtPtr(z, FFortItemEntry::GetStructSize());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(Entry->GetItemDefinition(), Entry->GetCount(), Entry->GetLoadedAmmo());
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(Entry->GetItemDefinition(), Entry->GetCount(), Entry->GetLoadedAmmo(), MAX_DURABILITY, Entry->GetLevel());
|
||||||
CreateData.SpawnLocation = LocationToSpawnLoot;
|
CreateData.SpawnLocation = LocationToSpawnLoot;
|
||||||
CreateData.PawnOwner = PlayerController->GetMyFortPawn(); // hmm
|
CreateData.PawnOwner = PlayerController->GetMyFortPawn(); // hmm
|
||||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||||
@@ -627,9 +627,6 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
|
|||||||
if (Engine_Version < 424 && !Globals::bLateGame.load())
|
if (Engine_Version < 424 && !Globals::bLateGame.load())
|
||||||
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
||||||
|
|
||||||
if (Fortnite_Version == 17.30 && Globals::bGoingToPlayEvent)
|
|
||||||
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation); // We want to be teleported back to the UFO but we dont use chooseplayerstart
|
|
||||||
|
|
||||||
if (!PlayerController)
|
if (!PlayerController)
|
||||||
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
||||||
|
|
||||||
@@ -637,32 +634,57 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
|
|||||||
// return;
|
// return;
|
||||||
|
|
||||||
auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode();
|
auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode();
|
||||||
auto GameState = GameMode->GetGameStateAthena();
|
|
||||||
|
|
||||||
AActor* AircraftToJumpFrom = nullptr;
|
if (false)
|
||||||
|
|
||||||
static auto AircraftsOffset = GameState->GetOffset("Aircrafts", false);
|
|
||||||
|
|
||||||
if (AircraftsOffset == -1)
|
|
||||||
{
|
{
|
||||||
static auto AircraftOffset = GameState->GetOffset("Aircraft");
|
auto GameState = GameMode->GetGameStateAthena();
|
||||||
AircraftToJumpFrom = GameState->Get<AActor*>(AircraftOffset);
|
|
||||||
|
AActor* AircraftToJumpFrom = nullptr;
|
||||||
|
|
||||||
|
static auto AircraftsOffset = GameState->GetOffset("Aircrafts", false);
|
||||||
|
|
||||||
|
if (AircraftsOffset == -1)
|
||||||
|
{
|
||||||
|
static auto AircraftOffset = GameState->GetOffset("Aircraft");
|
||||||
|
AircraftToJumpFrom = GameState->Get<AActor*>(AircraftOffset);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto Aircrafts = GameState->GetPtr<TArray<AActor*>>(AircraftsOffset);
|
||||||
|
AircraftToJumpFrom = Aircrafts->Num() > 0 ? Aircrafts->at(0) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AircraftToJumpFrom)
|
||||||
|
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
||||||
|
|
||||||
|
auto NewPawn = GameMode->SpawnDefaultPawnForHook(GameMode, (AController*)PlayerController, AircraftToJumpFrom);
|
||||||
|
PlayerController->Possess(NewPawn);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto Aircrafts = GameState->GetPtr<TArray<AActor*>>(AircraftsOffset);
|
if (false)
|
||||||
AircraftToJumpFrom = Aircrafts->Num() > 0 ? Aircrafts->at(0) : nullptr;
|
{
|
||||||
|
// honestly idk why this doesnt work
|
||||||
|
|
||||||
|
auto NAME_Inactive = UKismetStringLibrary::Conv_StringToName(L"NAME_Inactive");
|
||||||
|
|
||||||
|
LOG_INFO(LogDev, "name Comp: {}", NAME_Inactive.ComparisonIndex.Value);
|
||||||
|
|
||||||
|
PlayerController->GetStateName() = NAME_Inactive;
|
||||||
|
PlayerController->SetPlayerIsWaiting(true);
|
||||||
|
PlayerController->ServerRestartPlayer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GameMode->RestartPlayer(PlayerController);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we are supposed to do some skydivign stuff here but whatever
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!AircraftToJumpFrom)
|
auto NewPawnAsFort = PlayerController->GetMyFortPawn();
|
||||||
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
|
||||||
|
|
||||||
auto NewPawn = GameMode->SpawnDefaultPawnForHook(GameMode, (AController*)PlayerController, AircraftToJumpFrom);
|
if (Fortnite_Version >= 18) // TODO (Milxnor) Find a better fix and move this
|
||||||
PlayerController->Possess(NewPawn);
|
|
||||||
|
|
||||||
auto NewPawnAsFort = Cast<AFortPawn>(NewPawn);
|
|
||||||
|
|
||||||
if (Fortnite_Version >= 18)
|
|
||||||
{
|
{
|
||||||
static auto StormEffectClass = FindObject<UClass>(L"/Game/Athena/SafeZone/GE_OutsideSafeZoneDamage.GE_OutsideSafeZoneDamage_C");
|
static auto StormEffectClass = FindObject<UClass>(L"/Game/Athena/SafeZone/GE_OutsideSafeZoneDamage.GE_OutsideSafeZoneDamage_C");
|
||||||
auto PlayerState = PlayerController->GetPlayerStateAthena();
|
auto PlayerState = PlayerController->GetPlayerStateAthena();
|
||||||
@@ -671,7 +693,7 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
|
|||||||
|
|
||||||
if (NewPawnAsFort)
|
if (NewPawnAsFort)
|
||||||
{
|
{
|
||||||
NewPawnAsFort->SetHealth(100);
|
NewPawnAsFort->SetHealth(100); // needed with server restart player?
|
||||||
|
|
||||||
if (Globals::bLateGame)
|
if (Globals::bLateGame)
|
||||||
NewPawnAsFort->SetShield(100);
|
NewPawnAsFort->SetShield(100);
|
||||||
@@ -907,9 +929,7 @@ AActor* AFortPlayerController::SpawnToyInstanceHook(UObject* Context, FFrame* St
|
|||||||
if (!ToyClass)
|
if (!ToyClass)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
FActorSpawnParameters SpawnParameters{};
|
auto NewToy = GetWorld()->SpawnActor<AActor>(ToyClass, SpawnPosition, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, false, PlayerController));
|
||||||
SpawnParameters.Owner = PlayerController;
|
|
||||||
auto NewToy = GetWorld()->SpawnActor<AActor>(ToyClass, SpawnPosition, SpawnParameters);
|
|
||||||
|
|
||||||
static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances");
|
static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances");
|
||||||
auto& ActiveToyInstances = PlayerController->Get<TArray<AActor*>>(ActiveToyInstancesOffset);
|
auto& ActiveToyInstances = PlayerController->Get<TArray<AActor*>>(ActiveToyInstancesOffset);
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ void AFortPlayerControllerAthena::ServerRestartPlayerHook(AFortPlayerControllerA
|
|||||||
static auto ZoneServerRestartPlayer = __int64(FortPlayerControllerZoneDefault->VFTable[GetFunctionIdxOrPtr(ServerRestartPlayerFn) / 8]);
|
static auto ZoneServerRestartPlayer = __int64(FortPlayerControllerZoneDefault->VFTable[GetFunctionIdxOrPtr(ServerRestartPlayerFn) / 8]);
|
||||||
static void (*ZoneServerRestartPlayerOriginal)(AFortPlayerController*) = decltype(ZoneServerRestartPlayerOriginal)(__int64(ZoneServerRestartPlayer));
|
static void (*ZoneServerRestartPlayerOriginal)(AFortPlayerController*) = decltype(ZoneServerRestartPlayerOriginal)(__int64(ZoneServerRestartPlayer));
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Call 0x{:x}!", ZoneServerRestartPlayer - __int64(_ReturnAddress()));
|
LOG_INFO(LogDev, "Call 0x{:x} returning with 0x{:x}!", ZoneServerRestartPlayer - __int64(_ReturnAddress()), __int64(ZoneServerRestartPlayerOriginal) - __int64(GetModuleHandleW(0)));
|
||||||
return ZoneServerRestartPlayerOriginal(Controller);
|
return ZoneServerRestartPlayerOriginal(Controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "FortItemDefinition.h"
|
#include "FortItemDefinition.h"
|
||||||
|
#include "FortLootLevel.h"
|
||||||
|
|
||||||
enum class EWorldItemDropBehavior : uint8_t
|
enum class EWorldItemDropBehavior : uint8_t
|
||||||
{
|
{
|
||||||
@@ -10,6 +11,16 @@ enum class EWorldItemDropBehavior : uint8_t
|
|||||||
EWorldItemDropBehavior_MAX = 3
|
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
|
class UFortWorldItemDefinition : public UFortItemDefinition
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -26,6 +37,42 @@ public:
|
|||||||
return Get<int>(DropCountOffset);
|
return Get<int>(DropCountOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 GetFinalLevel(int WorldLevel)
|
||||||
|
{
|
||||||
|
auto ItemLevel = UFortLootLevel::GetItemLevel(GetLootLevelData(), WorldLevel);
|
||||||
|
|
||||||
|
return PickLevel(ItemLevel >= 0 ? ItemLevel : 0);
|
||||||
|
}
|
||||||
|
|
||||||
EWorldItemDropBehavior& GetDropBehavior()
|
EWorldItemDropBehavior& GetDropBehavior()
|
||||||
{
|
{
|
||||||
static auto DropBehaviorOffset = GetOffset("DropBehavior");
|
static auto DropBehaviorOffset = GetOffset("DropBehavior");
|
||||||
@@ -85,7 +132,7 @@ public:
|
|||||||
|
|
||||||
static UClass* StaticClass()
|
static UClass* StaticClass()
|
||||||
{
|
{
|
||||||
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortWorldItemDefinition");
|
static auto Class = FindObject<UClass>(L"/Script/FortniteGame.FortWorldItemDefinition");
|
||||||
return Class;
|
return Class;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -4,8 +4,7 @@
|
|||||||
|
|
||||||
#include "TimerManager.h"
|
#include "TimerManager.h"
|
||||||
|
|
||||||
class UGameInstance :
|
class UGameInstance : public UObject
|
||||||
public UObject
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline FTimerManager& GetTimerManager() const
|
inline FTimerManager& GetTimerManager() const
|
||||||
|
|||||||
@@ -110,12 +110,9 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
|
|||||||
FTransform SpawnTransform = StartSpot->GetTransform();
|
FTransform SpawnTransform = StartSpot->GetTransform();
|
||||||
APawn* NewPawn = nullptr;
|
APawn* NewPawn = nullptr;
|
||||||
|
|
||||||
FActorSpawnParameters SpawnParameters{};
|
|
||||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
|
||||||
|
|
||||||
if constexpr (bUseSpawnActor)
|
if constexpr (bUseSpawnActor)
|
||||||
{
|
{
|
||||||
NewPawn = GetWorld()->SpawnActor<APawn>(PawnClass, SpawnTransform, SpawnParameters);
|
NewPawn = GetWorld()->SpawnActor<APawn>(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,13 +9,30 @@ struct FNameEntryId
|
|||||||
FNameEntryId() : Value(0) {}
|
FNameEntryId() : Value(0) {}
|
||||||
|
|
||||||
FNameEntryId(uint32 value) : Value(value) {}
|
FNameEntryId(uint32 value) : Value(value) {}
|
||||||
|
|
||||||
|
bool operator<(FNameEntryId Rhs) const { return Value < Rhs.Value; }
|
||||||
|
bool operator>(FNameEntryId Rhs) const { return Rhs.Value < Value; }
|
||||||
|
bool operator==(FNameEntryId Rhs) const { return Value == Rhs.Value; }
|
||||||
|
bool operator!=(FNameEntryId Rhs) const { return Value != Rhs.Value; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define WITH_CASE_PRESERVING_NAME 1 // ??
|
||||||
|
|
||||||
struct FName
|
struct FName
|
||||||
{
|
{
|
||||||
FNameEntryId ComparisonIndex;
|
FNameEntryId ComparisonIndex;
|
||||||
uint32 Number;
|
uint32 Number;
|
||||||
|
|
||||||
|
FORCEINLINE int32 GetNumber() const
|
||||||
|
{
|
||||||
|
return Number;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCEINLINE FNameEntryId GetComparisonIndexFast() const
|
||||||
|
{
|
||||||
|
return ComparisonIndex;
|
||||||
|
}
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
std::string ToString();
|
std::string ToString();
|
||||||
|
|
||||||
@@ -23,15 +40,36 @@ struct FName
|
|||||||
|
|
||||||
FName(uint32 Value) : ComparisonIndex(Value), Number(0) {}
|
FName(uint32 Value) : ComparisonIndex(Value), Number(0) {}
|
||||||
|
|
||||||
bool IsValid() { return ComparisonIndex.Value > 0; }
|
bool IsValid() { return ComparisonIndex.Value > 0; } // for real
|
||||||
|
|
||||||
bool operator==(FName other)
|
FORCEINLINE bool operator==(const FName& Other) const // HMM??
|
||||||
{
|
{
|
||||||
return ComparisonIndex.Value == other.ComparisonIndex.Value;
|
#if WITH_CASE_PRESERVING_NAME
|
||||||
|
return GetComparisonIndexFast() == Other.GetComparisonIndexFast() && GetNumber() == Other.GetNumber();
|
||||||
|
#else
|
||||||
|
// static_assert(sizeof(CompositeComparisonValue) == sizeof(*this), "ComparisonValue does not cover the entire FName state");
|
||||||
|
// return CompositeComparisonValue == Other.CompositeComparisonValue;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(FName Other) const
|
int32 Compare(const FName& Other) const;
|
||||||
|
|
||||||
|
/* FORCEINLINE bool operator<(const FName& Other) const
|
||||||
{
|
{
|
||||||
return this->ComparisonIndex.Value < Other.ComparisonIndex.Value;
|
return Compare(Other) < 0;
|
||||||
|
} */
|
||||||
|
|
||||||
|
FORCEINLINE bool operator<(const FName& Other) const
|
||||||
|
{
|
||||||
|
return GetComparisonIndexFast() < Other.GetComparisonIndexFast();
|
||||||
|
|
||||||
|
// (Milxnor) BRO IDK
|
||||||
|
|
||||||
|
if (GetComparisonIndexFast() == Other.GetComparisonIndexFast())
|
||||||
|
{
|
||||||
|
return GetNumber() - Other.GetNumber();
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetComparisonIndexFast() < Other.GetComparisonIndexFast();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -189,7 +189,7 @@ UFunction* UObject::FindFunction(const std::string& ShortFunctionName)
|
|||||||
|
|
||||||
/* class UClass* UObject::StaticClass()
|
/* class UClass* UObject::StaticClass()
|
||||||
{
|
{
|
||||||
static auto Class = FindObject<UClass>("/Script/CoreUObject.Object");
|
static auto Class = FindObject<UClass>(L"/Script/CoreUObject.Object");
|
||||||
return Class;
|
return Class;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
@@ -208,9 +208,6 @@ void UObject::AddToRoot()
|
|||||||
|
|
||||||
bool UObject::IsValidLowLevel()
|
bool UObject::IsValidLowLevel()
|
||||||
{
|
{
|
||||||
if (std::floor(Fortnite_Version) == 5) // real 1:1 // todo (milxnor) try without this
|
|
||||||
return !IsBadReadPtr(this, 8);
|
|
||||||
|
|
||||||
if (this == nullptr)
|
if (this == nullptr)
|
||||||
{
|
{
|
||||||
// UE_LOG(LogUObjectBase, Warning, TEXT("NULL object"));
|
// UE_LOG(LogUObjectBase, Warning, TEXT("NULL object"));
|
||||||
|
|||||||
@@ -217,6 +217,7 @@
|
|||||||
<ClCompile Include="FortItem.cpp" />
|
<ClCompile Include="FortItem.cpp" />
|
||||||
<ClCompile Include="FortItemDefinition.cpp" />
|
<ClCompile Include="FortItemDefinition.cpp" />
|
||||||
<ClCompile Include="FortKismetLibrary.cpp" />
|
<ClCompile Include="FortKismetLibrary.cpp" />
|
||||||
|
<ClCompile Include="FortLootLevel.cpp" />
|
||||||
<ClCompile Include="FortLootPackage.cpp" />
|
<ClCompile Include="FortLootPackage.cpp" />
|
||||||
<ClCompile Include="FortMinigame.cpp" />
|
<ClCompile Include="FortMinigame.cpp" />
|
||||||
<ClCompile Include="FortOctopusVehicle.cpp" />
|
<ClCompile Include="FortOctopusVehicle.cpp" />
|
||||||
|
|||||||
@@ -292,6 +292,9 @@
|
|||||||
<ClCompile Include="ScriptDisassembler.cpp">
|
<ClCompile Include="ScriptDisassembler.cpp">
|
||||||
<Filter>Engine\Source\Developer\ScriptDisassembler\Private</Filter>
|
<Filter>Engine\Source\Developer\ScriptDisassembler\Private</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="FortLootLevel.cpp">
|
||||||
|
<Filter>FortniteGame\Source\FortniteGame\Private\Items</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="log.h" />
|
<ClInclude Include="log.h" />
|
||||||
|
|||||||
@@ -89,9 +89,11 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern inline int NumElementsPerChunk = 0x10000;
|
||||||
|
|
||||||
class FChunkedFixedUObjectArray
|
class FChunkedFixedUObjectArray
|
||||||
{
|
{
|
||||||
enum { NumElementsPerChunk = 64 * 1024, };
|
// enum { NumElementsPerChunk = 64 * 1024, };
|
||||||
|
|
||||||
FUObjectItem** Objects;
|
FUObjectItem** Objects;
|
||||||
FUObjectItem* PreAllocatedObjects;
|
FUObjectItem* PreAllocatedObjects;
|
||||||
|
|||||||
@@ -22,6 +22,50 @@ std::string FName::ToString() const
|
|||||||
return Str;
|
return Str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 FName::Compare(const FName& Other) const
|
||||||
|
{
|
||||||
|
if (GetComparisonIndexFast() == Other.GetComparisonIndexFast())
|
||||||
|
{
|
||||||
|
return GetNumber() - Other.GetNumber();
|
||||||
|
}
|
||||||
|
// Names don't match. This means we don't even need to check numbers.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// return ToString() == Other.ToString(); // FOR REAL!! (Milxnor)
|
||||||
|
/* TNameEntryArray& Names = GetNames();
|
||||||
|
const FNameEntry* const ThisEntry = GetComparisonNameEntry();
|
||||||
|
const FNameEntry* const OtherEntry = Other.GetComparisonNameEntry();
|
||||||
|
|
||||||
|
FNameBuffer TempBuffer1;
|
||||||
|
FNameBuffer TempBuffer2;
|
||||||
|
|
||||||
|
// If one or both entries return an invalid name entry, the comparison fails - fallback to comparing the index
|
||||||
|
if (ThisEntry == nullptr || OtherEntry == nullptr)
|
||||||
|
{
|
||||||
|
return GetComparisonIndexFast() - Other.GetComparisonIndexFast();
|
||||||
|
}
|
||||||
|
// Ansi/Wide mismatch, convert to wide
|
||||||
|
else if (ThisEntry->IsWide() != OtherEntry->IsWide())
|
||||||
|
{
|
||||||
|
return FCStringWide::Stricmp(
|
||||||
|
ThisEntry->IsWide() ? ThisEntry->GetWideNamePtr(TempBuffer1.WideName) : StringCast<WIDECHAR>(ThisEntry->GetAnsiNamePtr(TempBuffer1.AnsiName)).Get(),
|
||||||
|
OtherEntry->IsWide() ? OtherEntry->GetWideNamePtr(TempBuffer2.WideName) : StringCast<WIDECHAR>(OtherEntry->GetAnsiNamePtr(TempBuffer2.AnsiName)).Get());
|
||||||
|
}
|
||||||
|
// Both are wide.
|
||||||
|
else if (ThisEntry->IsWide())
|
||||||
|
{
|
||||||
|
return FCStringWide::Stricmp(ThisEntry->GetWideNamePtr(TempBuffer1.WideName), OtherEntry->GetWideNamePtr(TempBuffer2.WideName));
|
||||||
|
}
|
||||||
|
// Both are ansi.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return FCStringAnsi::Stricmp(ThisEntry->GetAnsiNamePtr(TempBuffer1.AnsiName), OtherEntry->GetAnsiNamePtr(TempBuffer2.AnsiName));
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string FName::ToString()
|
std::string FName::ToString()
|
||||||
{
|
{
|
||||||
static auto KismetStringLibrary = FindObject<UKismetStringLibrary>(L"/Script/Engine.Default__KismetStringLibrary");
|
static auto KismetStringLibrary = FindObject<UKismetStringLibrary>(L"/Script/Engine.Default__KismetStringLibrary");
|
||||||
|
|||||||
@@ -35,10 +35,70 @@ struct FActorSpawnParameters
|
|||||||
EObjectFlags ObjectFlags;
|
EObjectFlags ObjectFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FActorSpawnParametersUE500
|
||||||
|
{
|
||||||
|
FName Name = FName(0);
|
||||||
|
UObject* Template = nullptr;
|
||||||
|
UObject* Owner = nullptr;
|
||||||
|
UObject** Instigator = nullptr;
|
||||||
|
UObject* OverrideLevel = nullptr;
|
||||||
|
UObject* OverrideParentComponent;
|
||||||
|
ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined;
|
||||||
|
uint8_t TransformScaleMethod;
|
||||||
|
uint16 bRemoteOwned : 1;
|
||||||
|
uint16 bNoFail : 1;
|
||||||
|
uint16 bDeferConstruction : 1;
|
||||||
|
uint16 bAllowDuringConstructionScript : 1;
|
||||||
|
#if WITH_EDITOR
|
||||||
|
uint16 bTemporaryEditorActor : 1;
|
||||||
|
#endif
|
||||||
|
enum class ESpawnActorNameMode : uint8_t
|
||||||
|
{
|
||||||
|
Required_Fatal,
|
||||||
|
Required_ErrorAndReturnNull,
|
||||||
|
Required_ReturnNull,
|
||||||
|
Requested
|
||||||
|
};
|
||||||
|
|
||||||
|
ESpawnActorNameMode NameMode;
|
||||||
|
EObjectFlags ObjectFlags;
|
||||||
|
TFunction<void(UObject*)> CustomPreSpawnInitalization; // my favorite
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void* CreateSpawnParameters(ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined, bool bDeferConstruction = false, UObject* Owner = nullptr)
|
||||||
|
{
|
||||||
|
if (Engine_Version >= 500)
|
||||||
|
{
|
||||||
|
auto addr = (FActorSpawnParametersUE500*)VirtualAlloc(0, sizeof(FActorSpawnParametersUE500), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
|
||||||
|
if (!addr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
addr->Owner = Owner;
|
||||||
|
addr->bDeferConstruction = bDeferConstruction;
|
||||||
|
addr->SpawnCollisionHandlingOverride = SpawnCollisionHandlingOverride;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto addr = (FActorSpawnParameters*)VirtualAlloc(0, sizeof(FActorSpawnParameters), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
||||||
|
|
||||||
|
if (!addr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
addr->Owner = Owner;
|
||||||
|
addr->bDeferConstruction = bDeferConstruction;
|
||||||
|
addr->SpawnCollisionHandlingOverride = SpawnCollisionHandlingOverride;
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
class UWorld : public UObject, public FNetworkNotify
|
class UWorld : public UObject, public FNetworkNotify
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static inline UObject* (*SpawnActorOriginal)(UWorld* World, UClass* Class, FTransform const* UserTransformPtr, const FActorSpawnParameters& SpawnParameters);
|
static inline UObject* (*SpawnActorOriginal)(UWorld* World, UClass* Class, FTransform const* UserTransformPtr, void* SpawnParameters);
|
||||||
|
|
||||||
template <typename T = AActor>
|
template <typename T = AActor>
|
||||||
T*& GetGameMode()
|
T*& GetGameMode()
|
||||||
@@ -72,19 +132,34 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ActorType>
|
template <typename ActorType>
|
||||||
ActorType* SpawnActor(UClass* Class, FTransform UserTransformPtr = FTransform(), const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters())
|
ActorType* SpawnActor(UClass* Class, FTransform UserTransformPtr = FTransform(), void* SpawnParameters = nullptr)
|
||||||
{
|
{
|
||||||
return (ActorType*)SpawnActorOriginal(this, Class, &UserTransformPtr, SpawnParameters);
|
if (!SpawnParameters)
|
||||||
|
SpawnParameters = CreateSpawnParameters();
|
||||||
|
|
||||||
|
auto actor = (ActorType*)SpawnActorOriginal(this, Class, &UserTransformPtr, SpawnParameters);
|
||||||
|
|
||||||
|
VirtualFree(SpawnParameters, 0, MEM_RELEASE);
|
||||||
|
|
||||||
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ActorType>
|
template <typename ActorType>
|
||||||
ActorType* SpawnActor(UClass* Class, FVector Location, FQuat Rotation = FQuat(), FVector Scale3D = FVector(1, 1, 1), const FActorSpawnParameters& SpawnParameters = FActorSpawnParameters())
|
ActorType* SpawnActor(UClass* Class, FVector Location, FQuat Rotation = FQuat(), FVector Scale3D = FVector(1, 1, 1), void* SpawnParameters = nullptr)
|
||||||
{
|
{
|
||||||
|
if (!SpawnParameters)
|
||||||
|
SpawnParameters = CreateSpawnParameters();
|
||||||
|
|
||||||
FTransform UserTransformPtr{};
|
FTransform UserTransformPtr{};
|
||||||
UserTransformPtr.Translation = Location;
|
UserTransformPtr.Translation = Location;
|
||||||
UserTransformPtr.Rotation = Rotation;
|
UserTransformPtr.Rotation = Rotation;
|
||||||
UserTransformPtr.Scale3D = Scale3D;
|
UserTransformPtr.Scale3D = Scale3D;
|
||||||
return SpawnActor<ActorType>(Class, UserTransformPtr, SpawnParameters);
|
|
||||||
|
auto actor = SpawnActor<ActorType>(Class, UserTransformPtr, SpawnParameters);
|
||||||
|
|
||||||
|
VirtualFree(SpawnParameters, 0, MEM_RELEASE);
|
||||||
|
|
||||||
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
AWorldSettings* GetWorldSettings(bool bCheckStreamingPersistent = false, bool bChecked = true) const;
|
AWorldSettings* GetWorldSettings(bool bCheckStreamingPersistent = false, bool bChecked = true) const;
|
||||||
|
|||||||
@@ -570,7 +570,7 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
|
|||||||
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
|
||||||
toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 55 56 57 41 54 41 55 41 56 41 57 48 8D 68 A8 48 81 EC ? ? ? ? 45").Get()); // GC
|
// toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 55 56 57 41 54 41 55 41 56 41 57 48 8D 68 A8 48 81 EC ? ? ? ? 45").Get()); // GC
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Engine_Version >= 426)
|
if (Engine_Version >= 426)
|
||||||
|
|||||||
@@ -42,11 +42,8 @@ public:
|
|||||||
|
|
||||||
static auto FortAthenaAIBotControllerClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaAIBotController");
|
static auto FortAthenaAIBotControllerClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaAIBotController");
|
||||||
|
|
||||||
FActorSpawnParameters PawnSpawnParameters{};
|
|
||||||
PawnSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
|
||||||
|
|
||||||
Controller = GetWorld()->SpawnActor<AController>(ControllerClass);
|
Controller = GetWorld()->SpawnActor<AController>(ControllerClass);
|
||||||
AFortPlayerPawnAthena* Pawn = GetWorld()->SpawnActor<AFortPlayerPawnAthena>(PawnClass, SpawnTransform, PawnSpawnParameters);
|
AFortPlayerPawnAthena* Pawn = GetWorld()->SpawnActor<AFortPlayerPawnAthena>(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||||
AFortPlayerStateAthena* PlayerState = Cast<AFortPlayerStateAthena>(Controller->GetPlayerState());
|
AFortPlayerStateAthena* PlayerState = Cast<AFortPlayerStateAthena>(Controller->GetPlayerState());
|
||||||
|
|
||||||
if (!Pawn || !PlayerState)
|
if (!Pawn || !PlayerState)
|
||||||
@@ -126,14 +123,10 @@ public:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FActorSpawnParameters InventorySpawnParameters{};
|
|
||||||
InventorySpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
|
||||||
InventorySpawnParameters.Owner = Controller;
|
|
||||||
|
|
||||||
FTransform InventorySpawnTransform{};
|
FTransform InventorySpawnTransform{};
|
||||||
|
|
||||||
static auto FortInventoryClass = FindObject<UClass>("/Script/FortniteGame.FortInventory"); // AFortInventory::StaticClass()
|
static auto FortInventoryClass = FindObject<UClass>("/Script/FortniteGame.FortInventory"); // AFortInventory::StaticClass()
|
||||||
*Inventory = GetWorld()->SpawnActor<AFortInventory>(FortInventoryClass, InventorySpawnTransform, InventorySpawnParameters);
|
*Inventory = GetWorld()->SpawnActor<AFortInventory>(FortInventoryClass, InventorySpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AlwaysSpawn, false, Controller));
|
||||||
|
|
||||||
if (!*Inventory)
|
if (!*Inventory)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,12 +14,13 @@
|
|||||||
|
|
||||||
bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController)
|
bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController)
|
||||||
{
|
{
|
||||||
auto IP = PlayerState->GetPtr<FString>("SavedNetworkAddress");
|
static auto SavedNetworkAddressOffset = PlayerState->GetOffset("SavedNetworkAddress");
|
||||||
|
auto IP = PlayerState->GetPtr<FString>(SavedNetworkAddressOffset);
|
||||||
auto IPStr = IP->ToString();
|
auto IPStr = IP->ToString();
|
||||||
|
|
||||||
// std::cout << "IPStr: " << IPStr << '\n';
|
// std::cout << "IPStr: " << IPStr << '\n';
|
||||||
|
|
||||||
if (IPStr == "127.0.0.1" || IPStr == "68.134.74.228" || IPStr == "26.66.97.190" || IPStr == "68.134.74.228") // || IsOp(PlayerController))
|
if (IPStr == "127.0.0.1" || IPStr == "68.134.74.228" || IPStr == "26.66.97.190") // || IsOp(PlayerController))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -32,7 +33,7 @@ inline void SendMessageToConsole(AFortPlayerController* PlayerController, const
|
|||||||
float MsgLifetime = 1; // unused by ue
|
float MsgLifetime = 1; // unused by ue
|
||||||
FName TypeName = FName(); // auto set to "Event"
|
FName TypeName = FName(); // auto set to "Event"
|
||||||
|
|
||||||
static auto ClientMessageFn = FindObject<UFunction>("/Script/Engine.PlayerController.ClientMessage");
|
static auto ClientMessageFn = FindObject<UFunction>(L"/Script/Engine.PlayerController.ClientMessage");
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
FString S; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
FString S; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
@@ -64,7 +65,10 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
|||||||
auto firstBackslash = OldMsg.find_first_of("\\");
|
auto firstBackslash = OldMsg.find_first_of("\\");
|
||||||
auto lastBackslash = OldMsg.find_last_of("\\");
|
auto lastBackslash = OldMsg.find_last_of("\\");
|
||||||
|
|
||||||
auto& ClientConnections = GetWorld()->Get("NetDriver")->Get<TArray<UObject*>>("ClientConnections");
|
static auto World_NetDriverOffset = GetWorld()->GetOffset("NetDriver");
|
||||||
|
auto WorldNetDriver = GetWorld()->Get(World_NetDriverOffset);
|
||||||
|
static auto ClientConnectionsOffset = WorldNetDriver->GetOffset("ClientConnections");
|
||||||
|
auto& ClientConnections = WorldNetDriver->Get<TArray<UObject*>>(ClientConnectionsOffset);
|
||||||
|
|
||||||
/* if (firstBackslash == lastBackslash)
|
/* if (firstBackslash == lastBackslash)
|
||||||
{
|
{
|
||||||
@@ -442,8 +446,10 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
|||||||
|
|
||||||
auto Location = Pawn->GetActorLocation();
|
auto Location = Pawn->GetActorLocation();
|
||||||
|
|
||||||
|
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||||
|
|
||||||
PickupCreateData CreateData;
|
PickupCreateData CreateData;
|
||||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WID, count, -1);
|
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WID, count, -1, MAX_DURABILITY, WID->GetFinalLevel(GameState->GetWorldLevel()));
|
||||||
CreateData.SpawnLocation = Location;
|
CreateData.SpawnLocation = Location;
|
||||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||||
|
|
||||||
@@ -623,12 +629,9 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
|||||||
|
|
||||||
for (int i = 0; i < Count; i++)
|
for (int i = 0; i < Count; i++)
|
||||||
{
|
{
|
||||||
FActorSpawnParameters SpawnParameters{};
|
|
||||||
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
|
||||||
|
|
||||||
auto Loc = Pawn->GetActorLocation();
|
auto Loc = Pawn->GetActorLocation();
|
||||||
Loc.Z += 1000;
|
Loc.Z += 1000;
|
||||||
auto NewActor = GetWorld()->SpawnActor<AActor>(ClassObj, Loc, FQuat(), FVector(1, 1, 1), SpawnParameters);
|
auto NewActor = GetWorld()->SpawnActor<AActor>(ClassObj, Loc, FQuat(), FVector(1, 1, 1));
|
||||||
|
|
||||||
if (!NewActor)
|
if (!NewActor)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -270,6 +270,8 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
Addresses::SetupVersion();
|
Addresses::SetupVersion();
|
||||||
|
|
||||||
|
NumElementsPerChunk = std::floor(Fortnite_Version) == 5 ? 0x10400 : 0x10000; // DUDE
|
||||||
|
|
||||||
Offsets::FindAll(); // We have to do this before because FindCantBuild uses FortAIController.CreateBuildingActor
|
Offsets::FindAll(); // We have to do this before because FindCantBuild uses FortAIController.CreateBuildingActor
|
||||||
Offsets::Print();
|
Offsets::Print();
|
||||||
|
|
||||||
@@ -525,7 +527,7 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
|
|
||||||
if (bEnableRebooting)
|
if (bEnableRebooting)
|
||||||
{
|
{
|
||||||
auto GameSessionDedicatedAthenaPatch = Memcury::Scanner::FindPattern("3B 41 38 7F 27 48 8B D0 48 8B 41 30 4C 39 04 D0 75 1A 48 8D 96").Get();
|
auto GameSessionDedicatedAthenaPatch = Memcury::Scanner::FindPattern("3B 41 38 7F ? 48 8B D0 48 8B 41 30 4C 39 04 D0 75 ? 48 8D 96").Get(); // todo check this sig more
|
||||||
PatchBytes(GameSessionDedicatedAthenaPatch, { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
|
PatchBytes(GameSessionDedicatedAthenaPatch, { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -643,7 +645,7 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
Hooking::MinHook::Hook(FortWeaponDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"),
|
Hooking::MinHook::Hook(FortWeaponDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"),
|
||||||
AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true);
|
AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true);
|
||||||
|
|
||||||
Hooking::MinHook::Hook(FindObject<UKismetSystemLibrary>("/Script/Engine.Default__KismetSystemLibrary"), FindObject<UFunction>(L"/Script/Engine.KismetSystemLibrary.PrintString"),
|
Hooking::MinHook::Hook(FindObject<UKismetSystemLibrary>(L"/Script/Engine.Default__KismetSystemLibrary"), FindObject<UFunction>(L"/Script/Engine.KismetSystemLibrary.PrintString"),
|
||||||
UKismetSystemLibrary::PrintStringHook, (PVOID*)&UKismetSystemLibrary::PrintStringOriginal, false, true);
|
UKismetSystemLibrary::PrintStringHook, (PVOID*)&UKismetSystemLibrary::PrintStringOriginal, false, true);
|
||||||
|
|
||||||
Hooking::MinHook::Hook((PVOID)Addresses::GetSquadIdForCurrentPlayer, (PVOID)AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook);
|
Hooking::MinHook::Hook((PVOID)Addresses::GetSquadIdForCurrentPlayer, (PVOID)AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook);
|
||||||
@@ -710,6 +712,7 @@ DWORD WINAPI Main(LPVOID)
|
|||||||
AFortPlayerControllerAthena::ServerRequestSeatChangeHook, (PVOID*)&AFortPlayerControllerAthena::ServerRequestSeatChangeOriginal, false);
|
AFortPlayerControllerAthena::ServerRequestSeatChangeHook, (PVOID*)&AFortPlayerControllerAthena::ServerRequestSeatChangeOriginal, false);
|
||||||
|
|
||||||
// if (false)
|
// if (false)
|
||||||
|
if (Fortnite_Version > 6.10) // so on 6.10 there isa param and our little finder dont work for that so
|
||||||
{
|
{
|
||||||
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.StartGhostMode"), // (Milxnor) TODO: This changes to a component in later seasons.
|
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.StartGhostMode"), // (Milxnor) TODO: This changes to a component in later seasons.
|
||||||
AFortPlayerControllerAthena::StartGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::StartGhostModeOriginal, false, true); // We can exec hook since it only gets called via blueprint.
|
AFortPlayerControllerAthena::StartGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::StartGhostModeOriginal, false, true); // We can exec hook since it only gets called via blueprint.
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "events.h"
|
#include "events.h"
|
||||||
#include "FortAthenaMutator_Heist.h"
|
#include "FortAthenaMutator_Heist.h"
|
||||||
#include "BGA.h"
|
#include "BGA.h"
|
||||||
|
#include "vendingmachine.h"
|
||||||
|
|
||||||
#define GAME_TAB 1
|
#define GAME_TAB 1
|
||||||
#define PLAYERS_TAB 2
|
#define PLAYERS_TAB 2
|
||||||
|
|||||||
@@ -129,9 +129,6 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner)
|
|||||||
SpawnTransform.Rotation = VehicleSpawner->GetActorRotation().Quaternion();
|
SpawnTransform.Rotation = VehicleSpawner->GetActorRotation().Quaternion();
|
||||||
SpawnTransform.Scale3D = { 1, 1, 1 };
|
SpawnTransform.Scale3D = { 1, 1, 1 };
|
||||||
|
|
||||||
FActorSpawnParameters SpawnParameters{};
|
|
||||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
|
||||||
|
|
||||||
static auto VehicleClassOffset = VehicleSpawner->GetOffset("VehicleClass", false);
|
static auto VehicleClassOffset = VehicleSpawner->GetOffset("VehicleClass", false);
|
||||||
static auto BGAClass = FindObject<UClass>("/Script/Engine.BlueprintGeneratedClass");
|
static auto BGAClass = FindObject<UClass>("/Script/Engine.BlueprintGeneratedClass");
|
||||||
|
|
||||||
@@ -147,7 +144,7 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetWorld()->SpawnActor<AActor>(StrongVehicleClass, SpawnTransform, SpawnParameters);
|
return GetWorld()->SpawnActor<AActor>(StrongVehicleClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||||
}
|
}
|
||||||
|
|
||||||
static auto FortVehicleItemDefOffset = VehicleSpawner->GetOffset("FortVehicleItemDef");
|
static auto FortVehicleItemDefOffset = VehicleSpawner->GetOffset("FortVehicleItemDef");
|
||||||
@@ -176,12 +173,12 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetWorld()->SpawnActor<AActor>(StrongVehicleActorClass, SpawnTransform, SpawnParameters);
|
return GetWorld()->SpawnActor<AActor>(StrongVehicleActorClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SpawnVehicles2()
|
static inline void SpawnVehicles2()
|
||||||
{
|
{
|
||||||
static auto FortAthenaVehicleSpawnerClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaVehicleSpawner");
|
static auto FortAthenaVehicleSpawnerClass = FindObject<UClass>(L"/Script/FortniteGame.FortAthenaVehicleSpawner");
|
||||||
TArray<AActor*> AllVehicleSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaVehicleSpawnerClass);
|
TArray<AActor*> AllVehicleSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaVehicleSpawnerClass);
|
||||||
|
|
||||||
int AmountOfVehiclesSpawned = 0;
|
int AmountOfVehiclesSpawned = 0;
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
|||||||
auto StoneName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Stone");
|
auto StoneName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Stone");
|
||||||
auto MetalName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Metal");
|
auto MetalName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Metal");
|
||||||
|
|
||||||
static auto StoneItemData = FindObject<UFortResourceItemDefinition>("/Game/Items/ResourcePickups/StoneItemData.StoneItemData");
|
static auto StoneItemData = FindObject<UFortResourceItemDefinition>(L"/Game/Items/ResourcePickups/StoneItemData.StoneItemData");
|
||||||
static auto MetalItemData = FindObject<UFortResourceItemDefinition>("/Game/Items/ResourcePickups/MetalItemData.MetalItemData");
|
static auto MetalItemData = FindObject<UFortResourceItemDefinition>(L"/Game/Items/ResourcePickups/MetalItemData.MetalItemData");
|
||||||
|
|
||||||
// TODO: Pull prices from datatables.
|
// TODO: Pull prices from datatables.
|
||||||
|
|
||||||
@@ -124,10 +124,14 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
|||||||
|
|
||||||
constexpr bool bPrint = false;
|
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)
|
if (LootDrops.size() == 0)
|
||||||
|
{
|
||||||
|
// LOG_WARN(LogGame, "Failed to find LootDrops for vending machine loot tier: {}", LootTier);
|
||||||
|
// ItemCollectorIt--; // retry (?)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
|
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
|
||||||
{
|
{
|
||||||
@@ -168,7 +172,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
|||||||
|
|
||||||
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
|
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
|
||||||
{
|
{
|
||||||
auto ItemEntry = FFortItemEntry::MakeItemEntry(LootDrops[LootDropIt]->GetItemDefinition(), LootDrops[LootDropIt]->GetCount(), LootDrops[LootDropIt]->GetLoadedAmmo());
|
auto ItemEntry = LootDrops[LootDropIt].ItemEntry; // FFortItemEntry::MakeItemEntry(LootDrops[LootDropIt]->GetItemDefinition(), LootDrops[LootDropIt]->GetCount(), LootDrops[LootDropIt]->GetLoadedAmmo(), MAX_DURABILITY, LootDrops[LootDropIt]->GetLevel());
|
||||||
|
|
||||||
if (!ItemEntry)
|
if (!ItemEntry)
|
||||||
continue;
|
continue;
|
||||||
@@ -202,7 +206,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
|||||||
if (StartingGoalLevelOffset != -1)
|
if (StartingGoalLevelOffset != -1)
|
||||||
ItemCollector->Get<int32>(StartingGoalLevelOffset) = LootTier;
|
ItemCollector->Get<int32>(StartingGoalLevelOffset) = LootTier;
|
||||||
|
|
||||||
static auto VendingMachineClass = FindObject<UClass>("/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C");
|
static auto VendingMachineClass = FindObject<UClass>(L"/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C");
|
||||||
|
|
||||||
if (ItemCollector->IsA(VendingMachineClass))
|
if (ItemCollector->IsA(VendingMachineClass))
|
||||||
{
|
{
|
||||||
@@ -274,7 +278,19 @@ static inline void FillVendingMachines()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
FillItemCollector(VendingMachine, OverrideLootTierGroup, Out - 1, true, true);
|
/*
|
||||||
|
|
||||||
|
LOOT LEVELS:
|
||||||
|
|
||||||
|
0 - Common
|
||||||
|
1 - Uncommon
|
||||||
|
2 - Rare
|
||||||
|
3 - Epic
|
||||||
|
4 - Legendary
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
FillItemCollector(VendingMachine, OverrideLootTierGroup, true, Out - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto AllVendingMachinesNum = AllVendingMachines.Num();
|
auto AllVendingMachinesNum = AllVendingMachines.Num();
|
||||||
|
|||||||
Reference in New Issue
Block a user