mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
abundant update
complete looting rewrite, improve combining pickups, add debug printing logs, fix some agids, fix cheat summon, fix issue with vehicle spawning.
This commit is contained in:
@@ -35,11 +35,6 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
|
|||||||
|
|
||||||
auto MapInfo = GameState->GetMapInfo();
|
auto MapInfo = GameState->GetMapInfo();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// SpawnLocation.Z += 100;
|
|
||||||
// SpawnLocation.Z -= 50; // proper frfr
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup");
|
static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup");
|
||||||
auto& SpawnLootTierGroup = BGAConsumableSpawner->Get<FName>(SpawnLootTierGroupOffset);
|
auto& SpawnLootTierGroup = BGAConsumableSpawner->Get<FName>(SpawnLootTierGroupOffset);
|
||||||
@@ -48,8 +43,8 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
|
|||||||
|
|
||||||
for (auto& LootDrop : LootDrops)
|
for (auto& LootDrop : LootDrops)
|
||||||
{
|
{
|
||||||
static auto ConsumableClassOffset = LootDrop.ItemDefinition->GetOffset("ConsumableClass");
|
static auto ConsumableClassOffset = LootDrop->GetItemDefinition()->GetOffset("ConsumableClass");
|
||||||
auto ConsumableClassSoft = LootDrop.ItemDefinition->GetPtr<TSoftObjectPtr<UClass>>(ConsumableClassOffset);
|
auto ConsumableClassSoft = LootDrop->GetItemDefinition()->GetPtr<TSoftObjectPtr<UClass>>(ConsumableClassOffset);
|
||||||
|
|
||||||
static auto BlueprintGeneratedClassClass = FindObject<UClass>(L"/Script/Engine.BlueprintGeneratedClass");
|
static auto BlueprintGeneratedClassClass = FindObject<UClass>(L"/Script/Engine.BlueprintGeneratedClass");
|
||||||
auto StrongConsumableClass = ConsumableClassSoft->Get(BlueprintGeneratedClassClass, true);
|
auto StrongConsumableClass = ConsumableClassSoft->Get(BlueprintGeneratedClassClass, true);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "FortPickup.h"
|
#include "FortPickup.h"
|
||||||
#include "FortLootPackage.h"
|
#include "FortLootPackage.h"
|
||||||
#include "FortGameModeAthena.h"
|
#include "FortGameModeAthena.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
||||||
{
|
{
|
||||||
@@ -12,14 +13,14 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
|
|||||||
|
|
||||||
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
|
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
|
||||||
|
|
||||||
auto LootDrops = PickLootDrops(RedirectedLootTier, true);
|
auto LootDrops = PickLootDrops(RedirectedLootTier, bDebugPrintLooting);
|
||||||
|
|
||||||
// LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
|
// LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
|
||||||
|
|
||||||
for (int i = 0; i < LootDrops.size(); i++)
|
for (int i = 0; i < LootDrops.size(); i++)
|
||||||
{
|
{
|
||||||
auto& lootDrop = LootDrops.at(i);
|
auto& lootDrop = LootDrops.at(i);
|
||||||
AFortPickup::SpawnPickup(lootDrop.ItemDefinition, LocationToSpawnLoot, lootDrop.Count, EFortPickupSourceTypeFlag::Container, EFortPickupSpawnSource::Unset, lootDrop.LoadedAmmo);
|
AFortPickup::SpawnPickup(lootDrop->GetItemDefinition(), LocationToSpawnLoot, lootDrop->GetCount(), EFortPickupSourceTypeFlag::Container, EFortPickupSpawnSource::Unset, lootDrop->GetLoadedAmmo());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -34,3 +34,10 @@ struct RowNameAndRowData
|
|||||||
FName RowName;
|
FName RowName;
|
||||||
StructType* RowData;
|
StructType* RowData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FDataTableCategoryHandle
|
||||||
|
{
|
||||||
|
UDataTable* DataTable; // 0x0000(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
FName ColumnName; // 0x0008(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
FName RowContents; // 0x0010(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
};
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ void AFortAthenaMapInfo::SpawnLlamas()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AmountOfLlamasSpawned = 0;
|
||||||
auto AmountOfLlamasToSpawn = CalcuateCurveMinAndMax(GetLlamaQuantityMin(), GetLlamaQuantityMax(), 1);
|
auto AmountOfLlamasToSpawn = CalcuateCurveMinAndMax(GetLlamaQuantityMin(), GetLlamaQuantityMax(), 1);
|
||||||
|
|
||||||
LOG_INFO(LogDev, "Attempting to spawn {} llamas.", AmountOfLlamasToSpawn);
|
LOG_INFO(LogDev, "Attempting to spawn {} llamas.", AmountOfLlamasToSpawn);
|
||||||
@@ -67,7 +68,7 @@ void AFortAthenaMapInfo::SpawnLlamas()
|
|||||||
|
|
||||||
auto LlamaStart = GetWorld()->SpawnActor<AFortAthenaSupplyDrop>(GetLlamaClass(), InitialSpawnTransform, SpawnParameters);
|
auto LlamaStart = GetWorld()->SpawnActor<AFortAthenaSupplyDrop>(GetLlamaClass(), InitialSpawnTransform, SpawnParameters);
|
||||||
|
|
||||||
LOG_INFO(LogDev, "LlamaStart: {}", __int64(LlamaStart));
|
// LOG_INFO(LogDev, "LlamaStart: {}", __int64(LlamaStart));
|
||||||
|
|
||||||
if (!LlamaStart)
|
if (!LlamaStart)
|
||||||
continue;
|
continue;
|
||||||
@@ -80,5 +81,8 @@ void AFortAthenaMapInfo::SpawnLlamas()
|
|||||||
LOG_INFO(LogDev, "Spawning Llama at {} {} {}", GroundLocation.X, GroundLocation.Y, GroundLocation.Z);
|
LOG_INFO(LogDev, "Spawning Llama at {} {} {}", GroundLocation.X, GroundLocation.Y, GroundLocation.Z);
|
||||||
|
|
||||||
UGameplayStatics::FinishSpawningActor(LlamaStart, FinalSpawnTransform);
|
UGameplayStatics::FinishSpawningActor(LlamaStart, FinalSpawnTransform);
|
||||||
|
AmountOfLlamasSpawned++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_INFO(LogGame, "Spawned {} llamas.", AmountOfLlamasSpawned);
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,15 @@ public:
|
|||||||
return GetPawnAtSeat_Params.ReturnValue;
|
return GetPawnAtSeat_Params.ReturnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FindSeatIndex(class AFortPlayerPawn* PlayerPawn)
|
||||||
|
{
|
||||||
|
static auto FindSeatIndexFn = FindObject<UFunction>("/Script/FortniteGame.FortAthenaVehicle.FindSeatIndex");
|
||||||
|
struct { AFortPlayerPawn* PlayerPawn; int ReturnValue; } AFortAthenaVehicle_FindSeatIndex_Params{ PlayerPawn };
|
||||||
|
this->ProcessEvent(FindSeatIndexFn, &AFortAthenaVehicle_FindSeatIndex_Params);
|
||||||
|
|
||||||
|
return AFortAthenaVehicle_FindSeatIndex_Params.ReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
UFortWeaponItemDefinition* GetVehicleWeaponForSeat(int SeatIdx);
|
UFortWeaponItemDefinition* GetVehicleWeaponForSeat(int SeatIdx);
|
||||||
|
|
||||||
static UClass* StaticClass()
|
static UClass* StaticClass()
|
||||||
|
|||||||
@@ -963,7 +963,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
{
|
{
|
||||||
for (auto& LootDrop : LootDrops)
|
for (auto& LootDrop : LootDrops)
|
||||||
{
|
{
|
||||||
auto Pickup = AFortPickup::SpawnPickup(LootDrop.ItemDefinition, Location, LootDrop.Count, SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop.LoadedAmmo);
|
auto Pickup = AFortPickup::SpawnPickup(LootDrop->GetItemDefinition(), Location, LootDrop->GetCount(), SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop->GetLoadedAmmo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -996,7 +996,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
{
|
{
|
||||||
for (auto& LootDrop : LootDrops)
|
for (auto& LootDrop : LootDrops)
|
||||||
{
|
{
|
||||||
auto Pickup = AFortPickup::SpawnPickup(LootDrop.ItemDefinition, Location, LootDrop.Count, SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop.LoadedAmmo);
|
auto Pickup = AFortPickup::SpawnPickup(LootDrop->GetItemDefinition(), Location, LootDrop->GetCount(), SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop->GetLoadedAmmo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1013,9 +1013,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
|
|||||||
|
|
||||||
if (Engine_Version >= 423 && Fortnite_Version <= 12.61) // 423+ we need to spawn manually and vehicle sync doesn't work on >S13.
|
if (Engine_Version >= 423 && Fortnite_Version <= 12.61) // 423+ we need to spawn manually and vehicle sync doesn't work on >S13.
|
||||||
{
|
{
|
||||||
static int LastNum420 = 1;
|
static int LastNum420 = 114;
|
||||||
|
|
||||||
if (Globals::AmountOfListens != LastNum420)
|
if (LastNum420 != Globals::AmountOfListens)
|
||||||
{
|
{
|
||||||
LastNum420 = Globals::AmountOfListens;
|
LastNum420 = Globals::AmountOfListens;
|
||||||
|
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
|||||||
{
|
{
|
||||||
if (GadgetItemDefinition->ShouldDropAllItemsOnEquip()) // idk shouldnt this be auto?
|
if (GadgetItemDefinition->ShouldDropAllItemsOnEquip()) // idk shouldnt this be auto?
|
||||||
{
|
{
|
||||||
FortPlayerController->DropAllItems({ GadgetItemDefinition });
|
FortPlayerController->DropAllItems({ GadgetItemDefinition }, false, false, Fortnite_Version < 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool (*ApplyGadgetData)(UFortGadgetItemDefinition* a1, __int64 a2, UFortItem* a3, unsigned __int8 a4) = decltype(ApplyGadgetData)(Addresses::ApplyGadgetData);
|
bool (*ApplyGadgetData)(UFortGadgetItemDefinition* a1, __int64 a2, UFortItem* a3, unsigned __int8 a4) = decltype(ApplyGadgetData)(Addresses::ApplyGadgetData);
|
||||||
@@ -165,17 +165,6 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
|||||||
bool DidApplyingGadgetSucceed = ApplyGadgetData(GadgetItemDefinition, Interface, NewItemInstance, idktbh);
|
bool DidApplyingGadgetSucceed = ApplyGadgetData(GadgetItemDefinition, Interface, NewItemInstance, idktbh);
|
||||||
LOG_INFO(LogDev, "DidApplyingGadgetSucceed: {}", DidApplyingGadgetSucceed);
|
LOG_INFO(LogDev, "DidApplyingGadgetSucceed: {}", DidApplyingGadgetSucceed);
|
||||||
bWasGadget = true;
|
bWasGadget = true;
|
||||||
|
|
||||||
if (Fortnite_Version < 7)
|
|
||||||
{
|
|
||||||
auto PickaxeInstance = GetPickaxeInstance();
|
|
||||||
|
|
||||||
if (PickaxeInstance)
|
|
||||||
{
|
|
||||||
// RemoveItem(PickaxeInstance->GetItemEntry()->GetItemGuid(), nullptr, PickaxeInstance->GetItemEntry()->GetCount(), true);
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,14 +174,6 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
|||||||
FortPlayerController->ServerExecuteInventoryItemHook(FortPlayerController, NewItemInstance->GetItemEntry()->GetItemGuid());
|
FortPlayerController->ServerExecuteInventoryItemHook(FortPlayerController, NewItemInstance->GetItemEntry()->GetItemGuid());
|
||||||
FortPlayerController->ClientEquipItem(NewItemInstance->GetItemEntry()->GetItemGuid(), true);
|
FortPlayerController->ClientEquipItem(NewItemInstance->GetItemEntry()->GetItemGuid(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bWasGadget)
|
|
||||||
{
|
|
||||||
if (Fortnite_Version < 7)
|
|
||||||
{
|
|
||||||
// FortPlayerController->AddPickaxeToInventory();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -357,9 +338,12 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int
|
|||||||
|
|
||||||
bWasGadget = true;
|
bWasGadget = true;
|
||||||
|
|
||||||
if (Fortnite_Version < 7)
|
if (bWasGadget)
|
||||||
{
|
{
|
||||||
// FortPlayerController->AddPickaxeToInventory();
|
if (Fortnite_Version < 7 && GadgetItemDefinition->ShouldDropAllItemsOnEquip())
|
||||||
|
{
|
||||||
|
FortPlayerController->AddPickaxeToInventory();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
#include "NetSerialization.h"
|
#include "NetSerialization.h"
|
||||||
#include "Class.h"
|
#include "Class.h"
|
||||||
|
#include "GameplayAbilitySpec.h"
|
||||||
|
|
||||||
#include "reboot.h"
|
#include "reboot.h"
|
||||||
|
|
||||||
@@ -101,6 +104,24 @@ struct FFortItemEntry : FFastArraySerializerItem
|
|||||||
return *(int*)(__int64(this) + LoadedAmmoOffset);
|
return *(int*)(__int64(this) + LoadedAmmoOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float& GetDurability()
|
||||||
|
{
|
||||||
|
static auto DurabilityOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "Durability");
|
||||||
|
return *(float*)(__int64(this) + DurabilityOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
FGameplayAbilitySpecHandle& GetGameplayAbilitySpecHandle()
|
||||||
|
{
|
||||||
|
static auto GameplayAbilitySpecHandleOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "GameplayAbilitySpecHandle");
|
||||||
|
return *(FGameplayAbilitySpecHandle*)(__int64(this) + GameplayAbilitySpecHandleOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
TWeakObjectPtr<class AFortInventory>& GetParentInventory()
|
||||||
|
{
|
||||||
|
static auto ParentInventoryOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ParentInventory");
|
||||||
|
return *(TWeakObjectPtr<class AFortInventory>*)(__int64(this) + ParentInventoryOffset);
|
||||||
|
}
|
||||||
|
|
||||||
void CopyFromAnotherItemEntry(FFortItemEntry* OtherItemEntry, bool bCopyGuid = false)
|
void CopyFromAnotherItemEntry(FFortItemEntry* OtherItemEntry, bool bCopyGuid = false)
|
||||||
{
|
{
|
||||||
// We can use FortItemEntryStruct->CopyScriptStruct
|
// We can use FortItemEntryStruct->CopyScriptStruct
|
||||||
@@ -142,7 +163,7 @@ struct FFortItemEntry : FFastArraySerializerItem
|
|||||||
return StructSize;
|
return StructSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0)
|
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000)
|
||||||
{
|
{
|
||||||
auto Entry = // (FFortItemEntry*)FMemory::Realloc(0, GetStructSize(), 0);
|
auto Entry = // (FFortItemEntry*)FMemory::Realloc(0, GetStructSize(), 0);
|
||||||
Alloc<FFortItemEntry>(GetStructSize());
|
Alloc<FFortItemEntry>(GetStructSize());
|
||||||
@@ -150,14 +171,18 @@ struct FFortItemEntry : FFastArraySerializerItem
|
|||||||
if (!Entry)
|
if (!Entry)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
Entry->MostRecentArrayReplicationKey = -1;
|
Entry->MostRecentArrayReplicationKey = -1; // idk if we need to set this
|
||||||
Entry->ReplicationID = -1;
|
Entry->ReplicationID = -1;
|
||||||
Entry->ReplicationKey = -1;
|
Entry->ReplicationKey = -1;
|
||||||
|
|
||||||
Entry->GetItemDefinition() = ItemDefinition;
|
Entry->GetItemDefinition() = ItemDefinition;
|
||||||
Entry->GetCount() = Count;
|
Entry->GetCount() = Count;
|
||||||
Entry->GetLoadedAmmo() = LoadedAmmo;
|
Entry->GetLoadedAmmo() = LoadedAmmo;
|
||||||
// Entry->bUpdateStatsOnCollection = true; // Idk what this does but fortnite does it soo
|
Entry->GetDurability() = Durability;
|
||||||
|
Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1);
|
||||||
|
Entry->GetParentInventory().ObjectIndex = -1;
|
||||||
|
// CoCreateGuid((GUID*)&Entry->GetItemGuid());
|
||||||
|
// Entry->bUpdateStatsOnCollection = true; // Idk what this does but fortnite does it i think
|
||||||
|
|
||||||
return Entry;
|
return Entry;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,27 @@ UFortResourceItemDefinition* UFortKismetLibrary::K2_GetResourceItemDefinition(EF
|
|||||||
return params.ret;
|
return params.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FVector UFortKismetLibrary::FindGroundLocationAt(UWorld* World, AActor* IgnoreActor, FVector InLocation, float TraceStartZ, float TraceEndZ, FName TraceName)
|
||||||
|
{
|
||||||
|
static auto FindGroundLocationAtFn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.FindGroundLocationAt");
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
UWorld* World; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
AActor* IgnoreActor; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
FVector InLocation; // (ConstParm, Parm, OutParm, ZeroConstructor, ReferenceParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
float TraceStartZ; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
float TraceEndZ; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
FName TraceName; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
FVector ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||||
|
} UFortKismetLibrary_FindGroundLocationAt_Params{ World, IgnoreActor, InLocation, TraceStartZ, TraceEndZ, TraceName };
|
||||||
|
|
||||||
|
static auto DefaultClass = StaticClass();
|
||||||
|
DefaultClass->ProcessEvent(FindGroundLocationAtFn, &UFortKismetLibrary_FindGroundLocationAt_Params);
|
||||||
|
|
||||||
|
return UFortKismetLibrary_FindGroundLocationAt_Params.ReturnValue;
|
||||||
|
}
|
||||||
|
|
||||||
void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, const TArray<UObject*>& CharacterParts, UObject* PlayerState, bool* bSuccess)
|
void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, const TArray<UObject*>& CharacterParts, UObject* PlayerState, bool* bSuccess)
|
||||||
{
|
{
|
||||||
static auto fn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.ApplyCharacterCosmetics");
|
static auto fn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.ApplyCharacterCosmetics");
|
||||||
@@ -550,7 +571,7 @@ bool UFortKismetLibrary::PickLootDropsHook(UObject* Context, FFrame& Stack, bool
|
|||||||
{
|
{
|
||||||
auto& LootDrop = LootDrops.at(i);
|
auto& LootDrop = LootDrops.at(i);
|
||||||
|
|
||||||
auto NewEntry = FFortItemEntry::MakeItemEntry(LootDrop.ItemDefinition, LootDrop.Count, LootDrop.LoadedAmmo);
|
auto NewEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
|
||||||
|
|
||||||
OutLootToDrop.AddPtr(NewEntry, FFortItemEntry::GetStructSize());
|
OutLootToDrop.AddPtr(NewEntry, FFortItemEntry::GetStructSize());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public:
|
|||||||
|
|
||||||
static UFortResourceItemDefinition* K2_GetResourceItemDefinition(EFortResourceType ResourceType);
|
static UFortResourceItemDefinition* K2_GetResourceItemDefinition(EFortResourceType ResourceType);
|
||||||
static void ApplyCharacterCosmetics(UObject* WorldContextObject, const TArray<UObject*>& CharacterParts, UObject* PlayerState, bool* bSuccess);
|
static void ApplyCharacterCosmetics(UObject* WorldContextObject, const TArray<UObject*>& CharacterParts, UObject* PlayerState, bool* bSuccess);
|
||||||
|
static FVector FindGroundLocationAt(UWorld* World, AActor* IgnoreActor, FVector InLocation, float TraceStartZ, float TraceEndZ, FName TraceName);
|
||||||
|
|
||||||
static void PickLootDropsWithNamedWeightsHook(UObject* Context, FFrame& Stack, void* Ret);
|
static void PickLootDropsWithNamedWeightsHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||||
static void SpawnItemVariantPickupInWorldHook(UObject* Context, FFrame& Stack, void* Ret);
|
static void SpawnItemVariantPickupInWorldHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||||
|
|||||||
11
Project Reboot 3.0/FortLootLevel.h
Normal file
11
Project Reboot 3.0/FortLootLevel.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DataTable.h"
|
||||||
|
|
||||||
|
class UFortLootLevel
|
||||||
|
{
|
||||||
|
int GetItemLevel(FDataTableCategoryHandle LootLevelData, int WorldLevel)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -8,6 +8,711 @@
|
|||||||
#include "FortGameModeAthena.h"
|
#include "FortGameModeAthena.h"
|
||||||
|
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <map>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
|
struct FFortGameFeatureLootTableData
|
||||||
|
{
|
||||||
|
TSoftObjectPtr<UDataTable> LootTierData;
|
||||||
|
TSoftObjectPtr<UDataTable> LootPackageData;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef EXPERIMENTAL_LOOTING
|
||||||
|
float RandomFloatForLoot(float AllWeightsSum)
|
||||||
|
{
|
||||||
|
return (rand() * 0.000030518509) * AllWeightsSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename RowStructType = uint8>
|
||||||
|
void CollectDataTablesRows(std::vector<UDataTable*> DataTables, std::map<FName, RowStructType*>* OutMap, std::function<bool(FName, RowStructType*)> Check = []() { return true; })
|
||||||
|
{
|
||||||
|
std::vector<UDataTable*> DataTablesToIterate;
|
||||||
|
|
||||||
|
static auto CompositeDataTableClass = FindObject<UClass>("/Script/Engine.CompositeDataTable");
|
||||||
|
|
||||||
|
for (auto DataTable : DataTables)
|
||||||
|
{
|
||||||
|
// if (auto CompositeDataTable = Cast<UCompositeDataTable>(DataTable))
|
||||||
|
if (DataTable->IsA(CompositeDataTableClass))
|
||||||
|
{
|
||||||
|
auto CompositeDataTable = DataTable;
|
||||||
|
|
||||||
|
static auto ParentTablesOffset = DataTable->GetOffset("ParentTables");
|
||||||
|
auto& ParentTables = DataTable->Get<TArray<UDataTable*>>(ParentTablesOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < ParentTables.Num(); i++)
|
||||||
|
{
|
||||||
|
DataTablesToIterate.push_back(ParentTables.at(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataTablesToIterate.push_back(DataTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto CurrentDataTable : DataTablesToIterate)
|
||||||
|
{
|
||||||
|
for (auto& CurrentPair : CurrentDataTable->GetRowMap())
|
||||||
|
{
|
||||||
|
if (Check(CurrentPair.Key(), (RowStructType*)CurrentPair.Value()))
|
||||||
|
(*OutMap)[CurrentPair.Key()] = (RowStructType*)CurrentPair.Value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T* PickWeightedElement(const std::map<FName, T*>& Elements, std::function<float(T*)> GetWeightFn, float TotalWeightParam = -1, bool bCheckIfWeightIsZero = false, int RandMultiplier = 1, FName* OutName = nullptr, bool bPrint = false)
|
||||||
|
{
|
||||||
|
float TotalWeight = TotalWeightParam;
|
||||||
|
|
||||||
|
if (TotalWeight == -1)
|
||||||
|
{
|
||||||
|
TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<FName, T*>& p) {
|
||||||
|
auto Weight = GetWeightFn(p.second);
|
||||||
|
|
||||||
|
if (bPrint)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "Adding weight: {}", Weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc + Weight;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
float RandomNumber = // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight);
|
||||||
|
RandMultiplier * RandomFloatForLoot(TotalWeight);
|
||||||
|
|
||||||
|
if (bPrint)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "RandomNumber: {} TotalWeight: {}", RandomNumber, TotalWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetItemLevel(const FDataTableCategoryHandle& LootLevelData, int WorldLevel)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops)
|
||||||
|
{
|
||||||
|
if (LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryWeightArray().Num()
|
||||||
|
|| LootTierData->GetLootPackageCategoryMinArray().Num() != LootTierData->GetLootPackageCategoryMaxArray().Num()
|
||||||
|
)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// return OriginalNumberLootDrops;
|
||||||
|
|
||||||
|
float MinimumLootDrops = 0;
|
||||||
|
|
||||||
|
if (LootTierData->GetLootPackageCategoryMinArray().Num() > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < LootTierData->GetLootPackageCategoryMinArray().Num(); i++)
|
||||||
|
{
|
||||||
|
// Fortnite does more here, we need to figure it out.
|
||||||
|
MinimumLootDrops += LootTierData->GetLootPackageCategoryMinArray().at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MinimumLootDrops > OriginalNumberLootDrops)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "Requested {} loot drops but minimum drops is {} for loot package {}", OriginalNumberLootDrops, MinimumLootDrops, LootTierData->GetLootPackage().ToString());
|
||||||
|
// Fortnite doesn't return here?
|
||||||
|
}
|
||||||
|
|
||||||
|
int SumLootPackageCategoryWeightArray = 0;
|
||||||
|
|
||||||
|
if (LootTierData->GetLootPackageCategoryWeightArray().Num() > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < LootTierData->GetLootPackageCategoryWeightArray().Num(); i++)
|
||||||
|
{
|
||||||
|
// Fortnite does more here, we need to figure it out.
|
||||||
|
|
||||||
|
if (LootTierData->GetLootPackageCategoryWeightArray().at(i) > 0)
|
||||||
|
{
|
||||||
|
auto LootPackageCategoryMaxArrayIt = LootTierData->GetLootPackageCategoryMaxArray().at(i);
|
||||||
|
|
||||||
|
float IDK = 0; // TODO
|
||||||
|
|
||||||
|
if (LootPackageCategoryMaxArrayIt < 0 || IDK < LootPackageCategoryMaxArrayIt)
|
||||||
|
{
|
||||||
|
SumLootPackageCategoryWeightArray += LootTierData->GetLootPackageCategoryWeightArray().at(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (MinimumLootDrops < OriginalNumberLootDrops) // real commeneted one to one
|
||||||
|
{
|
||||||
|
// IDK
|
||||||
|
|
||||||
|
while (SumLootPackageCategoryWeightArray > 0)
|
||||||
|
{
|
||||||
|
// HONESTLY IDEK WHAT FORTNITE DOES HERE
|
||||||
|
|
||||||
|
float v29 = (float)rand() * 0.000030518509;
|
||||||
|
|
||||||
|
float v35 = (int)(float)((float)((float)((float)SumLootPackageCategoryWeightArray * v29)
|
||||||
|
+ (float)((float)SumLootPackageCategoryWeightArray * v29))
|
||||||
|
+ 0.5) >> 1;
|
||||||
|
|
||||||
|
// OutLootTierInfo->Hello++;
|
||||||
|
MinimumLootDrops++;
|
||||||
|
|
||||||
|
if (MinimumLootDrops >= OriginalNumberLootDrops)
|
||||||
|
return MinimumLootDrops;
|
||||||
|
|
||||||
|
SumLootPackageCategoryWeightArray--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (MinimumLootDrops < OriginalNumberLootDrops)
|
||||||
|
{
|
||||||
|
std::cout << std::format("Requested {} loot drops but maximum drops is {} for loot package {}\n", OriginalNumberLootDrops, MinimumLootDrops, LootTierData->LootPackage.ToString());
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
return MinimumLootDrops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*struct UFortLootPackage
|
||||||
|
{
|
||||||
|
int CurrentIdx = 0;
|
||||||
|
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.
|
||||||
|
{
|
||||||
|
float LootTier = ForcedLootTier;
|
||||||
|
|
||||||
|
if (LootTier == -1)
|
||||||
|
{
|
||||||
|
LootTier = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// buncha code im too lazy to reverse
|
||||||
|
}
|
||||||
|
|
||||||
|
LootTier = 1; // ONG PROPER
|
||||||
|
|
||||||
|
// if (fabs(LootTier) <= 0.0000000099999999)
|
||||||
|
// return 0;
|
||||||
|
|
||||||
|
std::map<FName, FFortLootTierData*> TierGroupLTDs;
|
||||||
|
|
||||||
|
CollectDataTablesRows<FFortLootTierData>(LTDTables, &TierGroupLTDs, [&](FName RowName, FFortLootTierData* TierData) -> bool {
|
||||||
|
if (LootTierGroup == TierData->GetTierGroup())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
FFortLootTierData* ChosenRowLootTierData = PickWeightedElement<FFortLootTierData>(TierGroupLTDs,
|
||||||
|
[](FFortLootTierData* LootTierData) -> float { return LootTierData->GetWeight(); }, -1,
|
||||||
|
true, LootTier, OutRowName);
|
||||||
|
|
||||||
|
if (!ChosenRowLootTierData)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return ChosenRowLootTierData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, const FName& LootPackageName, std::vector<LootDrop>* OutEntries, int LootPackageCategory = -1, bool bPrint = false)
|
||||||
|
{
|
||||||
|
if (!OutEntries)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::map<FName, FFortLootPackageData*> LootPackageIDMap;
|
||||||
|
|
||||||
|
CollectDataTablesRows<FFortLootPackageData>(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool {
|
||||||
|
if (LootPackage->GetLootPackageID() != LootPackageName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LootPackageCategory != -1 && LootPackage->GetLootPackageCategory() != LootPackageCategory) // idk if proper
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (WorldLevel >= 0)
|
||||||
|
{
|
||||||
|
if (LootPackage->MaxWorldLevel >= 0 && WorldLevel > LootPackage->MaxWorldLevel)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (LootPackage->MinWorldLevel >= 0 && WorldLevel < LootPackage->MinWorldLevel)
|
||||||
|
return 0;
|
||||||
|
} */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (LootPackageIDMap.size() == 0)
|
||||||
|
{
|
||||||
|
// std::cout << std::format("Loot Package {} has no valid weights.\n", LootPackageName.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FName PickedPackageRowName;
|
||||||
|
FFortLootPackageData* PickedPackage = PickWeightedElement<FFortLootPackageData>(LootPackageIDMap,
|
||||||
|
[](FFortLootPackageData* LootPackageData) -> float { return LootPackageData->GetWeight(); },
|
||||||
|
-1, true, 1, &PickedPackageRowName, bPrint);
|
||||||
|
|
||||||
|
if (!PickedPackage)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (bPrint)
|
||||||
|
LOG_INFO(LogLoot, "PickLootDropsFromLootPackage selected package {} with loot package category {} from LootPackageIDMap of size: {}", PickedPackageRowName.ToString(), LootPackageCategory, LootPackageIDMap.size());
|
||||||
|
|
||||||
|
if (PickedPackage->GetLootPackageCall().Data.Num() > 1)
|
||||||
|
{
|
||||||
|
if (PickedPackage->GetCount() > 0)
|
||||||
|
{
|
||||||
|
int v9 = 0;
|
||||||
|
|
||||||
|
while (v9 < PickedPackage->GetCount())
|
||||||
|
{
|
||||||
|
int LootPackageCategoryToUseForLPCall = 0; // hmm
|
||||||
|
|
||||||
|
PickLootDropsFromLootPackage(LPTables,
|
||||||
|
PickedPackage->GetLootPackageCall().Data.Data ? UKismetStringLibrary::Conv_StringToName(PickedPackage->GetLootPackageCall()) : FName(0),
|
||||||
|
OutEntries, LootPackageCategoryToUseForLPCall, bPrint
|
||||||
|
);
|
||||||
|
|
||||||
|
v9++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ItemDefinition = PickedPackage->GetItemDefinition().Get(UFortItemDefinition::StaticClass(), true);
|
||||||
|
|
||||||
|
if (!ItemDefinition)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "Loot Package {} does not contain a LootPackageCall or ItemDefinition.", PickedPackage->GetLootPackageID().ToString());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CountMultiplier = 1;
|
||||||
|
int FinalCount = CountMultiplier * PickedPackage->GetCount();
|
||||||
|
|
||||||
|
if (FinalCount > 0)
|
||||||
|
{
|
||||||
|
int FinalItemLevel = 0;
|
||||||
|
|
||||||
|
if (ItemLevel >= 0)
|
||||||
|
FinalItemLevel = ItemLevel;
|
||||||
|
|
||||||
|
while (FinalCount > 0)
|
||||||
|
{
|
||||||
|
int CurrentCountForEntry = PickedPackage->GetCount(); // Idk calls some itemdefinition vfunc
|
||||||
|
|
||||||
|
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDefinition, CurrentCountForEntry, LoadedAmmo)));
|
||||||
|
|
||||||
|
if (Engine_Version >= 424)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
|
||||||
|
Alright, so Fortnite literally doesn't reference the first loot package category for chests and floor loot (didnt check rest).
|
||||||
|
Usually the first loot package category in our case is ammo, so this is quite weird.
|
||||||
|
I have no clue how Fortnite would actually add the ammo.
|
||||||
|
|
||||||
|
Guess what, on the chapter 2 new loot tier groups, like FactionChests, they don't even have a package which has ammo as its loot package call.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool IsWeapon = PickedPackage->GetLootPackageID().ToString().contains(".Weapon.") && WeaponItemDefinition; // ONG?
|
||||||
|
|
||||||
|
if (IsWeapon)
|
||||||
|
{
|
||||||
|
auto AmmoData = WeaponItemDefinition->GetAmmoData();
|
||||||
|
|
||||||
|
int AmmoCount = AmmoData->GetDropCount(); // idk about this one
|
||||||
|
|
||||||
|
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(WeaponItemDefinition->GetAmmoData(), AmmoCount)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FinalCount -= CurrentCountForEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recursive)
|
||||||
|
{
|
||||||
|
std::vector<LootDrop> LootDrops;
|
||||||
|
|
||||||
|
if (recursive > 6)
|
||||||
|
return LootDrops;
|
||||||
|
|
||||||
|
auto GameState = ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena();
|
||||||
|
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
|
||||||
|
|
||||||
|
static std::vector<UDataTable*> LTDTables;
|
||||||
|
static std::vector<UDataTable*> LPTables;
|
||||||
|
|
||||||
|
static auto CompositeDataTableClass = FindObject<UClass>(L"/Script/Engine.CompositeDataTable");
|
||||||
|
|
||||||
|
static int LastNum1 = 14915;
|
||||||
|
|
||||||
|
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
|
||||||
|
|
||||||
|
if (LastNum1 != Globals::AmountOfListens)
|
||||||
|
{
|
||||||
|
LastNum1 = Globals::AmountOfListens;
|
||||||
|
|
||||||
|
LTDTables.clear();
|
||||||
|
LPTables.clear();
|
||||||
|
|
||||||
|
bool bFoundPlaylistTable = false;
|
||||||
|
|
||||||
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData");
|
||||||
|
auto& LootTierDataSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootTierDataOffset);
|
||||||
|
|
||||||
|
static auto LootPackagesOffset = CurrentPlaylist->GetOffset("LootPackages");
|
||||||
|
auto& LootPackagesSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootPackagesOffset);
|
||||||
|
|
||||||
|
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
|
||||||
|
{
|
||||||
|
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
||||||
|
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
||||||
|
|
||||||
|
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
|
if (StrongLootTierData && StrongLootPackage)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(StrongLootTierData);
|
||||||
|
LPTables.push_back(StrongLootPackage);
|
||||||
|
|
||||||
|
bFoundPlaylistTable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bFoundPlaylistTable)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
||||||
|
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
||||||
|
// LPTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
||||||
|
|
||||||
|
static auto FortGameFeatureDataClass = FindObject<UClass>("/Script/FortniteGame.FortGameFeatureData");
|
||||||
|
|
||||||
|
if (FortGameFeatureDataClass)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < ChunkedObjects->Num(); i++)
|
||||||
|
{
|
||||||
|
auto Object = ChunkedObjects->GetObjectByIndex(i);
|
||||||
|
|
||||||
|
if (!Object)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Object->IsA(FortGameFeatureDataClass))
|
||||||
|
{
|
||||||
|
auto GameFeatureData = Object;
|
||||||
|
static auto DefaultLootTableDataOffset = GameFeatureData->GetOffset("DefaultLootTableData");
|
||||||
|
|
||||||
|
if (DefaultLootTableDataOffset != -1)
|
||||||
|
{
|
||||||
|
auto DefaultLootTableData = GameFeatureData->GetPtr<FFortGameFeatureLootTableData>(DefaultLootTableDataOffset);
|
||||||
|
|
||||||
|
auto LootTierDataTableStr = DefaultLootTableData->LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
|
||||||
|
auto LootTierDataTableIsComposite = LootTierDataTableStr.contains("Composite");
|
||||||
|
auto LootPackageTableStr = DefaultLootTableData->LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto LootPackageTableIsComposite = LootPackageTableStr.contains("Composite");
|
||||||
|
|
||||||
|
auto LootTierDataPtr = DefaultLootTableData->LootTierData.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
auto LootPackagePtr = DefaultLootTableData->LootPackageData.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
|
if (LootPackagePtr)
|
||||||
|
{
|
||||||
|
LPTables.push_back(LootPackagePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
||||||
|
auto& PlaylistOverrideLootTableData = GameFeatureData->Get<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
||||||
|
|
||||||
|
static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer");
|
||||||
|
auto GameplayTagContainer = CurrentPlaylist->GetPtr<FGameplayTagContainer>(GameplayTagContainerOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& Tag = GameplayTagContainer->GameplayTags.At(i);
|
||||||
|
|
||||||
|
for (auto& Value : PlaylistOverrideLootTableData)
|
||||||
|
{
|
||||||
|
auto CurrentOverrideTag = Value.First;
|
||||||
|
|
||||||
|
if (Tag.TagName == CurrentOverrideTag.TagName)
|
||||||
|
{
|
||||||
|
auto OverrideLootPackageTableStr = Value.Second.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite");
|
||||||
|
|
||||||
|
auto ptr = Value.Second.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
/* if (bOverrideIsComposite)
|
||||||
|
{
|
||||||
|
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
||||||
|
|
||||||
|
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
||||||
|
|
||||||
|
for (int z = 0; z < ParentTables->size(); z++)
|
||||||
|
{
|
||||||
|
auto ParentTable = ParentTables->At(z);
|
||||||
|
|
||||||
|
if (ParentTable)
|
||||||
|
{
|
||||||
|
LPTables.push_back(ParentTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
LPTables.push_back(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LootTierDataPtr)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(LootTierDataPtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData");
|
||||||
|
auto& PlaylistOverrideLootTableData = GameFeatureData->Get<TMap<FGameplayTag, FFortGameFeatureLootTableData>>(PlaylistOverrideLootTableDataOffset);
|
||||||
|
|
||||||
|
static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer");
|
||||||
|
auto GameplayTagContainer = CurrentPlaylist->GetPtr<FGameplayTagContainer>(GameplayTagContainerOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++)
|
||||||
|
{
|
||||||
|
auto& Tag = GameplayTagContainer->GameplayTags.At(i);
|
||||||
|
|
||||||
|
for (auto& Value : PlaylistOverrideLootTableData)
|
||||||
|
{
|
||||||
|
auto CurrentOverrideTag = Value.First;
|
||||||
|
|
||||||
|
if (Tag.TagName == CurrentOverrideTag.TagName)
|
||||||
|
{
|
||||||
|
auto OverrideLootTierDataStr = Value.Second.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite");
|
||||||
|
|
||||||
|
auto ptr = Value.Second.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
/* if (bOverrideIsComposite)
|
||||||
|
{
|
||||||
|
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
|
||||||
|
|
||||||
|
auto ParentTables = ptr->GetPtr<TArray<UDataTable*>>(ParentTablesOffset);
|
||||||
|
|
||||||
|
for (int z = 0; z < ParentTables->size(); z++)
|
||||||
|
{
|
||||||
|
auto ParentTable = ParentTables->At(z);
|
||||||
|
|
||||||
|
if (ParentTable)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(ParentTable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
LTDTables.push_back(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < LTDTables.size(); i++)
|
||||||
|
{
|
||||||
|
auto& Table = LTDTables.at(i);
|
||||||
|
|
||||||
|
if (!Table->IsValidLowLevel())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Table->AddToRoot();
|
||||||
|
LOG_INFO(LogDev, "[{}] LTD {}", i, Table->GetFullName());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < LPTables.size(); i++)
|
||||||
|
{
|
||||||
|
auto& Table = LPTables.at(i);
|
||||||
|
|
||||||
|
if (!Table->IsValidLowLevel())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Table->AddToRoot();
|
||||||
|
LOG_INFO(LogDev, "[{}] LP {}", i, Table->GetFullName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Fortnite_Version <= 6 || std::floor(Fortnite_Version) == 9) // ahhh
|
||||||
|
{
|
||||||
|
LTDTables.clear();
|
||||||
|
LPTables.clear();
|
||||||
|
|
||||||
|
bool bFoundPlaylistTable = false;
|
||||||
|
|
||||||
|
if (CurrentPlaylist)
|
||||||
|
{
|
||||||
|
static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData");
|
||||||
|
auto& LootTierDataSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootTierDataOffset);
|
||||||
|
|
||||||
|
static auto LootPackagesOffset = CurrentPlaylist->GetOffset("LootPackages");
|
||||||
|
auto& LootPackagesSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootPackagesOffset);
|
||||||
|
|
||||||
|
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
|
||||||
|
{
|
||||||
|
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
|
||||||
|
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
|
||||||
|
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
|
||||||
|
|
||||||
|
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : UDataTable::StaticClass(), true);
|
||||||
|
|
||||||
|
if (StrongLootTierData && StrongLootPackage)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(StrongLootTierData);
|
||||||
|
LPTables.push_back(StrongLootPackage);
|
||||||
|
|
||||||
|
bFoundPlaylistTable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bFoundPlaylistTable)
|
||||||
|
{
|
||||||
|
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
|
||||||
|
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LTDTables.size() <= 0 || LPTables.size() <= 0)
|
||||||
|
{
|
||||||
|
LOG_WARN(LogLoot, "Empty tables! ({} {})", LTDTables.size(), LPTables.size());
|
||||||
|
return LootDrops;
|
||||||
|
}
|
||||||
|
|
||||||
|
FName LootTierRowName;
|
||||||
|
auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, 0, -1, &LootTierRowName);
|
||||||
|
|
||||||
|
if (!ChosenRowLootTierData)
|
||||||
|
{
|
||||||
|
return LootDrops;
|
||||||
|
}
|
||||||
|
else if (bPrint)
|
||||||
|
{
|
||||||
|
LOG_INFO(LogLoot, "Picked loot tier data row {}", LootTierRowName.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto ChosenLootPackageName = ChosenRowLootTierData->GetLootPackage().ToString();
|
||||||
|
|
||||||
|
// if (ChosenLootPackageName.contains(".Empty")) { return PickLootDropsNew(TierGroupName, bPrint, ++recursive); }
|
||||||
|
|
||||||
|
float NumLootPackageDrops = ChosenRowLootTierData->GetNumLootPackageDrops();
|
||||||
|
|
||||||
|
float NumberLootDrops = 0;
|
||||||
|
|
||||||
|
if (NumLootPackageDrops > 0)
|
||||||
|
{
|
||||||
|
if (NumLootPackageDrops < 1)
|
||||||
|
{
|
||||||
|
NumberLootDrops = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NumberLootDrops = (int)(float)((float)(NumLootPackageDrops + NumLootPackageDrops) - 0.5) >> 1;
|
||||||
|
float v20 = NumLootPackageDrops - NumberLootDrops;
|
||||||
|
if (v20 > 0.0000099999997)
|
||||||
|
{
|
||||||
|
NumberLootDrops += v20 >= (rand() * 0.000030518509);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float AmountOfLootPackageDrops = GetAmountOfLootPackagesToDrop(ChosenRowLootTierData, NumberLootDrops);
|
||||||
|
|
||||||
|
LootDrops.reserve(AmountOfLootPackageDrops);
|
||||||
|
|
||||||
|
if (AmountOfLootPackageDrops > 0)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < AmountOfLootPackageDrops; i++)
|
||||||
|
{
|
||||||
|
if (i >= ChosenRowLootTierData->GetLootPackageCategoryMinArray().Num())
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (int j = 0; j < ChosenRowLootTierData->GetLootPackageCategoryMinArray().at(i); j++)
|
||||||
|
{
|
||||||
|
if (ChosenRowLootTierData->GetLootPackageCategoryMinArray().at(i) < 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int LootPackageCategory = i;
|
||||||
|
|
||||||
|
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->GetLootPackage(), &LootDrops, LootPackageCategory, bPrint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LootDrops;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
float GetRandomFloatForLooting(float min, float max)
|
float GetRandomFloatForLooting(float min, float max)
|
||||||
{
|
{
|
||||||
@@ -72,12 +777,6 @@ static FFortLootPackageData* GetLootPackage(std::vector<FFortLootPackageData*>&
|
|||||||
return SelectedItem;
|
return SelectedItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FFortGameFeatureLootTableData
|
|
||||||
{
|
|
||||||
TSoftObjectPtr<UDataTable> LootTierData;
|
|
||||||
TSoftObjectPtr<UDataTable> LootPackageData;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recursive)
|
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recursive)
|
||||||
{
|
{
|
||||||
std::vector<LootDrop> LootDrops;
|
std::vector<LootDrop> LootDrops;
|
||||||
@@ -644,13 +1343,9 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
|
|||||||
|
|
||||||
auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDef);
|
auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDef);
|
||||||
|
|
||||||
LootDrop lootDrop{};
|
LootDrops.push_back(LootDrop(FFortItemEntry::MakeItemEntry(ItemDef, LootPackageCall->GetCount(), WeaponDef ? WeaponDef->GetClipSize() : 0));
|
||||||
lootDrop.ItemDefinition = ItemDef;
|
|
||||||
lootDrop.LoadedAmmo = WeaponDef ? WeaponDef->GetClipSize() : 0;
|
|
||||||
lootDrop.Count = LootPackageCall->GetCount();
|
|
||||||
|
|
||||||
LootDrops.push_back(lootDrop);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return LootDrops;
|
return LootDrops;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -5,13 +5,9 @@
|
|||||||
#include "Array.h"
|
#include "Array.h"
|
||||||
#include "FortWorldItemDefinition.h"
|
#include "FortWorldItemDefinition.h"
|
||||||
#include "SoftObjectPtr.h"
|
#include "SoftObjectPtr.h"
|
||||||
|
#include "FortItem.h"
|
||||||
|
|
||||||
struct LootDrop
|
#define EXPERIMENTAL_LOOTING
|
||||||
{
|
|
||||||
UFortItemDefinition* ItemDefinition;
|
|
||||||
int Count;
|
|
||||||
int LoadedAmmo;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FFortLootPackageData
|
struct FFortLootPackageData
|
||||||
{
|
{
|
||||||
@@ -46,6 +42,12 @@ public:
|
|||||||
return *(int*)(__int64(this) + CountOffset);
|
return *(int*)(__int64(this) + CountOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int& GetLootPackageCategory()
|
||||||
|
{
|
||||||
|
static auto LootPackageCategoryOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "LootPackageCategory");
|
||||||
|
return *(int*)(__int64(this) + LootPackageCategoryOffset);
|
||||||
|
}
|
||||||
|
|
||||||
FString& GetAnnotation()
|
FString& GetAnnotation()
|
||||||
{
|
{
|
||||||
static auto AnnotationOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "Annotation");
|
static auto AnnotationOffset = FindOffsetStruct("/Script/FortniteGame.FortLootPackageData", "Annotation");
|
||||||
@@ -99,4 +101,18 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LootDrop
|
||||||
|
{
|
||||||
|
FFortItemEntry* ItemEntry;
|
||||||
|
|
||||||
|
FFortItemEntry* operator->() {
|
||||||
|
return ItemEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
~LootDrop()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint = false, int recursive = 0);
|
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint = false, int recursive = 0);
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "FortPlayerController.h"
|
#include "FortPlayerController.h"
|
||||||
#include <memcury.h>
|
#include <memcury.h>
|
||||||
#include "GameplayStatics.h"
|
#include "GameplayStatics.h"
|
||||||
|
#include "gui.h"
|
||||||
|
|
||||||
void AFortPickup::TossPickup(FVector FinalLocation, AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource)
|
void AFortPickup::TossPickup(FVector FinalLocation, AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource)
|
||||||
{
|
{
|
||||||
@@ -30,7 +31,7 @@ void AFortPickup::SpawnMovementComponent()
|
|||||||
|
|
||||||
AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Location,
|
AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Location,
|
||||||
EFortPickupSourceTypeFlag PickupSource, EFortPickupSpawnSource SpawnSource,
|
EFortPickupSourceTypeFlag PickupSource, EFortPickupSpawnSource SpawnSource,
|
||||||
class AFortPawn* Pawn, UClass* OverrideClass, bool bToss, int OverrideCount)
|
class AFortPawn* Pawn, UClass* OverrideClass, bool bToss, int OverrideCount, AFortPickup* IgnoreCombinePickup)
|
||||||
{
|
{
|
||||||
if (bToss)
|
if (bToss)
|
||||||
{
|
{
|
||||||
@@ -85,14 +86,17 @@ AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Locatio
|
|||||||
{
|
{
|
||||||
auto OtherPickup = (AFortPickup*)OtherPickupActor;
|
auto OtherPickup = (AFortPickup*)OtherPickupActor;
|
||||||
|
|
||||||
if (OtherPickup->GetPickupLocationData()->GetCombineTarget())
|
if (OtherPickup == IgnoreCombinePickup || OtherPickup->GetPickupLocationData()->GetCombineTarget())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (PrimaryPickupItemEntry->GetItemDefinition() == OtherPickup->GetPrimaryPickupItemEntry()->GetItemDefinition())
|
if (PrimaryPickupItemEntry->GetItemDefinition() == OtherPickup->GetPrimaryPickupItemEntry()->GetItemDefinition())
|
||||||
{
|
{
|
||||||
auto IncomingCount = OtherPickup->GetPrimaryPickupItemEntry()->GetCount();
|
// auto IncomingCount = OtherPickup->GetPrimaryPickupItemEntry()->GetCount();
|
||||||
|
|
||||||
if (PrimaryPickupItemEntry->GetCount() + IncomingCount > PrimaryPickupItemEntry->GetItemDefinition()->GetMaxStackSize())
|
// if (PrimaryPickupItemEntry->GetCount() + IncomingCount == PrimaryPickupItemEntry->GetItemDefinition()->GetMaxStackSize())
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
if (OtherPickup->GetPrimaryPickupItemEntry()->GetCount() == PrimaryPickupItemEntry->GetItemDefinition()->GetMaxStackSize()) // Other pickup is already at the max size.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -106,21 +110,29 @@ AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Locatio
|
|||||||
PickupLocationData->GetCombineTarget() = (AFortPickup*)Pickup->GetClosestActor(AFortPickup::StaticClass(), 4, CanCombineWithPickup);
|
PickupLocationData->GetCombineTarget() = (AFortPickup*)Pickup->GetClosestActor(AFortPickup::StaticClass(), 4, CanCombineWithPickup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// our little remake of tosspickup
|
if (!PickupLocationData->GetCombineTarget()) // I don't think we should call TossPickup for every pickup anyways.
|
||||||
|
|
||||||
Pickup->GetPickupLocationData()->GetLootFinalPosition() = Location;
|
|
||||||
Pickup->GetPickupLocationData()->GetLootInitialPosition() = Pickup->GetActorLocation();
|
|
||||||
Pickup->GetPickupLocationData()->GetFlyTime() = 1.4f; // not right really
|
|
||||||
Pickup->GetPickupLocationData()->GetItemOwner() = Pawn;
|
|
||||||
Pickup->GetPickupLocationData()->GetFinalTossRestLocation() = Pickup->GetActorLocation(); // ong ong proper
|
|
||||||
|
|
||||||
if (!PickupLocationData->GetCombineTarget()) // I don't think we should call TossPickup for every pickup.
|
|
||||||
{
|
{
|
||||||
Pickup->TossPickup(Location, Pawn, 0, bToss, PickupSource, SpawnSource);
|
Pickup->TossPickup(Location, Pawn, 0, bToss, PickupSource, SpawnSource);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
auto ActorLocation = Pickup->GetActorLocation();
|
||||||
|
auto CurrentActorLocation = PickupLocationData->GetCombineTarget()->GetActorLocation();
|
||||||
|
|
||||||
|
int Dist = float(sqrtf(powf(CurrentActorLocation.X - ActorLocation.X, 2.0) + powf(CurrentActorLocation.Y - ActorLocation.Y, 2.0) + powf(CurrentActorLocation.Z - ActorLocation.Z, 2.0))) / 100.f;
|
||||||
|
|
||||||
|
// LOG_INFO(LogDev, "Distance: {}", Dist);
|
||||||
|
|
||||||
|
// our little remake of tosspickup
|
||||||
|
|
||||||
|
PickupLocationData->GetLootFinalPosition() = Location;
|
||||||
|
PickupLocationData->GetLootInitialPosition() = Pickup->GetActorLocation();
|
||||||
|
PickupLocationData->GetFlyTime() = 1.f / Dist; // Higher the dist quicker it should be. // not right
|
||||||
|
PickupLocationData->GetItemOwner() = Pawn;
|
||||||
|
PickupLocationData->GetFinalTossRestLocation() = PickupLocationData->GetCombineTarget()->GetActorLocation(); // Pickup->GetActorLocation() // ong ong proper
|
||||||
|
|
||||||
Pickup->OnRep_PickupLocationData();
|
Pickup->OnRep_PickupLocationData();
|
||||||
|
Pickup->ForceNetUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PickupSource == EFortPickupSourceTypeFlag::Container) // crashes if we do this then tosspickup
|
if (PickupSource == EFortPickupSourceTypeFlag::Container) // crashes if we do this then tosspickup
|
||||||
@@ -142,7 +154,7 @@ AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Locatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Location, int Count, EFortPickupSourceTypeFlag PickupSource, EFortPickupSpawnSource SpawnSource,
|
AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Location, int Count, EFortPickupSourceTypeFlag PickupSource, EFortPickupSpawnSource SpawnSource,
|
||||||
int LoadedAmmo, AFortPawn* Pawn, UClass* OverrideClass, bool bToss)
|
int LoadedAmmo, AFortPawn* Pawn, UClass* OverrideClass, bool bToss, AFortPickup* IgnoreCombinePickup)
|
||||||
{
|
{
|
||||||
if (LoadedAmmo == -1)
|
if (LoadedAmmo == -1)
|
||||||
{
|
{
|
||||||
@@ -153,7 +165,7 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto ItemEntry = FFortItemEntry::MakeItemEntry(ItemDef, Count, LoadedAmmo);
|
auto ItemEntry = FFortItemEntry::MakeItemEntry(ItemDef, Count, LoadedAmmo);
|
||||||
auto Pickup = SpawnPickup(ItemEntry, Location, PickupSource, SpawnSource, Pawn, OverrideClass, bToss);
|
auto Pickup = SpawnPickup(ItemEntry, Location, PickupSource, SpawnSource, Pawn, OverrideClass, bToss, -1, IgnoreCombinePickup);
|
||||||
// VirtualFree(ItemEntry);
|
// VirtualFree(ItemEntry);
|
||||||
return Pickup;
|
return Pickup;
|
||||||
}
|
}
|
||||||
@@ -164,27 +176,40 @@ void AFortPickup::CombinePickupHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
auto PickupToCombineInto = (AFortPickup*)Pickup->GetPickupLocationData()->GetCombineTarget();
|
auto PickupToCombineInto = (AFortPickup*)Pickup->GetPickupLocationData()->GetCombineTarget();
|
||||||
|
|
||||||
if (!PickupToCombineInto->IsActorBeingDestroyed())
|
if (PickupToCombineInto->IsActorBeingDestroyed())
|
||||||
{
|
return;
|
||||||
// TODO Add more checks
|
|
||||||
|
|
||||||
PickupToCombineInto->GetPrimaryPickupItemEntry()->GetCount() += Pickup->GetPrimaryPickupItemEntry()->GetCount();
|
const int IncomingCount = Pickup->GetPrimaryPickupItemEntry()->GetCount();
|
||||||
|
const int OriginalCount = PickupToCombineInto->GetPrimaryPickupItemEntry()->GetCount();
|
||||||
|
|
||||||
|
// add more checks?
|
||||||
|
|
||||||
|
auto ItemDefinition = PickupToCombineInto->GetPrimaryPickupItemEntry()->GetItemDefinition();
|
||||||
|
|
||||||
|
int CountToAdd = IncomingCount;
|
||||||
|
|
||||||
|
if (OriginalCount + CountToAdd > ItemDefinition->GetMaxStackSize())
|
||||||
|
{
|
||||||
|
const int OverStackCount = OriginalCount + CountToAdd - ItemDefinition->GetMaxStackSize();
|
||||||
|
CountToAdd = ItemDefinition->GetMaxStackSize() - OriginalCount;
|
||||||
|
|
||||||
|
auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner();
|
||||||
|
|
||||||
|
auto NewOverStackPickup = AFortPickup::SpawnPickup(ItemDefinition, PickupToCombineInto->GetActorLocation(), OverStackCount,
|
||||||
|
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, ItemOwner, nullptr, false, PickupToCombineInto);
|
||||||
|
}
|
||||||
|
|
||||||
|
PickupToCombineInto->GetPrimaryPickupItemEntry()->GetCount() += CountToAdd;
|
||||||
PickupToCombineInto->OnRep_PrimaryPickupItemEntry();
|
PickupToCombineInto->OnRep_PrimaryPickupItemEntry();
|
||||||
|
|
||||||
PickupToCombineInto->ForceNetUpdate();
|
PickupToCombineInto->ForceNetUpdate();
|
||||||
PickupToCombineInto->FlushNetDormancy();
|
PickupToCombineInto->FlushNetDormancy();
|
||||||
|
|
||||||
Pickup->K2_DestroyActor();
|
Pickup->K2_DestroyActor();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
||||||
{
|
{
|
||||||
constexpr bool bTestPrinting = false; // we could just use our own logger but eh
|
|
||||||
|
|
||||||
if constexpr (bTestPrinting)
|
|
||||||
LOG_INFO(LogDev, "CompletePickupAnimationHook!");
|
|
||||||
|
|
||||||
auto Pawn = Cast<AFortPlayerPawn>(Pickup->GetPickupLocationData()->GetPickupTarget());
|
auto Pawn = Cast<AFortPlayerPawn>(Pickup->GetPickupLocationData()->GetPickupTarget());
|
||||||
|
|
||||||
if (!Pawn)
|
if (!Pawn)
|
||||||
@@ -234,7 +259,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
std::vector<std::pair<FFortItemEntry*, FFortItemEntry*>> PairsToMarkDirty; // vector of sets or something so no duplicates??
|
std::vector<std::pair<FFortItemEntry*, FFortItemEntry*>> PairsToMarkDirty; // vector of sets or something so no duplicates??
|
||||||
|
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "Start cpyCount: {}", cpyCount);
|
LOG_INFO(LogDev, "Start cpyCount: {}", cpyCount);
|
||||||
|
|
||||||
bool bWasHoldingSameItemWhenSwap = false;
|
bool bWasHoldingSameItemWhenSwap = false;
|
||||||
@@ -300,7 +325,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
bHasSwapped = true;
|
bHasSwapped = true;
|
||||||
|
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "[{}] Swapping: {}", i, ItemDefinitionToSwap->GetFullName());
|
LOG_INFO(LogDev, "[{}] Swapping: {}", i, ItemDefinitionToSwap->GetFullName());
|
||||||
|
|
||||||
// bForceDontAddItem = true;
|
// bForceDontAddItem = true;
|
||||||
@@ -311,7 +336,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
if (CurrentItemEntry->GetItemDefinition() == PickupItemDefinition)
|
if (CurrentItemEntry->GetItemDefinition() == PickupItemDefinition)
|
||||||
{
|
{
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "[{}] Found stack of item!", i);
|
LOG_INFO(LogDev, "[{}] Found stack of item!", i);
|
||||||
|
|
||||||
if (CurrentItemEntry->GetCount() < PickupItemDefinition->GetMaxStackSize())
|
if (CurrentItemEntry->GetCount() < PickupItemDefinition->GetMaxStackSize())
|
||||||
@@ -327,7 +352,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
bEverStacked = true;
|
bEverStacked = true;
|
||||||
|
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "[{}] We are stacking {}.", i, AmountToStack);
|
LOG_INFO(LogDev, "[{}] We are stacking {}.", i, AmountToStack);
|
||||||
|
|
||||||
// if (cpyCount > 0)
|
// if (cpyCount > 0)
|
||||||
@@ -339,7 +364,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
if ((bIsInventoryFull || bForceOverflow) && cpyCount > 0) // overflow
|
if ((bIsInventoryFull || bForceOverflow) && cpyCount > 0) // overflow
|
||||||
{
|
{
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "[{}] Overflow", i);
|
LOG_INFO(LogDev, "[{}] Overflow", i);
|
||||||
|
|
||||||
UFortWorldItemDefinition* ItemDefinitionToSpawn = PickupItemDefinition;
|
UFortWorldItemDefinition* ItemDefinitionToSpawn = PickupItemDefinition;
|
||||||
@@ -359,7 +384,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
|
|
||||||
if (cpyCount > 0 && !bIsInventoryFull && !bForceDontAddItem)
|
if (cpyCount > 0 && !bIsInventoryFull && !bForceDontAddItem)
|
||||||
{
|
{
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "Attempting to add to inventory.");
|
LOG_INFO(LogDev, "Attempting to add to inventory.");
|
||||||
|
|
||||||
if (bDoesStackExist ? PickupItemDefinition->DoesAllowMultipleStacks() : true)
|
if (bDoesStackExist ? PickupItemDefinition->DoesAllowMultipleStacks() : true)
|
||||||
@@ -375,7 +400,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
|||||||
else
|
else
|
||||||
cpyCount -= NewItemCount;
|
cpyCount -= NewItemCount;
|
||||||
|
|
||||||
if constexpr (bTestPrinting)
|
if (bDebugPrintSwapping)
|
||||||
LOG_INFO(LogDev, "Added item with count {} to inventory.", NewItemCount);
|
LOG_INFO(LogDev, "Added item with count {} to inventory.", NewItemCount);
|
||||||
|
|
||||||
if (bHasSwapped && NewSwappedItem == FGuid(-1, -1, -1, -1))
|
if (bHasSwapped && NewSwappedItem == FGuid(-1, -1, -1, -1))
|
||||||
|
|||||||
@@ -120,11 +120,11 @@ public:
|
|||||||
|
|
||||||
static AFortPickup* SpawnPickup(FFortItemEntry* ItemEntry, FVector Location,
|
static AFortPickup* SpawnPickup(FFortItemEntry* ItemEntry, FVector Location,
|
||||||
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
|
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
|
||||||
class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true, int OverrideCount = -1);
|
class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true, int OverrideCount = -1, AFortPickup* IgnoreCombinePickup = nullptr);
|
||||||
|
|
||||||
static AFortPickup* SpawnPickup(class UFortItemDefinition* ItemDef, FVector Location, int Count,
|
static AFortPickup* SpawnPickup(class UFortItemDefinition* ItemDef, FVector Location, int Count,
|
||||||
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
|
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
|
||||||
int LoadedAmmo = -1, class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true);
|
int LoadedAmmo = -1, class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true, AFortPickup* IgnoreCombinePickup = nullptr);
|
||||||
|
|
||||||
static void CombinePickupHook(AFortPickup* Pickup);
|
static void CombinePickupHook(AFortPickup* Pickup);
|
||||||
static char CompletePickupAnimationHook(AFortPickup* Pickup);
|
static char CompletePickupAnimationHook(AFortPickup* Pickup);
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ bool AFortPlayerController::DoesBuildFree()
|
|||||||
return ReadBitfieldValue(bBuildFreeOffset, bBuildFreeFieldMask);
|
return ReadBitfieldValue(bBuildFreeOffset, bBuildFreeFieldMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AFortPlayerController::DropAllItems(const std::vector<UFortItemDefinition*>& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar, bool bRemoveIfNotDroppable)
|
void AFortPlayerController::DropAllItems(const std::vector<UFortItemDefinition*>& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar, bool bRemoveIfNotDroppable, bool RemovePickaxe)
|
||||||
{
|
{
|
||||||
auto Pawn = this->GetMyFortPawn();
|
auto Pawn = this->GetMyFortPawn();
|
||||||
|
|
||||||
@@ -78,6 +78,8 @@ void AFortPlayerController::DropAllItems(const std::vector<UFortItemDefinition*>
|
|||||||
|
|
||||||
std::vector<std::pair<FGuid, int>> GuidAndCountsToRemove;
|
std::vector<std::pair<FGuid, int>> GuidAndCountsToRemove;
|
||||||
|
|
||||||
|
auto PickaxeInstance = WorldInventory->GetPickaxeInstance();
|
||||||
|
|
||||||
for (int i = 0; i < ItemInstances.Num(); i++)
|
for (int i = 0; i < ItemInstances.Num(); i++)
|
||||||
{
|
{
|
||||||
auto ItemInstance = ItemInstances.at(i);
|
auto ItemInstance = ItemInstances.at(i);
|
||||||
@@ -86,6 +88,13 @@ void AFortPlayerController::DropAllItems(const std::vector<UFortItemDefinition*>
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto ItemEntry = ItemInstance->GetItemEntry();
|
auto ItemEntry = ItemInstance->GetItemEntry();
|
||||||
|
|
||||||
|
if (RemovePickaxe && ItemInstance == PickaxeInstance)
|
||||||
|
{
|
||||||
|
GuidAndCountsToRemove.push_back({ ItemEntry->GetItemGuid(), ItemEntry->GetCount() });
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemEntry->GetItemDefinition());
|
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemEntry->GetItemDefinition());
|
||||||
|
|
||||||
if (!WorldItemDefinition || std::find(IgnoreItemDefs.begin(), IgnoreItemDefs.end(), WorldItemDefinition) != IgnoreItemDefs.end())
|
if (!WorldItemDefinition || std::find(IgnoreItemDefs.begin(), IgnoreItemDefs.end(), WorldItemDefinition) != IgnoreItemDefs.end())
|
||||||
@@ -482,16 +491,42 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
|
|||||||
auto VehicleWeapon = Pawn->EquipWeaponDefinition(VehicleWeaponDefinition, NewVehicleInstance->GetItemEntry()->GetItemGuid());
|
auto VehicleWeapon = Pawn->EquipWeaponDefinition(VehicleWeaponDefinition, NewVehicleInstance->GetItemEntry()->GetItemGuid());
|
||||||
// PlayerController->ServerExecuteInventoryItemHook(PlayerController, newitem->GetItemEntry()->GetItemGuid());
|
// PlayerController->ServerExecuteInventoryItemHook(PlayerController, newitem->GetItemEntry()->GetItemGuid());
|
||||||
|
|
||||||
/* if (WeaponComponent)
|
/* static auto GetSeatWeaponComponentFn = FindObject<UFunction>("/Script/FortniteGame.FortAthenaVehicle.GetSeatWeaponComponent");
|
||||||
|
|
||||||
|
if (GetSeatWeaponComponentFn)
|
||||||
{
|
{
|
||||||
|
struct { int SeatIndex; UObject* ReturnValue; } AFortAthenaVehicle_GetSeatWeaponComponent_Params{};
|
||||||
|
|
||||||
|
Vehicle->ProcessEvent(GetSeatWeaponComponentFn, &AFortAthenaVehicle_GetSeatWeaponComponent_Params);
|
||||||
|
|
||||||
|
UObject* WeaponComponent = AFortAthenaVehicle_GetSeatWeaponComponent_Params.ReturnValue;
|
||||||
|
|
||||||
|
if (!WeaponComponent)
|
||||||
|
return;
|
||||||
|
|
||||||
|
static auto WeaponSeatDefinitionStructSize = FindObject<UClass>("/Script/FortniteGame.WeaponSeatDefinition")->GetPropertiesSize();
|
||||||
|
static auto VehicleWeaponOffset = FindOffsetStruct("/Script/FortniteGame.WeaponSeatDefinition", "VehicleWeapon");
|
||||||
|
static auto SeatIndexOffset = FindOffsetStruct("/Script/FortniteGame.WeaponSeatDefinition", "SeatIndex");
|
||||||
|
static auto WeaponSeatDefinitionsOffset = WeaponComponent->GetOffset("WeaponSeatDefinitions");
|
||||||
|
auto& WeaponSeatDefinitions = WeaponComponent->Get<TArray<__int64>>(WeaponSeatDefinitionsOffset);
|
||||||
|
|
||||||
|
for (int i = 0; i < WeaponSeatDefinitions.Num(); i++)
|
||||||
|
{
|
||||||
|
auto WeaponSeat = WeaponSeatDefinitions.AtPtr(i, WeaponSeatDefinitionStructSize);
|
||||||
|
|
||||||
|
if (*(int*)(__int64(WeaponSeat) + SeatIndexOffset) != Vehicle->FindSeatIndex(Pawn))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto VehicleGrantedWeaponItem = (TWeakObjectPtr<UFortItem>*)(__int64(WeaponSeat) + 0x20);
|
||||||
|
|
||||||
|
VehicleGrantedWeaponItem->ObjectIndex = NewVehicleInstance->InternalIndex;
|
||||||
|
VehicleGrantedWeaponItem->ObjectSerialNumber = GetItemByIndex(NewVehicleInstance->InternalIndex)->SerialNumber;
|
||||||
|
|
||||||
static auto bWeaponEquippedOffset = WeaponComponent->GetOffset("bWeaponEquipped");
|
static auto bWeaponEquippedOffset = WeaponComponent->GetOffset("bWeaponEquipped");
|
||||||
WeaponComponent->Get<bool>(bWeaponEquippedOffset) = true;
|
WeaponComponent->Get<bool>(bWeaponEquippedOffset) = true;
|
||||||
|
|
||||||
static auto CachedWeaponOffset = WeaponComponent->GetOffset("CachedWeapon");
|
break;
|
||||||
WeaponComponent->Get<AFortWeapon*>(CachedWeaponOffset) = VehicleWeapon;
|
}
|
||||||
|
|
||||||
static auto CachedWeaponDefOffset = WeaponComponent->GetOffset("CachedWeaponDef");
|
|
||||||
WeaponComponent->Get<UFortWeaponItemDefinition*>(CachedWeaponDefOffset) = VehicleWeaponDefinition;
|
|
||||||
} */
|
} */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
return CosmeticLoadout;
|
return CosmeticLoadout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPickaxeToInventory()
|
UFortItem* AddPickaxeToInventory()
|
||||||
{
|
{
|
||||||
auto CosmeticLoadout = GetCosmeticLoadout();
|
auto CosmeticLoadout = GetCosmeticLoadout();
|
||||||
auto CosmeticLoadoutPickaxe = CosmeticLoadout ? CosmeticLoadout->GetPickaxe() : nullptr;
|
auto CosmeticLoadoutPickaxe = CosmeticLoadout ? CosmeticLoadout->GetPickaxe() : nullptr;
|
||||||
@@ -100,10 +100,12 @@ public:
|
|||||||
auto WorldInventory = GetWorldInventory();
|
auto WorldInventory = GetWorldInventory();
|
||||||
|
|
||||||
if (!WorldInventory || WorldInventory->GetPickaxeInstance())
|
if (!WorldInventory || WorldInventory->GetPickaxeInstance())
|
||||||
return;
|
return nullptr;
|
||||||
|
|
||||||
WorldInventory->AddItem(PickaxeDefinition, nullptr);
|
auto NewAndModifiedInstances = WorldInventory->AddItem(PickaxeDefinition, nullptr);
|
||||||
WorldInventory->Update();
|
WorldInventory->Update();
|
||||||
|
|
||||||
|
return NewAndModifiedInstances.first.size() > 0 ? NewAndModifiedInstances.first[0] : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool& ShouldTryPickupSwap()
|
bool& ShouldTryPickupSwap()
|
||||||
@@ -121,7 +123,7 @@ public:
|
|||||||
void ClientEquipItem(const FGuid& ItemGuid, bool bForceExecution);
|
void ClientEquipItem(const FGuid& ItemGuid, bool bForceExecution);
|
||||||
|
|
||||||
bool DoesBuildFree();
|
bool DoesBuildFree();
|
||||||
void DropAllItems(const std::vector<UFortItemDefinition*>& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar = false, bool bRemoveIfNotDroppable = false);
|
void DropAllItems(const std::vector<UFortItemDefinition*>& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar = false, bool bRemoveIfNotDroppable = false, bool RemovePickaxe = false);
|
||||||
void ApplyCosmeticLoadout();
|
void ApplyCosmeticLoadout();
|
||||||
|
|
||||||
static void ServerLoadingScreenDroppedHook(UObject* Context, FFrame* Stack, void* Ret);
|
static void ServerLoadingScreenDroppedHook(UObject* Context, FFrame* Stack, void* Ret);
|
||||||
|
|||||||
@@ -44,6 +44,13 @@ void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* S
|
|||||||
if (!WorldInventory)
|
if (!WorldInventory)
|
||||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||||
|
|
||||||
|
auto PickaxeInstance = WorldInventory->GetPickaxeInstance();
|
||||||
|
|
||||||
|
if (PickaxeInstance)
|
||||||
|
{
|
||||||
|
WorldInventory->RemoveItem(PickaxeInstance->GetItemEntry()->GetItemGuid(), nullptr, PickaxeInstance->GetItemEntry()->GetCount(), true);
|
||||||
|
}
|
||||||
|
|
||||||
bool bShouldUpdate = false;
|
bool bShouldUpdate = false;
|
||||||
auto NewAndModifiedInstances = WorldInventory->AddItem(ItemProvidingGhostMode, &bShouldUpdate, 1);
|
auto NewAndModifiedInstances = WorldInventory->AddItem(ItemProvidingGhostMode, &bShouldUpdate, 1);
|
||||||
auto GhostModeItemInstance = NewAndModifiedInstances.first[0];
|
auto GhostModeItemInstance = NewAndModifiedInstances.first[0];
|
||||||
@@ -51,7 +58,7 @@ void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* S
|
|||||||
if (!GhostModeItemInstance)
|
if (!GhostModeItemInstance)
|
||||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||||
|
|
||||||
if (bShouldUpdate)
|
// if (bShouldUpdate)
|
||||||
WorldInventory->Update();
|
WorldInventory->Update();
|
||||||
|
|
||||||
PlayerController->ServerExecuteInventoryItemHook(PlayerController, GhostModeItemInstance->GetItemEntry()->GetItemGuid());
|
PlayerController->ServerExecuteInventoryItemHook(PlayerController, GhostModeItemInstance->GetItemEntry()->GetItemGuid());
|
||||||
@@ -95,12 +102,20 @@ void AFortPlayerControllerAthena::EndGhostModeHook(AFortPlayerControllerAthena*
|
|||||||
if (!GhostModeItemInstance)
|
if (!GhostModeItemInstance)
|
||||||
return EndGhostModeOriginal(PlayerController);
|
return EndGhostModeOriginal(PlayerController);
|
||||||
|
|
||||||
|
auto PickaxeInstance = PlayerController->AddPickaxeToInventory();
|
||||||
|
WorldInventory->Update();
|
||||||
|
|
||||||
|
if (PickaxeInstance)
|
||||||
|
{
|
||||||
|
PlayerController->ClientEquipItem(PickaxeInstance->GetItemEntry()->GetItemGuid(), true);
|
||||||
|
}
|
||||||
|
|
||||||
bool bShouldUpdate = false;
|
bool bShouldUpdate = false;
|
||||||
int Count = GhostModeItemInstance->GetItemEntry()->GetCount(); // 1
|
int Count = GhostModeItemInstance->GetItemEntry()->GetCount(); // 1
|
||||||
bool bForceRemoval = true; // false
|
bool bForceRemoval = true; // false
|
||||||
WorldInventory->RemoveItem(GhostModeItemInstance->GetItemEntry()->GetItemGuid(), &bShouldUpdate, Count, bForceRemoval);
|
WorldInventory->RemoveItem(GhostModeItemInstance->GetItemEntry()->GetItemGuid(), &bShouldUpdate, Count, bForceRemoval);
|
||||||
|
|
||||||
if (bShouldUpdate)
|
// if (bShouldUpdate)
|
||||||
WorldInventory->Update();
|
WorldInventory->Update();
|
||||||
|
|
||||||
return EndGhostModeOriginal(PlayerController);
|
return EndGhostModeOriginal(PlayerController);
|
||||||
|
|||||||
@@ -140,17 +140,7 @@ UFortWeaponItemDefinition* AFortPlayerPawn::GetVehicleWeaponDefinition(AFortAthe
|
|||||||
if (!Vehicle)
|
if (!Vehicle)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
static auto FindSeatIndexFn = FindObject<UFunction>("/Script/FortniteGame.FortAthenaVehicle.FindSeatIndex");
|
return Vehicle->GetVehicleWeaponForSeat(Vehicle->FindSeatIndex(this));
|
||||||
/* auto Vehicle = GetVehicle();
|
|
||||||
|
|
||||||
if (!Vehicle)
|
|
||||||
return nullptr; */
|
|
||||||
|
|
||||||
struct { AFortPlayerPawn* PlayerPawn; int ReturnValue; } AFortAthenaVehicle_FindSeatIndex_Params{ this };
|
|
||||||
Vehicle->ProcessEvent(FindSeatIndexFn, &AFortAthenaVehicle_FindSeatIndex_Params);
|
|
||||||
|
|
||||||
auto SeatIndex = AFortAthenaVehicle_FindSeatIndex_Params.ReturnValue;
|
|
||||||
return Vehicle->GetVehicleWeaponForSeat(SeatIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AFortPlayerPawn::UnEquipVehicleWeaponDefinition(UFortWeaponItemDefinition* VehicleWeaponDefinition)
|
void AFortPlayerPawn::UnEquipVehicleWeaponDefinition(UFortWeaponItemDefinition* VehicleWeaponDefinition)
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ int UFortWeaponItemDefinition::GetClipSize()
|
|||||||
UFortWorldItemDefinition* UFortWeaponItemDefinition::GetAmmoData()
|
UFortWorldItemDefinition* UFortWeaponItemDefinition::GetAmmoData()
|
||||||
{
|
{
|
||||||
static auto AmmoDataOffset = GetOffset("AmmoData");
|
static auto AmmoDataOffset = GetOffset("AmmoData");
|
||||||
auto AmmoData = Get<TSoftObjectPtr<UFortWorldItemDefinition>>(AmmoDataOffset);
|
auto AmmoData = GetPtr<TSoftObjectPtr<UFortWorldItemDefinition>>(AmmoDataOffset);
|
||||||
return AmmoData.Get();
|
return AmmoData->Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
UClass* UFortWeaponItemDefinition::StaticClass()
|
UClass* UFortWeaponItemDefinition::StaticClass()
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ public:
|
|||||||
return ReadBitfieldValue(bCanBeDroppedOffset, bCanBeDroppedFieldMask);
|
return ReadBitfieldValue(bCanBeDroppedOffset, bCanBeDroppedFieldMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int& GetDropCount()
|
||||||
|
{
|
||||||
|
static auto DropCountOffset = GetOffset("DropCount");
|
||||||
|
return Get<int>(DropCountOffset);
|
||||||
|
}
|
||||||
|
|
||||||
EWorldItemDropBehavior& GetDropBehavior()
|
EWorldItemDropBehavior& GetDropBehavior()
|
||||||
{
|
{
|
||||||
static auto DropBehaviorOffset = GetOffset("DropBehavior");
|
static auto DropBehaviorOffset = GetOffset("DropBehavior");
|
||||||
|
|||||||
@@ -29,4 +29,9 @@ struct FName
|
|||||||
{
|
{
|
||||||
return ComparisonIndex.Value == other.ComparisonIndex.Value;
|
return ComparisonIndex.Value == other.ComparisonIndex.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator<(FName Other) const
|
||||||
|
{
|
||||||
|
return this->ComparisonIndex.Value < Other.ComparisonIndex.Value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@@ -335,6 +335,7 @@
|
|||||||
<ClInclude Include="FortItem.h" />
|
<ClInclude Include="FortItem.h" />
|
||||||
<ClInclude Include="FortItemDefinition.h" />
|
<ClInclude Include="FortItemDefinition.h" />
|
||||||
<ClInclude Include="FortKismetLibrary.h" />
|
<ClInclude Include="FortKismetLibrary.h" />
|
||||||
|
<ClInclude Include="FortLootLevel.h" />
|
||||||
<ClInclude Include="FortLootPackage.h" />
|
<ClInclude Include="FortLootPackage.h" />
|
||||||
<ClInclude Include="FortMinigame.h" />
|
<ClInclude Include="FortMinigame.h" />
|
||||||
<ClInclude Include="FortMountedCannon.h" />
|
<ClInclude Include="FortMountedCannon.h" />
|
||||||
|
|||||||
@@ -694,9 +694,6 @@
|
|||||||
<ClInclude Include="ReversePredicate.h">
|
<ClInclude Include="ReversePredicate.h">
|
||||||
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="UnrealTypeTraits.h">
|
|
||||||
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="IsEnum.h">
|
<ClInclude Include="IsEnum.h">
|
||||||
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
@@ -848,6 +845,12 @@
|
|||||||
<ClInclude Include="Vector2D.h">
|
<ClInclude Include="Vector2D.h">
|
||||||
<Filter>Engine\Source\Runtime\Core\Public\Math</Filter>
|
<Filter>Engine\Source\Runtime\Core\Public\Math</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="UnrealTypeTraits.h">
|
||||||
|
<Filter>Engine\Source\Runtime\Core\Public\Templates</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="FortLootLevel.h">
|
||||||
|
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Engine">
|
<Filter Include="Engine">
|
||||||
|
|||||||
@@ -490,7 +490,7 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Pawn = ReceivingController->GetMyFortPawn();
|
auto Pawn = ReceivingController->GetPawn();
|
||||||
|
|
||||||
if (!Pawn)
|
if (!Pawn)
|
||||||
{
|
{
|
||||||
@@ -519,11 +519,25 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
|
|||||||
|
|
||||||
if (ClassObj)
|
if (ClassObj)
|
||||||
{
|
{
|
||||||
|
int AmountSpawned = 0;
|
||||||
|
|
||||||
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;
|
||||||
GetWorld()->SpawnActor<AActor>(ClassObj, Loc, FQuat());
|
auto NewActor = GetWorld()->SpawnActor<AActor>(ClassObj, Loc, FQuat(), FVector(1, 1, 1), SpawnParameters);
|
||||||
|
|
||||||
|
if (!NewActor)
|
||||||
|
{
|
||||||
|
SendMessageToConsole(PlayerController, L"Failed to spawn an actor!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AmountSpawned++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendMessageToConsole(PlayerController, L"Summoned!");
|
SendMessageToConsole(PlayerController, L"Summoned!");
|
||||||
|
|||||||
@@ -627,12 +627,26 @@ static inline uint64 FindUpdateTrackedAttributesLea() // kill me
|
|||||||
|
|
||||||
static inline uint64 FindCombinePickupLea() // kill me
|
static inline uint64 FindCombinePickupLea() // kill me
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* uint64 OnRep_PickupLocationDataAddr = 0; // TODO (Idea: Find SetupCombinePickupDelegates from this).
|
/* uint64 OnRep_PickupLocationDataAddr = 0; // TODO (Idea: Find SetupCombinePickupDelegates from this).
|
||||||
|
|
||||||
if (!OnRep_PickupLocationDataAddr)
|
if (!OnRep_PickupLocationDataAddr)
|
||||||
return 0; */
|
return 0; */
|
||||||
|
|
||||||
uint64 SetupCombinePickupDelegatesAddr = Memcury::Scanner::FindPattern("48 89 AC 24 ? ? ? ? 48 89 B4 24 ? ? ? ? 48 89 BC 24 ? ? ? ? 0F 29 B4 24 ? ? ? ? 75").Get(); // Haha so funny thing, this isn't actually the start its the middle because it's in function chunks yay!
|
uint64 SetupCombinePickupDelegatesAddr = 0;
|
||||||
|
|
||||||
|
bool bShouldCheckSafety = true;
|
||||||
|
|
||||||
|
if (Engine_Version <= 420)
|
||||||
|
{
|
||||||
|
SetupCombinePickupDelegatesAddr = Memcury::Scanner::FindPattern("49 89 73 10 49 89 7B 18 4D 89 73 20 4D 89 7B E8 41 0F 29 73 ? 75").Get(); // found on 4.1
|
||||||
|
bShouldCheckSafety = false; // it's like "corrupted" and not just return
|
||||||
|
}
|
||||||
|
else if (Engine_Version >= 421)
|
||||||
|
{
|
||||||
|
SetupCombinePickupDelegatesAddr = Memcury::Scanner::FindPattern("48 89 AC 24 ? ? ? ? 48 89 B4 24 ? ? ? ? 48 89 BC 24 ? ? ? ? 0F 29 B4 24 ? ? ? ? 75").Get(); // Haha so funny thing, this isn't actually the start its the middle because it's in function chunks yay!
|
||||||
|
}
|
||||||
|
|
||||||
if (!SetupCombinePickupDelegatesAddr)
|
if (!SetupCombinePickupDelegatesAddr)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -644,7 +658,7 @@ static inline uint64 FindCombinePickupLea() // kill me
|
|||||||
{
|
{
|
||||||
auto loadAddress = Memcury::Scanner(SetupCombinePickupDelegatesAddr + i).RelativeOffset(3).Get();
|
auto loadAddress = Memcury::Scanner(SetupCombinePickupDelegatesAddr + i).RelativeOffset(3).Get();
|
||||||
|
|
||||||
if (IsNullSub(loadAddress)) // Safety
|
if (!bShouldCheckSafety || IsNullSub(loadAddress))
|
||||||
return SetupCombinePickupDelegatesAddr + i;
|
return SetupCombinePickupDelegatesAddr + i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,8 +48,9 @@
|
|||||||
#define DUMP_TAB 7
|
#define DUMP_TAB 7
|
||||||
#define UNBAN_TAB 8
|
#define UNBAN_TAB 8
|
||||||
#define DEVELOPER_TAB 9
|
#define DEVELOPER_TAB 9
|
||||||
#define SETTINGS_TAB 10
|
#define DEBUGLOG_TAB 10
|
||||||
#define CREDITS_TAB 11
|
#define SETTINGS_TAB 11
|
||||||
|
#define CREDITS_TAB 12
|
||||||
|
|
||||||
#define MAIN_PLAYERTAB 1
|
#define MAIN_PLAYERTAB 1
|
||||||
#define INVENTORY_PLAYERTAB 2
|
#define INVENTORY_PLAYERTAB 2
|
||||||
@@ -61,6 +62,8 @@ extern inline bool bSwitchedInitialLevel = false;
|
|||||||
extern inline bool bIsInAutoRestart = false;
|
extern inline bool bIsInAutoRestart = false;
|
||||||
extern inline float AutoBusStartSeconds = 60;
|
extern inline float AutoBusStartSeconds = 60;
|
||||||
extern inline int NumRequiredPlayersToStart = 2;
|
extern inline int NumRequiredPlayersToStart = 2;
|
||||||
|
extern inline bool bDebugPrintLooting = false;
|
||||||
|
extern inline bool bDebugPrintSwapping = false;
|
||||||
|
|
||||||
// THE BASE CODE IS FROM IMGUI GITHUB
|
// THE BASE CODE IS FROM IMGUI GITHUB
|
||||||
|
|
||||||
@@ -376,6 +379,14 @@ static inline void MainTabs()
|
|||||||
bInformationTab = false;
|
bInformationTab = false;
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui::BeginTabItem("Debug Logs"))
|
||||||
|
{
|
||||||
|
Tab = DEBUGLOG_TAB;
|
||||||
|
PlayerTab = -1;
|
||||||
|
bInformationTab = false;
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (false && ImGui::BeginTabItem(("Credits")))
|
if (false && ImGui::BeginTabItem(("Credits")))
|
||||||
@@ -954,6 +965,11 @@ static inline void MainUI()
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
else if (Tab == DEBUGLOG_TAB)
|
||||||
|
{
|
||||||
|
ImGui::Checkbox("Looting Debug Log", &bDebugPrintLooting);
|
||||||
|
ImGui::Checkbox("Swapping Debug Log", &bDebugPrintSwapping);
|
||||||
|
}
|
||||||
else if (Tab == SETTINGS_TAB)
|
else if (Tab == SETTINGS_TAB)
|
||||||
{
|
{
|
||||||
// ImGui::Checkbox("Use custom lootpool (from Win64/lootpool.txt)", &Defines::bCustomLootpool);
|
// ImGui::Checkbox("Use custom lootpool (from Win64/lootpool.txt)", &Defines::bCustomLootpool);
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ struct PlaceholderBitfield
|
|||||||
|
|
||||||
inline bool AreVehicleWeaponsEnabled()
|
inline bool AreVehicleWeaponsEnabled()
|
||||||
{
|
{
|
||||||
return Fortnite_Version < 9;
|
return Fortnite_Version > 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsRestartingSupported()
|
inline bool IsRestartingSupported()
|
||||||
|
|||||||
@@ -184,11 +184,22 @@ static inline void SpawnVehicles2()
|
|||||||
static auto FortAthenaVehicleSpawnerClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaVehicleSpawner");
|
static auto FortAthenaVehicleSpawnerClass = FindObject<UClass>("/Script/FortniteGame.FortAthenaVehicleSpawner");
|
||||||
TArray<AActor*> AllVehicleSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaVehicleSpawnerClass);
|
TArray<AActor*> AllVehicleSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaVehicleSpawnerClass);
|
||||||
|
|
||||||
|
int AmountOfVehiclesSpawned = 0;
|
||||||
|
|
||||||
for (int i = 0; i < AllVehicleSpawners.Num(); i++)
|
for (int i = 0; i < AllVehicleSpawners.Num(); i++)
|
||||||
{
|
{
|
||||||
auto VehicleSpawner = AllVehicleSpawners.at(i);
|
auto VehicleSpawner = AllVehicleSpawners.at(i);
|
||||||
auto Vehicle = SpawnVehicleFromSpawner(VehicleSpawner);
|
auto Vehicle = SpawnVehicleFromSpawner(VehicleSpawner);
|
||||||
|
|
||||||
|
if (Vehicle)
|
||||||
|
{
|
||||||
|
AmountOfVehiclesSpawned++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto AllVehicleSpawnersNum = AllVehicleSpawners.Num();
|
||||||
|
|
||||||
AllVehicleSpawners.Free();
|
AllVehicleSpawners.Free();
|
||||||
|
|
||||||
|
LOG_INFO(LogGame, "Spawned {}/{} vehicles.", AmountOfVehiclesSpawned, AllVehicleSpawnersNum);
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector,
|
|||||||
|
|
||||||
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
|
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
|
||||||
{
|
{
|
||||||
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(LootDrops[LootDropIt].ItemDefinition);
|
UFortWorldItemDefinition* WorldItemDefinition = Cast<UFortWorldItemDefinition>(LootDrops[LootDropIt]->GetItemDefinition());
|
||||||
|
|
||||||
if (!WorldItemDefinition)
|
if (!WorldItemDefinition)
|
||||||
continue;
|
continue;
|
||||||
@@ -182,7 +182,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].ItemDefinition, LootDrops[LootDropIt].Count, LootDrops[LootDropIt].LoadedAmmo);
|
auto ItemEntry = FFortItemEntry::MakeItemEntry(LootDrops[LootDropIt]->GetItemDefinition(), LootDrops[LootDropIt]->GetCount(), LootDrops[LootDropIt]->GetLoadedAmmo());
|
||||||
|
|
||||||
if (!ItemEntry)
|
if (!ItemEntry)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
8
vendor/memcury.h
vendored
8
vendor/memcury.h
vendored
@@ -1431,4 +1431,10 @@
|
|||||||
return PtrRef.ScanFor(Bytes, false).Get();
|
return PtrRef.ScanFor(Bytes, false).Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsNullSub(uint64 Addr) { return *(uint8_t*)(Addr) == 0xC3 || *(uint8_t*)(Addr) == 0xC2; }
|
inline bool IsNullSub(uint64 Addr)
|
||||||
|
{
|
||||||
|
// if (*(uint8_t*)(Addr) == 0xEB && *(uint8_t*)(Addr + 1) == 0xF7) // positive sp value has been detected, the output may be wrong!
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
return *(uint8_t*)(Addr) == 0xC3 || *(uint8_t*)(Addr) == 0xC2;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user