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* 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() { 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");
|
||||
auto& SpawnLootTierGroup = BGAConsumableSpawner->Get<FName>(SpawnLootTierGroupOffset);
|
||||
|
||||
auto LootDrops = PickLootDrops(SpawnLootTierGroup);
|
||||
auto LootDrops = PickLootDrops(SpawnLootTierGroup, GameState->GetWorldLevel());
|
||||
|
||||
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?
|
||||
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
// 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);
|
||||
auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, bDeferConstruction));
|
||||
|
||||
if (ConsumableActor)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,9 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
||||
|
||||
// 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());
|
||||
|
||||
@@ -25,7 +27,7 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
||||
PickupCreateData CreateData;
|
||||
CreateData.bToss = true;
|
||||
// CreateData.PawnOwner = Pawn;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(lootDrop->GetItemDefinition(), lootDrop->GetCount(), lootDrop->GetLoadedAmmo());
|
||||
CreateData.ItemEntry = lootDrop.ItemEntry;
|
||||
CreateData.SpawnLocation = LocationToSpawnLoot;
|
||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetContainerValue();
|
||||
CreateData.bRandomRotation = true;
|
||||
|
||||
@@ -8,6 +8,12 @@ public:
|
||||
AActor* GetViewTarget();
|
||||
void Possess(class APawn* Pawn);
|
||||
|
||||
FName& GetStateName()
|
||||
{
|
||||
static auto StateNameOffset = GetOffset("StateName");
|
||||
return Get<FName>(StateNameOffset);
|
||||
}
|
||||
|
||||
class APawn*& GetPawn()
|
||||
{
|
||||
static auto PawnOffset = this->GetOffset("Pawn");
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "Object.h"
|
||||
#include "reboot.h"
|
||||
|
||||
#include "Map.h"
|
||||
|
||||
struct FTableRowBase
|
||||
{
|
||||
unsigned char UnknownData00[0x8]; // this is actually structural padding
|
||||
};
|
||||
|
||||
class UDataTable : public UObject
|
||||
{
|
||||
public:
|
||||
@@ -17,7 +23,7 @@ public:
|
||||
|
||||
static UClass* StaticClass()
|
||||
{
|
||||
static auto Class = FindObject<UClass>("/Script/Engine.DataTable");
|
||||
static auto Class = FindObject<UClass>(L"/Script/Engine.DataTable");
|
||||
return Class;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -63,11 +63,8 @@ void AFortAthenaMapInfo::SpawnLlamas()
|
||||
InitialSpawnTransform.Rotation = RandomYawRotator.Quaternion();
|
||||
InitialSpawnTransform.Scale3D = FVector(1, 1, 1);
|
||||
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
SpawnParameters.bDeferConstruction = true;
|
||||
|
||||
auto LlamaStart = GetWorld()->SpawnActor<AFortAthenaSupplyDrop>(GetLlamaClass(), InitialSpawnTransform, SpawnParameters);
|
||||
auto LlamaStart = GetWorld()->SpawnActor<AFortAthenaSupplyDrop>(GetLlamaClass(), InitialSpawnTransform,
|
||||
CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, true));
|
||||
|
||||
// LOG_INFO(LogDev, "LlamaStart: {}", __int64(LlamaStart));
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#include "FortAthenaSupplyDrop.h"
|
||||
#include "FortGameStateAthena.h"
|
||||
|
||||
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
|
||||
{
|
||||
@@ -44,12 +45,15 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnGameModePickupHook(UObject* Context, FF
|
||||
|
||||
LOG_INFO(LogDev, "Spawning GameModePickup with ItemDefinition: {}", ItemDefinition->GetFullName());
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.PawnOwner = TriggeringPawn;
|
||||
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
|
||||
CreateData.OverrideClass = PickupClass;
|
||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||
|
||||
*Ret = AFortPickup::SpawnPickup(CreateData);
|
||||
return *Ret;
|
||||
@@ -74,8 +78,10 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnPickupHook(UObject* Context, FFrame& St
|
||||
if (!ItemDefinition)
|
||||
return nullptr;
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.PawnOwner = TriggeringPawn;
|
||||
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
|
||||
|
||||
@@ -652,6 +652,8 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
|
||||
|
||||
GetWorld()->Listen();
|
||||
|
||||
LOG_INFO(LogNet, "WorldLevel {}", GameState->GetWorldLevel());
|
||||
|
||||
if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer())
|
||||
{
|
||||
TeamsArrayContainer->TeamIndexesArray.Free();
|
||||
@@ -889,6 +891,8 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
|
||||
bShouldSpreadTeams = bIsLargeTeamGame;
|
||||
}
|
||||
|
||||
// bShouldSpreadTeams = true;
|
||||
|
||||
static int CurrentTeamMembers = 0; // bad
|
||||
static int Current = DefaultFirstTeam;
|
||||
static int NextTeamIndex = DefaultFirstTeam;
|
||||
@@ -986,11 +990,14 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
|
||||
{
|
||||
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, "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();
|
||||
Location.Z += UpZ;
|
||||
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, -1, bPrintWarmup);
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, GameState->GetWorldLevel(), -1, bPrintWarmup);
|
||||
|
||||
for (auto& LootDrop : LootDrops)
|
||||
{
|
||||
PickupCreateData CreateData;
|
||||
CreateData.bToss = true;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
||||
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||
CreateData.SpawnLocation = Location;
|
||||
CreateData.SourceType = SpawnFlag;
|
||||
CreateData.bRandomRotation = true;
|
||||
@@ -1160,13 +1167,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
||||
auto Location = CurrentActor->GetActorLocation();
|
||||
Location.Z += UpZ;
|
||||
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, -1, bPrint);
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, GameState->GetWorldLevel(), -1, bPrint);
|
||||
|
||||
for (auto& LootDrop : LootDrops)
|
||||
{
|
||||
PickupCreateData CreateData;
|
||||
CreateData.bToss = true;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
||||
CreateData.ItemEntry = LootDrop.ItemEntry;
|
||||
CreateData.SpawnLocation = Location;
|
||||
CreateData.SourceType = SpawnFlag;
|
||||
CreateData.bRandomRotation = true;
|
||||
|
||||
@@ -105,6 +105,12 @@ public:
|
||||
return this->Get<bool>(bSafeZonePausedOffset);
|
||||
}
|
||||
|
||||
int& GetWorldLevel() // Actually in AFortGameState
|
||||
{
|
||||
static auto WorldLevelOffset = GetOffset("WorldLevel");
|
||||
return Get<int>(WorldLevelOffset);
|
||||
}
|
||||
|
||||
EAthenaGamePhase& GetGamePhase()
|
||||
{
|
||||
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);
|
||||
|
||||
PickupCreateData CreateData;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1);
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1, MAX_DURABILITY/* level */);
|
||||
CreateData.SpawnLocation = Pawn->GetActorLocation();
|
||||
CreateData.PawnOwner = Cast<AFortPawn>(Pawn);
|
||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
|
||||
|
||||
@@ -25,7 +25,7 @@ void FFortItemEntry::SetStateValue(EFortItemEntryState StateType, int IntValue)
|
||||
// ItemEntry->bIsDirty = true;
|
||||
}
|
||||
|
||||
FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability)
|
||||
FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability, int Level)
|
||||
{
|
||||
auto Entry = Alloc<FFortItemEntry>(GetStructSize(), bUseFMemoryRealloc);
|
||||
|
||||
@@ -50,6 +50,7 @@ FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinitio
|
||||
Entry->GetDurability() = Durability;
|
||||
Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1);
|
||||
Entry->GetParentInventory().ObjectIndex = -1;
|
||||
Entry->GetLevel() = Level;
|
||||
// We want to add StateValues.Add(DurabilityInitialized); orwnatefc erwgearf yk
|
||||
// CoCreateGuid((GUID*)&Entry->GetItemGuid());
|
||||
// Entry->DoesUpdateStatsOnCollection() = true; // I think fortnite does this?
|
||||
|
||||
@@ -30,6 +30,8 @@ enum class EFortItemEntryState : uint8_t // this changes but its fineee
|
||||
EFortItemEntryState_MAX = 15
|
||||
};
|
||||
|
||||
#define MAX_DURABILITY 0x3F800000
|
||||
|
||||
struct FFortItemEntryStateValue
|
||||
{
|
||||
static UStruct* GetStruct()
|
||||
@@ -189,7 +191,7 @@ struct FFortItemEntry : FFastArraySerializerItem
|
||||
return StructSize;
|
||||
}
|
||||
|
||||
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000);
|
||||
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 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.
|
||||
|
||||
|
||||
@@ -137,8 +137,10 @@ void UFortKismetLibrary::SpawnItemVariantPickupInWorldHook(UObject* Context, FFr
|
||||
|
||||
LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z);
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.Source = ParamsPtr->GetSource();
|
||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||
@@ -172,8 +174,10 @@ bool UFortKismetLibrary::SpawnInstancedPickupInWorldHook(UObject* Context, FFram
|
||||
Stack.StepCompiledIn(&bRandomRotation);
|
||||
Stack.StepCompiledIn(&bBlockedFromAutoPickup);
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.bToss = bToss;
|
||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||
@@ -226,8 +230,10 @@ void UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHo
|
||||
if (!AmmoDefinition)
|
||||
return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret);
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.Source = SpawnSource;
|
||||
CreateData.SpawnLocation = Location;
|
||||
@@ -508,8 +514,10 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con
|
||||
|
||||
LOG_INFO(LogDev, __FUNCTION__);
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.SourceType = SourceType;
|
||||
CreateData.OverrideClass = PickupClass;
|
||||
@@ -591,8 +599,10 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr
|
||||
|
||||
auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr;
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
PickupCreateData CreateData;
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
|
||||
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1, MAX_DURABILITY, GameState->GetWorldLevel());
|
||||
CreateData.SpawnLocation = Position;
|
||||
CreateData.bToss = bToss;
|
||||
CreateData.bRandomRotation = bRandomRotation;
|
||||
@@ -628,9 +638,11 @@ bool UFortKismetLibrary::PickLootDropsHook(UObject* Context, FFrame& Stack, bool
|
||||
|
||||
FFortItemEntry::FreeArrayOfEntries(OutLootToDropTempBuf);
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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++)
|
||||
{
|
||||
|
||||
71
Project Reboot 3.0/FortLootLevel.cpp
Normal file
71
Project Reboot 3.0/FortLootLevel.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
#include "FortLootLevel.h"
|
||||
#include "FortWorldItemDefinition.h"
|
||||
|
||||
int UFortLootLevel::GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel)
|
||||
{
|
||||
// OMG IM GONNA DIE
|
||||
|
||||
// we should use GetRows but L
|
||||
|
||||
auto DataTable = LootLevelData.DataTable;
|
||||
|
||||
if (!DataTable)
|
||||
return 0;
|
||||
|
||||
if (!LootLevelData.ColumnName.ComparisonIndex.Value)
|
||||
return 0;
|
||||
|
||||
if (!LootLevelData.RowContents.ComparisonIndex.Value)
|
||||
return 0;
|
||||
|
||||
std::vector<FFortLootLevelData*> OurLootLevelDatas;
|
||||
|
||||
for (auto& LootLevelDataPair : LootLevelData.DataTable->GetRowMap<FFortLootLevelData>())
|
||||
{
|
||||
if (LootLevelDataPair.Second->Category != LootLevelData.RowContents)
|
||||
continue;
|
||||
|
||||
OurLootLevelDatas.push_back(LootLevelDataPair.Second);
|
||||
}
|
||||
|
||||
if (OurLootLevelDatas.size() > 0)
|
||||
{
|
||||
int PickedIndex = -1;
|
||||
int PickedLootLevel = 0;
|
||||
|
||||
for (int i = 0; i < OurLootLevelDatas.size(); i++)
|
||||
{
|
||||
auto CurrentLootLevelData = OurLootLevelDatas.at(i);
|
||||
|
||||
if (CurrentLootLevelData->LootLevel <= WorldLevel && CurrentLootLevelData->LootLevel > PickedLootLevel)
|
||||
{
|
||||
PickedLootLevel = CurrentLootLevelData->LootLevel;
|
||||
PickedIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (PickedIndex != -1)
|
||||
{
|
||||
auto PickedLootLevelData = OurLootLevelDatas.at(PickedIndex);
|
||||
|
||||
const auto PickedMinItemLevel = PickedLootLevelData->MinItemLevel;
|
||||
const auto PickedMaxItemLevel = PickedLootLevelData->MaxItemLevel;
|
||||
auto v15 = PickedMaxItemLevel - PickedMinItemLevel;
|
||||
|
||||
if (v15 + 1 <= 0)
|
||||
{
|
||||
v15 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto v16 = (int)(float)((float)((float)rand() * 0.000030518509) * (float)(v15 + 1));
|
||||
if (v16 <= v15)
|
||||
v15 = v16;
|
||||
}
|
||||
|
||||
return v15 + PickedMinItemLevel;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
class UFortLootLevel
|
||||
{
|
||||
int GetItemLevel(FDataTableCategoryHandle LootLevelData, int WorldLevel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
public:
|
||||
static int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel);
|
||||
};
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "UObjectArray.h"
|
||||
#include "GameplayTagContainer.h"
|
||||
#include "FortGameModeAthena.h"
|
||||
#include "FortLootLevel.h"
|
||||
|
||||
struct FFortGameFeatureLootTableData
|
||||
{
|
||||
@@ -13,8 +14,10 @@ struct FFortGameFeatureLootTableData
|
||||
TSoftObjectPtr<UDataTable> LootPackageData;
|
||||
};
|
||||
|
||||
#define LOOTING_MAP_TYPE std::map // uhhh // TODO (Milxnor) switch bad to map
|
||||
|
||||
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;
|
||||
|
||||
@@ -32,8 +35,8 @@ void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, std::map<
|
||||
{
|
||||
auto CompositeDataTable = DataTable;
|
||||
|
||||
static auto ParentTablesOffset = DataTable->GetOffset("ParentTables");
|
||||
auto& ParentTables = DataTable->Get<TArray<UDataTable*>>(ParentTablesOffset);
|
||||
static auto ParentTablesOffset = CompositeDataTable->GetOffset("ParentTables");
|
||||
auto& ParentTables = CompositeDataTable->Get<TArray<UDataTable*>>(ParentTablesOffset);
|
||||
|
||||
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())
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops)
|
||||
{
|
||||
if (LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryWeightArray().Num()
|
||||
@@ -145,7 +146,7 @@ float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int Origina
|
||||
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.
|
||||
|
||||
@@ -153,45 +154,47 @@ FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& LTDTables, F
|
||||
|
||||
if (LootTier == -1)
|
||||
{
|
||||
// LootTier = 0;
|
||||
// LootTier = ??
|
||||
}
|
||||
else
|
||||
{
|
||||
// buncha code im too lazy to reverse
|
||||
}
|
||||
|
||||
// IDIakuuyg8712u091fj120gvik
|
||||
|
||||
// if (fabs(LootTier) <= 0.0000000099999999)
|
||||
// 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 {
|
||||
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;
|
||||
});
|
||||
|
||||
// LOG_INFO(LogDev, "TierGroupLTDs.size(): {}", TierGroupLTDs.size());
|
||||
|
||||
FFortLootTierData* ChosenRowLootTierData = PickWeightedElement<FName, FFortLootTierData*>(TierGroupLTDs,
|
||||
[](FFortLootTierData* LootTierData) -> float { return LootTierData->GetWeight(); }, RandomFloatForLoot, -1,
|
||||
true, LootTier == -1 ? 1 : LootTier, OutRowName);
|
||||
|
||||
if (!ChosenRowLootTierData)
|
||||
return nullptr;
|
||||
true, Multiplier, OutRowName);
|
||||
|
||||
return ChosenRowLootTierData;
|
||||
}
|
||||
|
||||
void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, const FName& LootPackageName, std::vector<LootDrop>* OutEntries, int LootPackageCategory = -1, bool bPrint = false)
|
||||
void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, const FName& LootPackageName, std::vector<LootDrop>* OutEntries, int LootPackageCategory = -1, int WorldLevel = 0, bool bPrint = false)
|
||||
{
|
||||
if (!OutEntries)
|
||||
return;
|
||||
|
||||
std::map<FName, FFortLootPackageData*> LootPackageIDMap;
|
||||
LOOTING_MAP_TYPE<FName, FFortLootPackageData*> LootPackageIDMap;
|
||||
|
||||
CollectDataTablesRows<FFortLootPackageData>(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool {
|
||||
if (LootPackage->GetLootPackageID() != LootPackageName)
|
||||
@@ -204,14 +207,14 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
return false;
|
||||
}
|
||||
|
||||
/* if (WorldLevel >= 0)
|
||||
if (WorldLevel >= 0)
|
||||
{
|
||||
if (LootPackage->MaxWorldLevel >= 0 && WorldLevel > LootPackage->MaxWorldLevel)
|
||||
if (LootPackage->GetMaxWorldLevel() >= 0 && WorldLevel > LootPackage->GetMaxWorldLevel())
|
||||
return 0;
|
||||
|
||||
if (LootPackage->MinWorldLevel >= 0 && WorldLevel < LootPackage->MinWorldLevel)
|
||||
if (LootPackage->GetMinWorldLevel() >= 0 && WorldLevel < LootPackage->GetMinWorldLevel())
|
||||
return 0;
|
||||
} */
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
@@ -245,7 +248,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
|
||||
PickLootDropsFromLootPackage(LPTables,
|
||||
PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0),
|
||||
OutEntries, LootPackageCategoryToUseForLPCall, bPrint
|
||||
OutEntries, LootPackageCategoryToUseForLPCall, WorldLevel, bPrint
|
||||
);
|
||||
|
||||
v9++;
|
||||
@@ -263,15 +266,15 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
return;
|
||||
}
|
||||
|
||||
int ItemLevel = 0;
|
||||
|
||||
auto WeaponItemDefinition = Cast<UFortWeaponItemDefinition>(ItemDefinition);
|
||||
int LoadedAmmo = WeaponItemDefinition ? WeaponItemDefinition->GetClipSize() : 0; // we shouldnt set loaded ammo here techinally
|
||||
|
||||
if (auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemDefinition))
|
||||
{
|
||||
ItemLevel = 0; // GetItemLevel(WorldItemDefinition->LootLevelData, 0);
|
||||
}
|
||||
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemDefinition);
|
||||
|
||||
if (!WorldItemDefinition) // hahahah not proper!!
|
||||
return;
|
||||
|
||||
int ItemLevel = UFortLootLevel::GetItemLevel(WorldItemDefinition->GetLootLevelData(), WorldLevel);
|
||||
|
||||
int CountMultiplier = 1;
|
||||
int FinalCount = CountMultiplier * PickedPackage->GetCount();
|
||||
@@ -285,9 +288,19 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
|
||||
while (FinalCount > 0)
|
||||
{
|
||||
int CurrentCountForEntry = PickedPackage->GetCount(); // Idk calls some itemdefinition vfunc
|
||||
int MaxStackSize = ItemDefinition->GetMaxStackSize();
|
||||
|
||||
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo)));
|
||||
int CurrentCountForEntry = MaxStackSize;
|
||||
|
||||
if (FinalCount <= MaxStackSize)
|
||||
CurrentCountForEntry = FinalCount;
|
||||
|
||||
if (CurrentCountForEntry <= 0)
|
||||
CurrentCountForEntry = 0;
|
||||
|
||||
auto ActualItemLevel = WorldItemDefinition->PickLevel(FinalItemLevel);
|
||||
|
||||
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo, 0x3F800000, ActualItemLevel)));
|
||||
|
||||
if (Engine_Version >= 424)
|
||||
{
|
||||
@@ -328,7 +341,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
|
||||
|
||||
// #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;
|
||||
|
||||
@@ -636,10 +649,11 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
||||
}
|
||||
|
||||
FName LootTierRowName;
|
||||
auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, 0, ForcedLootTier, &LootTierRowName);
|
||||
auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, ForcedLootTier, &LootTierRowName);
|
||||
|
||||
if (!ChosenRowLootTierData)
|
||||
{
|
||||
LOG_INFO(LogLoot, "Failed to find LootTierData row for {} with loot tier {}", TierGroupName.ToString(), ForcedLootTier);
|
||||
return LootDrops;
|
||||
}
|
||||
else if (bPrint)
|
||||
@@ -690,7 +704,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier, boo
|
||||
|
||||
int LootPackageCategory = i;
|
||||
|
||||
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, bPrint);
|
||||
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, WorldLevel, bPrint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <map>
|
||||
@@ -49,6 +50,18 @@ public:
|
||||
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()
|
||||
{
|
||||
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) {
|
||||
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;
|
||||
@@ -154,7 +170,7 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map<KeyType, ValueTy
|
||||
|
||||
if (bPrint)
|
||||
{
|
||||
LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {}", RandomNumber, TotalWeight);
|
||||
LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {} Elements.size(): {}", RandomNumber, TotalWeight, Elements.size());
|
||||
}
|
||||
|
||||
for (auto& Element : Elements)
|
||||
@@ -181,4 +197,62 @@ FORCEINLINE static ValueType PickWeightedElement(const std::map<KeyType, ValueTy
|
||||
return ValueType();
|
||||
}
|
||||
|
||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0);
|
||||
|
||||
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");
|
||||
auto PlayerState = PickupData.PawnOwner ? Cast<AFortPlayerState>(PickupData.PawnOwner->GetPlayerState()) : nullptr;
|
||||
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
|
||||
auto Pickup = GetWorld()->SpawnActor<AFortPickup>(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1), SpawnParameters);
|
||||
auto Pickup = GetWorld()->SpawnActor<AFortPickup>(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1));
|
||||
|
||||
if (!Pickup)
|
||||
return nullptr;
|
||||
@@ -270,7 +267,7 @@ void AFortPickup::CombinePickupHook(AFortPickup* Pickup)
|
||||
auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner();
|
||||
|
||||
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.PawnOwner = ItemOwner;
|
||||
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
|
||||
@@ -380,8 +377,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
||||
|
||||
if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped && ItemDefGoingInPrimary) // swap
|
||||
{
|
||||
auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc,
|
||||
EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn);
|
||||
auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc, EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn);
|
||||
|
||||
auto CurrentWeapon = Pawn->GetCurrentWeapon();
|
||||
|
||||
|
||||
@@ -592,7 +592,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
||||
auto Entry = ItemCollection->GetOutputItemEntry()->AtPtr(z, FFortItemEntry::GetStructSize());
|
||||
|
||||
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.PawnOwner = PlayerController->GetMyFortPawn(); // hmm
|
||||
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||
@@ -627,9 +627,6 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
|
||||
if (Engine_Version < 424 && !Globals::bLateGame.load())
|
||||
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)
|
||||
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
||||
|
||||
@@ -637,32 +634,57 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
|
||||
// return;
|
||||
|
||||
auto GameMode = (AFortGameModeAthena*)GetWorld()->GetGameMode();
|
||||
auto GameState = GameMode->GetGameStateAthena();
|
||||
|
||||
AActor* AircraftToJumpFrom = nullptr;
|
||||
|
||||
static auto AircraftsOffset = GameState->GetOffset("Aircrafts", false);
|
||||
|
||||
if (AircraftsOffset == -1)
|
||||
if (false)
|
||||
{
|
||||
static auto AircraftOffset = GameState->GetOffset("Aircraft");
|
||||
AircraftToJumpFrom = GameState->Get<AActor*>(AircraftOffset);
|
||||
auto GameState = GameMode->GetGameStateAthena();
|
||||
|
||||
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
|
||||
{
|
||||
auto Aircrafts = GameState->GetPtr<TArray<AActor*>>(AircraftsOffset);
|
||||
AircraftToJumpFrom = Aircrafts->Num() > 0 ? Aircrafts->at(0) : nullptr;
|
||||
if (false)
|
||||
{
|
||||
// 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)
|
||||
return ServerAttemptAircraftJumpOriginal(PC, ClientRotation);
|
||||
auto NewPawnAsFort = PlayerController->GetMyFortPawn();
|
||||
|
||||
auto NewPawn = GameMode->SpawnDefaultPawnForHook(GameMode, (AController*)PlayerController, AircraftToJumpFrom);
|
||||
PlayerController->Possess(NewPawn);
|
||||
|
||||
auto NewPawnAsFort = Cast<AFortPawn>(NewPawn);
|
||||
|
||||
if (Fortnite_Version >= 18)
|
||||
if (Fortnite_Version >= 18) // TODO (Milxnor) Find a better fix and move this
|
||||
{
|
||||
static auto StormEffectClass = FindObject<UClass>(L"/Game/Athena/SafeZone/GE_OutsideSafeZoneDamage.GE_OutsideSafeZoneDamage_C");
|
||||
auto PlayerState = PlayerController->GetPlayerStateAthena();
|
||||
@@ -671,7 +693,7 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
|
||||
|
||||
if (NewPawnAsFort)
|
||||
{
|
||||
NewPawnAsFort->SetHealth(100);
|
||||
NewPawnAsFort->SetHealth(100); // needed with server restart player?
|
||||
|
||||
if (Globals::bLateGame)
|
||||
NewPawnAsFort->SetShield(100);
|
||||
@@ -907,9 +929,7 @@ AActor* AFortPlayerController::SpawnToyInstanceHook(UObject* Context, FFrame* St
|
||||
if (!ToyClass)
|
||||
return nullptr;
|
||||
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
SpawnParameters.Owner = PlayerController;
|
||||
auto NewToy = GetWorld()->SpawnActor<AActor>(ToyClass, SpawnPosition, SpawnParameters);
|
||||
auto NewToy = GetWorld()->SpawnActor<AActor>(ToyClass, SpawnPosition, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, false, PlayerController));
|
||||
|
||||
static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances");
|
||||
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 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "FortItemDefinition.h"
|
||||
#include "FortLootLevel.h"
|
||||
|
||||
enum class EWorldItemDropBehavior : uint8_t
|
||||
{
|
||||
@@ -10,6 +11,16 @@ enum class EWorldItemDropBehavior : uint8_t
|
||||
EWorldItemDropBehavior_MAX = 3
|
||||
};
|
||||
|
||||
struct FFortLootLevelData : public FTableRowBase
|
||||
{
|
||||
public:
|
||||
FName Category; // 0x8(0x8)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
int32 LootLevel; // 0x10(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
int32 MinItemLevel; // 0x14(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
int32 MaxItemLevel; // 0x18(0x4)(Edit, BlueprintVisible, BlueprintReadOnly, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
uint8 Pad_B94[0x4]; // Fixing Size Of Struct [ Dumper-7 ]
|
||||
};
|
||||
|
||||
class UFortWorldItemDefinition : public UFortItemDefinition
|
||||
{
|
||||
public:
|
||||
@@ -26,6 +37,42 @@ public:
|
||||
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()
|
||||
{
|
||||
static auto DropBehaviorOffset = GetOffset("DropBehavior");
|
||||
@@ -85,7 +132,7 @@ public:
|
||||
|
||||
static UClass* StaticClass()
|
||||
{
|
||||
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortWorldItemDefinition");
|
||||
static auto Class = FindObject<UClass>(L"/Script/FortniteGame.FortWorldItemDefinition");
|
||||
return Class;
|
||||
}
|
||||
};
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
#include "TimerManager.h"
|
||||
|
||||
class UGameInstance :
|
||||
public UObject
|
||||
class UGameInstance : public UObject
|
||||
{
|
||||
public:
|
||||
inline FTimerManager& GetTimerManager() const
|
||||
|
||||
@@ -110,12 +110,9 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
|
||||
FTransform SpawnTransform = StartSpot->GetTransform();
|
||||
APawn* NewPawn = nullptr;
|
||||
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
|
||||
if constexpr (bUseSpawnActor)
|
||||
{
|
||||
NewPawn = GetWorld()->SpawnActor<APawn>(PawnClass, SpawnTransform, SpawnParameters);
|
||||
NewPawn = GetWorld()->SpawnActor<APawn>(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -9,13 +9,30 @@ struct FNameEntryId
|
||||
FNameEntryId() : Value(0) {}
|
||||
|
||||
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
|
||||
{
|
||||
FNameEntryId ComparisonIndex;
|
||||
uint32 Number;
|
||||
|
||||
FORCEINLINE int32 GetNumber() const
|
||||
{
|
||||
return Number;
|
||||
}
|
||||
|
||||
FORCEINLINE FNameEntryId GetComparisonIndexFast() const
|
||||
{
|
||||
return ComparisonIndex;
|
||||
}
|
||||
|
||||
std::string ToString() const;
|
||||
std::string ToString();
|
||||
|
||||
@@ -23,15 +40,36 @@ struct FName
|
||||
|
||||
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()
|
||||
{
|
||||
static auto Class = FindObject<UClass>("/Script/CoreUObject.Object");
|
||||
static auto Class = FindObject<UClass>(L"/Script/CoreUObject.Object");
|
||||
return Class;
|
||||
} */
|
||||
|
||||
@@ -208,9 +208,6 @@ void UObject::AddToRoot()
|
||||
|
||||
bool UObject::IsValidLowLevel()
|
||||
{
|
||||
if (std::floor(Fortnite_Version) == 5) // real 1:1 // todo (milxnor) try without this
|
||||
return !IsBadReadPtr(this, 8);
|
||||
|
||||
if (this == nullptr)
|
||||
{
|
||||
// UE_LOG(LogUObjectBase, Warning, TEXT("NULL object"));
|
||||
|
||||
@@ -217,6 +217,7 @@
|
||||
<ClCompile Include="FortItem.cpp" />
|
||||
<ClCompile Include="FortItemDefinition.cpp" />
|
||||
<ClCompile Include="FortKismetLibrary.cpp" />
|
||||
<ClCompile Include="FortLootLevel.cpp" />
|
||||
<ClCompile Include="FortLootPackage.cpp" />
|
||||
<ClCompile Include="FortMinigame.cpp" />
|
||||
<ClCompile Include="FortOctopusVehicle.cpp" />
|
||||
|
||||
@@ -292,6 +292,9 @@
|
||||
<ClCompile Include="ScriptDisassembler.cpp">
|
||||
<Filter>Engine\Source\Developer\ScriptDisassembler\Private</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FortLootLevel.cpp">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Private\Items</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="log.h" />
|
||||
|
||||
@@ -89,9 +89,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
extern inline int NumElementsPerChunk = 0x10000;
|
||||
|
||||
class FChunkedFixedUObjectArray
|
||||
{
|
||||
enum { NumElementsPerChunk = 64 * 1024, };
|
||||
// enum { NumElementsPerChunk = 64 * 1024, };
|
||||
|
||||
FUObjectItem** Objects;
|
||||
FUObjectItem* PreAllocatedObjects;
|
||||
|
||||
@@ -22,6 +22,50 @@ std::string FName::ToString() const
|
||||
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()
|
||||
{
|
||||
static auto KismetStringLibrary = FindObject<UKismetStringLibrary>(L"/Script/Engine.Default__KismetStringLibrary");
|
||||
|
||||
@@ -35,10 +35,70 @@ struct FActorSpawnParameters
|
||||
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
|
||||
{
|
||||
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>
|
||||
T*& GetGameMode()
|
||||
@@ -72,19 +132,34 @@ public:
|
||||
}
|
||||
|
||||
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>
|
||||
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{};
|
||||
UserTransformPtr.Translation = Location;
|
||||
UserTransformPtr.Rotation = Rotation;
|
||||
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;
|
||||
|
||||
@@ -570,7 +570,7 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
|
||||
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 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)
|
||||
|
||||
@@ -42,11 +42,8 @@ public:
|
||||
|
||||
static auto FortAthenaAIBotControllerClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaAIBotController");
|
||||
|
||||
FActorSpawnParameters PawnSpawnParameters{};
|
||||
PawnSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
|
||||
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());
|
||||
|
||||
if (!Pawn || !PlayerState)
|
||||
@@ -126,14 +123,10 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
FActorSpawnParameters InventorySpawnParameters{};
|
||||
InventorySpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
||||
InventorySpawnParameters.Owner = Controller;
|
||||
|
||||
FTransform InventorySpawnTransform{};
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -14,12 +14,13 @@
|
||||
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -32,7 +33,7 @@ inline void SendMessageToConsole(AFortPlayerController* PlayerController, const
|
||||
float MsgLifetime = 1; // unused by ue
|
||||
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
|
||||
{
|
||||
FString S; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
@@ -64,7 +65,10 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
||||
auto firstBackslash = OldMsg.find_first_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)
|
||||
{
|
||||
@@ -442,8 +446,10 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
||||
|
||||
auto Location = Pawn->GetActorLocation();
|
||||
|
||||
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
|
||||
|
||||
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.bShouldFreeItemEntryWhenDeconstructed = true;
|
||||
|
||||
@@ -623,12 +629,9 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
||||
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
|
||||
auto Loc = Pawn->GetActorLocation();
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -270,6 +270,8 @@ DWORD WINAPI Main(LPVOID)
|
||||
|
||||
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::Print();
|
||||
|
||||
@@ -525,7 +527,7 @@ DWORD WINAPI Main(LPVOID)
|
||||
|
||||
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 });
|
||||
}
|
||||
|
||||
@@ -643,7 +645,7 @@ DWORD WINAPI Main(LPVOID)
|
||||
Hooking::MinHook::Hook(FortWeaponDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"),
|
||||
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);
|
||||
|
||||
Hooking::MinHook::Hook((PVOID)Addresses::GetSquadIdForCurrentPlayer, (PVOID)AFortGameSessionDedicatedAthena::GetSquadIdForCurrentPlayerHook);
|
||||
@@ -710,6 +712,7 @@ DWORD WINAPI Main(LPVOID)
|
||||
AFortPlayerControllerAthena::ServerRequestSeatChangeHook, (PVOID*)&AFortPlayerControllerAthena::ServerRequestSeatChangeOriginal, 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.
|
||||
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 "FortAthenaMutator_Heist.h"
|
||||
#include "BGA.h"
|
||||
#include "vendingmachine.h"
|
||||
|
||||
#define GAME_TAB 1
|
||||
#define PLAYERS_TAB 2
|
||||
|
||||
@@ -129,9 +129,6 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner)
|
||||
SpawnTransform.Rotation = VehicleSpawner->GetActorRotation().Quaternion();
|
||||
SpawnTransform.Scale3D = { 1, 1, 1 };
|
||||
|
||||
FActorSpawnParameters SpawnParameters{};
|
||||
SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
|
||||
|
||||
static auto VehicleClassOffset = VehicleSpawner->GetOffset("VehicleClass", false);
|
||||
static auto BGAClass = FindObject<UClass>("/Script/Engine.BlueprintGeneratedClass");
|
||||
|
||||
@@ -147,7 +144,7 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GetWorld()->SpawnActor<AActor>(StrongVehicleClass, SpawnTransform, SpawnParameters);
|
||||
return GetWorld()->SpawnActor<AActor>(StrongVehicleClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||
}
|
||||
|
||||
static auto FortVehicleItemDefOffset = VehicleSpawner->GetOffset("FortVehicleItemDef");
|
||||
@@ -176,12 +173,12 @@ static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GetWorld()->SpawnActor<AActor>(StrongVehicleActorClass, SpawnTransform, SpawnParameters);
|
||||
return GetWorld()->SpawnActor<AActor>(StrongVehicleActorClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
int AmountOfVehiclesSpawned = 0;
|
||||
|
||||
@@ -90,8 +90,8 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
||||
auto StoneName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Stone");
|
||||
auto MetalName = UKismetStringLibrary::Conv_StringToName(L"Default.VendingMachine.Cost.Metal");
|
||||
|
||||
static auto StoneItemData = FindObject<UFortResourceItemDefinition>("/Game/Items/ResourcePickups/StoneItemData.StoneItemData");
|
||||
static auto MetalItemData = FindObject<UFortResourceItemDefinition>("/Game/Items/ResourcePickups/MetalItemData.MetalItemData");
|
||||
static auto StoneItemData = FindObject<UFortResourceItemDefinition>(L"/Game/Items/ResourcePickups/StoneItemData.StoneItemData");
|
||||
static auto MetalItemData = FindObject<UFortResourceItemDefinition>(L"/Game/Items/ResourcePickups/MetalItemData.MetalItemData");
|
||||
|
||||
// TODO: Pull prices from datatables.
|
||||
|
||||
@@ -124,10 +124,14 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
||||
|
||||
constexpr bool bPrint = false;
|
||||
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(LootTierGroup, LootTier, bPrint);
|
||||
std::vector<LootDrop> LootDrops = PickLootDrops(LootTierGroup, GameState->GetWorldLevel(), LootTier, bPrint);
|
||||
|
||||
if (LootDrops.size() == 0)
|
||||
{
|
||||
// LOG_WARN(LogGame, "Failed to find LootDrops for vending machine loot tier: {}", LootTier);
|
||||
// ItemCollectorIt--; // retry (?)
|
||||
continue;
|
||||
}
|
||||
|
||||
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++)
|
||||
{
|
||||
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)
|
||||
continue;
|
||||
@@ -202,7 +206,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
||||
if (StartingGoalLevelOffset != -1)
|
||||
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))
|
||||
{
|
||||
@@ -274,7 +278,19 @@ static inline void FillVendingMachines()
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user