i broke the whole project but its fine

complete pickup rewrite, idle pawns
This commit is contained in:
Milxnor
2023-05-07 17:34:24 -04:00
parent 5e92f2e90b
commit 3405177d20
51 changed files with 1439 additions and 338 deletions

View File

@@ -54,10 +54,10 @@ public:
this->ProcessEvent(fn, &UAbilitySystemComponent_ClientActivateAbilityFailed_Params); this->ProcessEvent(fn, &UAbilitySystemComponent_ClientActivateAbilityFailed_Params);
} }
TArray<UObject*>& GetSpawnedAttributes() TArray<UAttributeSet*>& GetSpawnedAttributes()
{ {
static auto SpawnedAttributesOffset = GetOffset("SpawnedAttributes"); static auto SpawnedAttributesOffset = GetOffset("SpawnedAttributes");
return Get<TArray<UObject*>>(SpawnedAttributesOffset); return Get<TArray<UAttributeSet*>>(SpawnedAttributesOffset);
} }
FGameplayAbilitySpecContainer* GetActivatableAbilities() FGameplayAbilitySpecContainer* GetActivatableAbilities()

View File

@@ -52,6 +52,37 @@ public:
return DefaultCalculateSlackReserve(NumElements, NumBytesPerElement, false); return DefaultCalculateSlackReserve(NumElements, NumBytesPerElement, false);
} }
void ResizeArray(SizeType NewNum, SIZE_T NumBytesPerElement)
{
const SizeType CurrentMax = ArrayMax;
SizeType v3 = NewNum;
if (NewNum)
{
/* SizeType v6 = (unsigned __int64)FMemory::QuantizeSize(4 * NewNum, 0) >> 2;
// if (v3 > (int)v6)
// LODWORD(v6) = 0x7FFFFFFF;
v3 = v6; */
}
if (v3 != CurrentMax && (Data || v3))
Data = (InElementType*)FMemory::Realloc(Data, NumBytesPerElement * v3, 0);
ArrayNum = v3; // ?
ArrayMax = v3;
}
void CopyFromArray(TArray<InElementType>& OtherArray, SIZE_T NumBytesPerElement = sizeof(InElementType))
{
if (!OtherArray.ArrayNum && !ArrayMax)
{
ArrayMax = 0;
return;
}
ResizeArray(OtherArray.ArrayNum, NumBytesPerElement);
memcpy(this->Data, OtherArray.Data, NumBytesPerElement * OtherArray.ArrayNum);
}
/* /*
FORCENOINLINE void ResizeForCopy(SizeType NewMax, SizeType PrevMax, int ElementSize = sizeof(InElementType)) FORCENOINLINE void ResizeForCopy(SizeType NewMax, SizeType PrevMax, int ElementSize = sizeof(InElementType))
{ {
@@ -303,6 +334,7 @@ public:
// VirtualFree(Data, 0, MEM_RELEASE); // VirtualFree(Data, 0, MEM_RELEASE);
} }
Data = nullptr;
ArrayNum = 0; ArrayNum = 0;
ArrayMax = 0; ArrayMax = 0;
} }

View File

@@ -10,6 +10,26 @@ public:
struct FGameplayAttribute struct FGameplayAttribute
{ {
FString AttributeName; FString AttributeName;
void* Attribute; void* Attribute; // Property
UStruct* AttributeOwner; UStruct* AttributeOwner;
std::string GetAttributeName()
{
return AttributeName.ToString();
}
std::string GetAttributePropertyName()
{
if (!Attribute)
return "INVALIDATTRIBUTE";
FName* NamePrivate = nullptr;
if (Engine_Version >= 425)
NamePrivate = (FName*)(__int64(Attribute) + 0x28);
else
NamePrivate = &((UField*)Attribute)->NamePrivate;
return NamePrivate->ToString();
}
}; };

View File

@@ -5,8 +5,9 @@
#include "FortLootPackage.h" #include "FortLootPackage.h"
#include "FortPickup.h" #include "FortPickup.h"
#include "BuildingGameplayActor.h" #include "BuildingGameplayActor.h"
#include "KismetSystemLibrary.h"
void SpawnBGAs() // hahah not "proper", there's a function that we can hook and it gets called on each spawner whenever playlist gets set, but it's fine. static inline void SpawnBGAs() // hahah not "proper", there's a function that we can hook and it gets called on each spawner whenever playlist gets set, but it's fine.
{ {
static auto BGAConsumableSpawnerClass = FindObject<UClass>("/Script/FortniteGame.BGAConsumableSpawner"); static auto BGAConsumableSpawnerClass = FindObject<UClass>("/Script/FortniteGame.BGAConsumableSpawner");
@@ -24,6 +25,9 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
auto BGAConsumableSpawner = AllBGAConsumableSpawners.at(i); auto BGAConsumableSpawner = AllBGAConsumableSpawners.at(i);
auto SpawnLocation = BGAConsumableSpawner->GetActorLocation(); auto SpawnLocation = BGAConsumableSpawner->GetActorLocation();
static auto bAlignSpawnedActorsToSurfaceOffset = BGAConsumableSpawner->GetOffset("bAlignSpawnedActorsToSurface");
const bool bAlignSpawnedActorsToSurface = BGAConsumableSpawner->Get<bool>(bAlignSpawnedActorsToSurfaceOffset);
FTransform SpawnTransform{}; FTransform SpawnTransform{};
SpawnTransform.Translation = SpawnLocation; SpawnTransform.Translation = SpawnLocation;
SpawnTransform.Scale3D = FVector{ 1, 1, 1 }; SpawnTransform.Scale3D = FVector{ 1, 1, 1 };
@@ -55,20 +59,63 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
continue; continue;
} }
bool bDeferConstruction = false; // hm? bool bDeferConstruction = true; // hm?
FActorSpawnParameters SpawnParameters{}; FActorSpawnParameters SpawnParameters{};
// SpawnParameters.ObjectFlags = RF_Transactional; // idk fortnite does this i think // SpawnParameters.ObjectFlags = RF_Transactional; // idk fortnite does this i think // i think its acutally suppsoed to be |= RF_Transient
SpawnParameters.bDeferConstruction = bDeferConstruction; SpawnParameters.bDeferConstruction = bDeferConstruction;
auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnTransform, SpawnParameters); auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnTransform, SpawnParameters);
if (ConsumableActor) if (ConsumableActor)
{ {
if (bDeferConstruction) FTransform FinalSpawnTransform = SpawnTransform;
UGameplayStatics::FinishSpawningActor(ConsumableActor, SpawnTransform); // what
ConsumableActor->InitializeBuildingActor(nullptr, nullptr, true); // idk UFortKismetLibrary::SpawnBuildingGameplayActor does this if (bAlignSpawnedActorsToSurface)
{
// I DONT KNOW
/* FHitResult* NewHit = Alloc<FHitResult>(FHitResult::GetStructSize());
FVector StartLocation = FinalSpawnTransform.Translation;
FVector EndLocation = StartLocation - FVector(0, 0, 1000);
bool bTraceComplex = true; // idk
FName ProfileName = UKismetStringLibrary::Conv_StringToName(L"FindGroundLocationAt");
UKismetSystemLibrary::LineTraceSingleByProfile(ConsumableActor, StartLocation, EndLocation, ProfileName, bTraceComplex,
TArray<AActor*>(), EDrawDebugTrace::None, &NewHit, true, FLinearColor(), FLinearColor(), 0);
// UKismetSystemLibrary::LineTraceSingle(ConsumableActor, StartLocation, EndLocation,
// ETraceTypeQuery::TraceTypeQuery1, bTraceComplex, TArray<AActor*>(), EDrawDebugTrace::None, true, FLinearColor(), FLinearColor(), 0, &NewHit);
bool IsBlockingHit = NewHit && NewHit->IsBlockingHit(); // Should we check ret of linetracesingle?
if (IsBlockingHit)
{
FinalSpawnTransform.Translation = NewHit->GetLocation();
}
else
{
FinalSpawnTransform.Translation = FVector(0, 0, 0);
}
*/
}
if (FinalSpawnTransform.Translation == FVector(0, 0, 0))
{
LOG_WARN(LogGame, "Invalid BGA spawn location!");
// ConsumableActor->K2_DestroyActor(); // ??
continue;
}
if (bDeferConstruction)
UGameplayStatics::FinishSpawningActor(ConsumableActor, FinalSpawnTransform);
// ConsumableActor->InitializeBuildingActor(nullptr, nullptr, true); // idk UFortKismetLibrary::SpawnBuildingGameplayActor does this
LOG_INFO(LogDev, "Spawned BGA {} at {} {} {}", ConsumableActor->GetName(), FinalSpawnTransform.Translation.X, FinalSpawnTransform.Translation.Y, FinalSpawnTransform.Translation.Z);
} }
} }
} }

View File

@@ -6,10 +6,11 @@
bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn) bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
{ {
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
FVector LocationToSpawnLoot = this->GetActorLocation() + this->GetActorRightVector() * 70.f + FVector{ 0, 0, 50 }; FVector LocationToSpawnLoot = this->GetActorLocation() + this->GetActorRightVector() * 70.f + FVector{ 0, 0, 50 };
static auto SearchLootTierGroupOffset = this->GetOffset("SearchLootTierGroup"); static auto SearchLootTierGroupOffset = this->GetOffset("SearchLootTierGroup");
auto RedirectedLootTier = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode())->RedirectLootTier(this->Get<FName>(SearchLootTierGroupOffset)); auto RedirectedLootTier = GameMode->RedirectLootTier(this->Get<FName>(SearchLootTierGroupOffset));
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString()); // LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
@@ -20,7 +21,17 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
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->GetItemDefinition(), LocationToSpawnLoot, lootDrop->GetCount(), EFortPickupSourceTypeFlag::Container, EFortPickupSpawnSource::Unset, lootDrop->GetLoadedAmmo());
PickupCreateData CreateData{};
CreateData.bToss = true;
// CreateData.PawnOwner = Pawn;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(lootDrop->GetItemDefinition(), lootDrop->GetCount(), lootDrop->GetLoadedAmmo());
CreateData.SpawnLocation = LocationToSpawnLoot;
CreateData.SourceType = EFortPickupSourceTypeFlag::GetContainerValue();
CreateData.bRandomRotation = true;
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
auto NewPickup = AFortPickup::SpawnPickup(CreateData);
} }
return true; return true;

View File

@@ -3,6 +3,8 @@
#include "Object.h" #include "Object.h"
#include "addresses.h" #include "addresses.h"
#include "UnrealString.h"
#include "Map.h"
struct UField : UObject struct UField : UObject
{ {
@@ -28,3 +30,24 @@ class UFunction : public UStruct
public: public:
void*& GetFunc() { return *(void**)(__int64(this) + Offsets::Func); } void*& GetFunc() { return *(void**)(__int64(this) + Offsets::Func); }
}; };
class UEnum : public UField
{
public:
int64 GetValue(const std::string& EnumMemberName)
{
auto Names = (TArray<TPair<FName, __int64>>*)(__int64(this) + sizeof(UField) + sizeof(FString));
for (int i = 0; i < Names->Num(); i++)
{
auto& Pair = Names->At(i);
auto& Name = Pair.Key();
auto Value = Pair.Value();
if (Name.ComparisonIndex.Value && Name.ToString().contains(EnumMemberName))
return Value;
}
return -1;
}
};

View File

@@ -12,3 +12,22 @@ int FHitResult::GetStructSize()
{ {
return GetStruct()->GetPropertiesSize(); return GetStruct()->GetPropertiesSize();
} }
bool FHitResult::IsBlockingHit()
{
// return true;
static auto bBlockingHitOffset = FindOffsetStruct("/Script/Engine.HitResult", "bBlockingHit");
static auto bBlockingHitFieldMask = GetFieldMask(FindPropertyStruct("/Script/Engine.HitResult", "bBlockingHit"));
return ReadBitfield((PlaceholderBitfield*)(__int64(this) + bBlockingHitOffset), bBlockingHitFieldMask);
}
FVector& FHitResult::GetLocation()
{
static auto LocationOffset = FindOffsetStruct("/Script/Engine.HitResult", "Location");
return *(FVector*)(__int64(this) + LocationOffset);
}
void FHitResult::CopyFromHitResult(FHitResult* Other)
{
this->GetLocation() = Other->GetLocation();
}

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Object.h" #include "Object.h"
#include "Vector.h"
#include "DelegateCombinations.h" #include "DelegateCombinations.h"
@@ -17,6 +18,10 @@ struct FHitResult
{ {
static class UStruct* GetStruct(); static class UStruct* GetStruct();
static int GetStructSize(); static int GetStructSize();
bool IsBlockingHit();
FVector& GetLocation();
void CopyFromHitResult(FHitResult* Other);
}; };
struct FTimerHandle struct FTimerHandle

View File

@@ -83,7 +83,7 @@ public:
if (!AbilityClass) if (!AbilityClass)
continue; continue;
LOG_INFO(LogDev, "Giving AbilityClass {}", AbilityClass->GetFullName()); // LOG_INFO(LogDev, "Giving AbilityClass {}", AbilityClass->GetFullName());
AbilitySystemComponent->GiveAbilityEasy(AbilityClass, SourceObject); AbilitySystemComponent->GiveAbilityEasy(AbilityClass, SourceObject);
} }

View File

@@ -44,7 +44,14 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnGameModePickupHook(UObject* Context, FF
LOG_INFO(LogDev, "Spawning GameModePickup with ItemDefinition: {}", ItemDefinition->GetFullName()); LOG_INFO(LogDev, "Spawning GameModePickup with ItemDefinition: {}", ItemDefinition->GetFullName());
*Ret = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::SupplyDrop, -1, TriggeringPawn, PickupClass); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.SpawnLocation = Position;
CreateData.PawnOwner = TriggeringPawn;
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
CreateData.OverrideClass = PickupClass;
*Ret = AFortPickup::SpawnPickup(CreateData);
return *Ret; return *Ret;
} }
@@ -67,7 +74,13 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnPickupHook(UObject* Context, FFrame& St
if (!ItemDefinition) if (!ItemDefinition)
return nullptr; return nullptr;
*Ret = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::SupplyDrop, -1, TriggeringPawn); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.SpawnLocation = Position;
CreateData.PawnOwner = TriggeringPawn;
CreateData.Source = EFortPickupSpawnSource::GetSupplyDropValue();
*Ret = AFortPickup::SpawnPickup(CreateData);
return *Ret; return *Ret;
} }

View File

@@ -30,6 +30,12 @@ public:
return ReadBitfieldValue(bDestroyGadgetWhenTrackedAttributesIsZeroOffset, bDestroyGadgetWhenTrackedAttributesIsZeroFieldMask); return ReadBitfieldValue(bDestroyGadgetWhenTrackedAttributesIsZeroOffset, bDestroyGadgetWhenTrackedAttributesIsZeroFieldMask);
} }
TArray<FGameplayAttribute>& GetTrackedAttributes()
{
static auto TrackedAttributesOffset = GetOffset("TrackedAttributes");
return Get<TArray<FGameplayAttribute>>(TrackedAttributesOffset);
}
UAttributeSet* GetAttributeSet() UAttributeSet* GetAttributeSet()
{ {
static auto AttributeSetOffset = this->GetOffset("AttributeSet", false); static auto AttributeSetOffset = this->GetOffset("AttributeSet", false);

View File

@@ -8,6 +8,7 @@
#include "FortLootPackage.h" #include "FortLootPackage.h"
#include "FortPlayerPawn.h" #include "FortPlayerPawn.h"
#include "FortPickup.h" #include "FortPickup.h"
#include "bots.h"
#include "FortAbilitySet.h" #include "FortAbilitySet.h"
#include "NetSerialization.h" #include "NetSerialization.h"
@@ -553,6 +554,11 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
GetWorld()->Listen(); GetWorld()->Listen();
if (AmountOfBotsToSpawn != 0)
{
Bots::SpawnBotsAtPlayerStarts(AmountOfBotsToSpawn);
}
// GameState->OnRep_CurrentPlaylistInfo(); // GameState->OnRep_CurrentPlaylistInfo();
// return false; // return false;
@@ -698,6 +704,15 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller) int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller)
{ {
bool bIsBot = false;
auto PlayerState = ((APlayerController*)Controller)->GetPlayerState();
if (PlayerState)
{
bIsBot = PlayerState->IsBot();
}
// VERY BASIC IMPLEMENTATION // VERY BASIC IMPLEMENTATION
LOG_INFO(LogTeams, "PickTeam called!"); LOG_INFO(LogTeams, "PickTeam called!");
@@ -939,7 +954,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
float UpZ = 50; float UpZ = 50;
EFortPickupSourceTypeFlag SpawnFlag = EFortPickupSourceTypeFlag::Container; uint8 SpawnFlag = EFortPickupSourceTypeFlag::GetContainerValue();
bool bTest = false; bool bTest = false;
bool bPrintWarmup = false; bool bPrintWarmup = false;
@@ -947,25 +962,22 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++) for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++)
{ {
ABuildingContainer* CurrentActor = (ABuildingContainer*)SpawnIsland_FloorLoot_Actors.at(i); ABuildingContainer* CurrentActor = (ABuildingContainer*)SpawnIsland_FloorLoot_Actors.at(i);
auto Location = CurrentActor->GetActorLocation();
Location.Z += UpZ;
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, bPrintWarmup);
for (auto& LootDrop : LootDrops)
{ {
auto Location = CurrentActor->GetActorLocation(); PickupCreateData CreateData;
Location.Z += UpZ; CreateData.bToss = true;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
CreateData.SpawnLocation = Location;
CreateData.SourceType = SpawnFlag;
CreateData.bRandomRotation = true;
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, bPrintWarmup); auto Pickup = AFortPickup::SpawnPickup(CreateData);
if (bPrintWarmup)
{
std::cout << "\n\n";
}
if (LootDrops.size())
{
for (auto& LootDrop : LootDrops)
{
auto Pickup = AFortPickup::SpawnPickup(LootDrop->GetItemDefinition(), Location, LootDrop->GetCount(), SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop->GetLoadedAmmo());
}
}
} }
if (!bTest) if (!bTest)
@@ -979,33 +991,31 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
for (int i = 0; i < BRIsland_FloorLoot_Actors.Num(); i++) for (int i = 0; i < BRIsland_FloorLoot_Actors.Num(); i++)
{ {
ABuildingContainer* CurrentActor = (ABuildingContainer*)BRIsland_FloorLoot_Actors.at(i); ABuildingContainer* CurrentActor = (ABuildingContainer*)BRIsland_FloorLoot_Actors.at(i);
// CurrentActor->K2_DestroyActor();
spawned++; spawned++;
// continue;
auto Location = CurrentActor->GetActorLocation(); auto Location = CurrentActor->GetActorLocation();
Location.Z += UpZ; Location.Z += UpZ;
std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, bPrint); std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, bPrint);
if (bPrint) for (auto& LootDrop : LootDrops)
std::cout << "\n";
if (LootDrops.size())
{ {
for (auto& LootDrop : LootDrops) PickupCreateData CreateData;
{ CreateData.bToss = true;
auto Pickup = AFortPickup::SpawnPickup(LootDrop->GetItemDefinition(), Location, LootDrop->GetCount(), SpawnFlag, EFortPickupSpawnSource::Unset, LootDrop->GetLoadedAmmo()); CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
} CreateData.SpawnLocation = Location;
CreateData.SourceType = SpawnFlag;
CreateData.bRandomRotation = true;
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
auto Pickup = AFortPickup::SpawnPickup(CreateData);
} }
if (!bTest) if (!bTest)
CurrentActor->K2_DestroyActor(); CurrentActor->K2_DestroyActor();
} }
// SpawnIsland_FloorLoot_Actors.Free(); SpawnIsland_FloorLoot_Actors.Free();
// BRIsland_FloorLoot_Actors.Free(); BRIsland_FloorLoot_Actors.Free();
LOG_INFO(LogDev, "Spawned loot!"); LOG_INFO(LogDev, "Spawned loot!");
} }
@@ -1058,7 +1068,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
static auto SquadIdOffset = PlayerStateAthena->GetOffset("SquadId", false); static auto SquadIdOffset = PlayerStateAthena->GetOffset("SquadId", false);
if (SquadIdOffset != -1) if (SquadIdOffset != -1)
PlayerStateAthena->GetSquadId() = PlayerStateAthena->GetTeamIndex() - 2; PlayerStateAthena->GetSquadId() = PlayerStateAthena->GetTeamIndex() - 2; // wrong place to do this
// idk if this is needed // idk if this is needed
@@ -1075,9 +1085,6 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
static auto OnRep_bHasStartedPlayingFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerState.OnRep_bHasStartedPlaying"); static auto OnRep_bHasStartedPlayingFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerState.OnRep_bHasStartedPlaying");
PlayerStateAthena->ProcessEvent(OnRep_bHasStartedPlayingFn); PlayerStateAthena->ProcessEvent(OnRep_bHasStartedPlayingFn);
LOG_INFO(LogDev, "Old ID: {}", PlayerStateAthena->GetWorldPlayerId());
LOG_INFO(LogDev, "PlayerID: {}", PlayerStateAthena->GetPlayerID());
PlayerStateAthena->GetWorldPlayerId() = PlayerStateAthena->GetPlayerID(); PlayerStateAthena->GetWorldPlayerId() = PlayerStateAthena->GetPlayerID();
auto PlayerAbilitySet = GetPlayerAbilitySet(); auto PlayerAbilitySet = GetPlayerAbilitySet();
@@ -1088,9 +1095,15 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
PlayerAbilitySet->GiveToAbilitySystem(AbilitySystemComponent); PlayerAbilitySet->GiveToAbilitySystem(AbilitySystemComponent);
} }
struct FUniqueNetIdReplExperimental struct FUniqueNetIdWrapper
{ {
unsigned char ahh[0x0028]; unsigned char UnknownData00[0x1]; // 0x0000(0x0001) MISSED OFFSET
};
struct FUniqueNetIdReplExperimental : public FUniqueNetIdWrapper
{
unsigned char UnknownData00[0x17]; // 0x0001(0x0017) MISSED OFFSET
TArray<unsigned char> ReplicationBytes; // 0x0018(0x0010) (ZeroConstructor, Transient, Protected, NativeAccessSpecifierProtected)
}; };
static auto PlayerCameraManagerOffset = NewPlayer->GetOffset("PlayerCameraManager"); static auto PlayerCameraManagerOffset = NewPlayer->GetOffset("PlayerCameraManager");
@@ -1105,12 +1118,10 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
PlayerCameraManager->Get<float>(ViewRollMaxOffset) = 0; PlayerCameraManager->Get<float>(ViewRollMaxOffset) = 0;
} }
/* FUniqueNetIdReplExperimental Bugha{}; */
static auto UniqueIdOffset = PlayerStateAthena->GetOffset("UniqueId"); static auto UniqueIdOffset = PlayerStateAthena->GetOffset("UniqueId");
auto PlayerStateUniqueId = PlayerStateAthena->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset); auto PlayerStateUniqueId = PlayerStateAthena->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset);
{ {
LOG_INFO(LogDev, "bruh");
static auto GameMemberInfoArrayOffset = GameState->GetOffset("GameMemberInfoArray", false); static auto GameMemberInfoArrayOffset = GameState->GetOffset("GameMemberInfoArray", false);
// if (false) // if (false)
@@ -1150,7 +1161,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
((FGameMemberInfo*)GameMemberInfo)->SquadId = PlayerStateAthena->GetSquadId(); ((FGameMemberInfo*)GameMemberInfo)->SquadId = PlayerStateAthena->GetSquadId();
((FGameMemberInfo*)GameMemberInfo)->TeamIndex = PlayerStateAthena->GetTeamIndex(); ((FGameMemberInfo*)GameMemberInfo)->TeamIndex = PlayerStateAthena->GetTeamIndex();
// GameMemberInfo->MemberUniqueId = PlayerStateUniqueId; // GameMemberInfo->MemberUniqueId = PlayerStateUniqueId;
CopyStruct(&((FGameMemberInfo*)GameMemberInfo)->MemberUniqueId, PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct()); ((FUniqueNetIdRepl*)&((FGameMemberInfo*)GameMemberInfo)->MemberUniqueId)->CopyFromAnotherUniqueId(PlayerStateUniqueId);
} }
static auto GameMemberInfoArray_MembersOffset = FindOffsetStruct("/Script/FortniteGame.GameMemberInfoArray", "Members"); static auto GameMemberInfoArray_MembersOffset = FindOffsetStruct("/Script/FortniteGame.GameMemberInfoArray", "Members");
@@ -1260,7 +1271,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
if (LevelSaveComponent) if (LevelSaveComponent)
{ {
static auto AccountIdOfOwnerOffset = LevelSaveComponent->GetOffset("AccountIdOfOwner"); static auto AccountIdOfOwnerOffset = LevelSaveComponent->GetOffset("AccountIdOfOwner");
CopyStruct(LevelSaveComponent->GetPtr<FUniqueNetIdReplExperimental>(AccountIdOfOwnerOffset), PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct()); LevelSaveComponent->GetPtr<FUniqueNetIdRepl>(AccountIdOfOwnerOffset)->CopyFromAnotherUniqueId(PlayerStateUniqueId);
// CopyStruct(LevelSaveComponent->GetPtr<FUniqueNetIdReplExperimental>(AccountIdOfOwnerOffset), PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct());
// LevelSaveComponent->Get<FUniqueNetIdReplExperimental>(AccountIdOfOwnerOffset) = PlayerStateUniqueId; // LevelSaveComponent->Get<FUniqueNetIdReplExperimental>(AccountIdOfOwnerOffset) = PlayerStateUniqueId;
static auto bIsLoadedOffset = LevelSaveComponent->GetOffset("bIsLoaded"); static auto bIsLoadedOffset = LevelSaveComponent->GetOffset("bIsLoaded");

View File

@@ -8,6 +8,7 @@
#include "FortSafeZoneIndicator.h" #include "FortSafeZoneIndicator.h"
#include "GameplayStatics.h" #include "GameplayStatics.h"
#include "FortAbilitySet.h" #include "FortAbilitySet.h"
#include "FortPlayerControllerAthena.h"
#include "FortItemDefinition.h" #include "FortItemDefinition.h"
struct FAircraftFlightInfo struct FAircraftFlightInfo
@@ -233,6 +234,12 @@ public:
return Get<TArray<FItemAndCount>>(StartingItemsOffset); return Get<TArray<FItemAndCount>>(StartingItemsOffset);
} }
TArray<AFortPlayerControllerAthena*>& GetAlivePlayers()
{
static auto AlivePlayersOffset = GetOffset("AlivePlayers");
return Get<TArray<AFortPlayerControllerAthena*>>(AlivePlayersOffset);
}
FName RedirectLootTier(const FName& LootTier); FName RedirectLootTier(const FName& LootTier);
UClass* GetVehicleClassOverride(UClass* DefaultClass); UClass* GetVehicleClassOverride(UClass* DefaultClass);

View File

@@ -244,3 +244,13 @@ void AFortGameStateAthena::OnRep_CurrentPlaylistInfo()
this->ProcessEvent(OnRep_CurrentPlaylistInfo); this->ProcessEvent(OnRep_CurrentPlaylistInfo);
} }
} }
void AFortGameStateAthena::OnRep_PlayersLeft()
{
static auto OnRep_PlayersLeftFn = FindObject<UFunction>("/Script/FortniteGame.FortGameStateAthena.OnRep_PlayersLeft");
if (!OnRep_PlayersLeftFn)
return;
this->ProcessEvent(OnRep_PlayersLeftFn);
}

View File

@@ -104,6 +104,7 @@ public:
bool IsPlayerBuildableClass(UClass* Class); bool IsPlayerBuildableClass(UClass* Class);
void OnRep_GamePhase(); void OnRep_GamePhase();
void OnRep_CurrentPlaylistInfo(); void OnRep_CurrentPlaylistInfo();
void OnRep_PlayersLeft();
}; };
static void* ConstructOnGamePhaseStepChangedParams(EAthenaGamePhaseStep GamePhaseStep) static void* ConstructOnGamePhaseStepChangedParams(EAthenaGamePhaseStep GamePhaseStep)

View File

@@ -110,7 +110,13 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
if (!Pawn) if (!Pawn)
return std::make_pair(NewItemInstances, ModifiedItemInstances); return std::make_pair(NewItemInstances, ModifiedItemInstances);
AFortPickup::SpawnPickup(ItemDefinition, Pawn->GetActorLocation(), Count, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, Cast<AFortPawn>(Pawn)); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, Count, -1);
CreateData.SpawnLocation = Pawn->GetActorLocation();
CreateData.PawnOwner = Cast<AFortPawn>(Pawn);
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
AFortPickup::SpawnPickup(CreateData);
return std::make_pair(NewItemInstances, ModifiedItemInstances); return std::make_pair(NewItemInstances, ModifiedItemInstances);
} }
@@ -126,21 +132,21 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
NewItemInstances.push_back(NewItemInstance); NewItemInstances.push_back(NewItemInstance);
static auto FortItemEntryStruct = FindObject(L"/Script/FortniteGame.FortItemEntry");
static auto FortItemEntrySize = *(int*)(__int64(FortItemEntryStruct) + Offsets::PropertiesSize);
bool bEnableStateValues = false; // Addresses::FreeEntry; bool bEnableStateValues = false; // Addresses::FreeEntry;
if (bEnableStateValues) if (bEnableStateValues)
{ {
FFortItemEntryStateValue* StateValue = Alloc<FFortItemEntryStateValue>(FFortItemEntryStateValue::GetStructSize(), true); // FFortItemEntryStateValue* StateValue = Alloc<FFortItemEntryStateValue>(FFortItemEntryStateValue::GetStructSize(), true);
StateValue->GetIntValue() = bShowItemToast; PadHexA8 StateValue{};
StateValue->GetStateType() = EFortItemEntryState::ShouldShowItemToast; ((FFortItemEntryStateValue*)&StateValue)->GetIntValue() = bShowItemToast;
NewItemInstance->GetItemEntry()->GetStateValues().AddPtr(StateValue, FFortItemEntryStateValue::GetStructSize()); ((FFortItemEntryStateValue*)&StateValue)->GetStateType() = EFortItemEntryState::ShouldShowItemToast;
((FFortItemEntryStateValue*)&StateValue)->GetNameValue() = FName(0);
NewItemInstance->GetItemEntry()->GetStateValues().AddPtr((FFortItemEntryStateValue*)&StateValue, FFortItemEntryStateValue::GetStructSize());
} }
ItemInstances.Add(NewItemInstance); ItemInstances.Add(NewItemInstance);
auto ReplicatedEntryIdx = GetItemList().GetReplicatedEntries().Add(*NewItemInstance->GetItemEntry(), FortItemEntrySize); auto ReplicatedEntryIdx = GetItemList().GetReplicatedEntries().Add(*NewItemInstance->GetItemEntry(), FFortItemEntry::GetStructSize());
// GetItemList().GetReplicatedEntries().AtPtr(ReplicatedEntryIdx, FFortItemEntry::GetStructSize())->GetIsReplicatedCopy() = true; // GetItemList().GetReplicatedEntries().AtPtr(ReplicatedEntryIdx, FFortItemEntry::GetStructSize())->GetIsReplicatedCopy() = true;
if (FortPlayerController && WorldItemDefinition->IsValidLowLevel()) if (FortPlayerController && WorldItemDefinition->IsValidLowLevel())
@@ -267,55 +273,61 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int
int OldCount = Count; int OldCount = Count;
bool bLikeReallyForce = false;
if (Count < 0) // idk why i have this if (Count < 0) // idk why i have this
{ {
Count = 0; Count = 0;
bForceRemoval = true; bForceRemoval = true;
bLikeReallyForce = true;
} }
auto NewCount = ReplicatedEntry->GetCount() - Count;
auto& ItemInstances = GetItemList().GetItemInstances(); auto& ItemInstances = GetItemList().GetItemInstances();
auto& ReplicatedEntries = GetItemList().GetReplicatedEntries(); auto& ReplicatedEntries = GetItemList().GetReplicatedEntries();
bool bOverrideChangeStackSize = false; if (!bLikeReallyForce)
if (ItemDefinition->ShouldPersistWhenFinalStackEmpty() && !bForceRemoval)
{ {
bool bIsFinalStack = true; auto NewCount = ReplicatedEntry->GetCount() - Count;
for (int i = 0; i < ItemInstances.Num(); i++) bool bOverrideChangeStackSize = false;
if (ItemDefinition->ShouldPersistWhenFinalStackEmpty())
{ {
auto ItemInstance = ItemInstances.at(i); bool bIsFinalStack = true;
if (ItemInstance->GetItemEntry()->GetItemDefinition() == ItemDefinition && ItemInstance->GetItemEntry()->GetItemGuid() != ItemGuid) for (int i = 0; i < ItemInstances.Num(); i++)
{ {
bIsFinalStack = false; auto ItemInstance = ItemInstances.at(i);
break;
if (ItemInstance->GetItemEntry()->GetItemDefinition() == ItemDefinition && ItemInstance->GetItemEntry()->GetItemGuid() != ItemGuid)
{
bIsFinalStack = false;
break;
}
}
if (bIsFinalStack)
{
NewCount = NewCount < 0 ? 0 : NewCount; // min(NewCount, 0) or something i forgot
bOverrideChangeStackSize = true;
} }
} }
if (bIsFinalStack) if (OldCount != -1 && (NewCount > 0 || bOverrideChangeStackSize))
{ {
NewCount = NewCount < 0 ? 0 : NewCount; // min(NewCount, 0) or something i forgot ItemInstance->GetItemEntry()->GetCount() = NewCount;
bOverrideChangeStackSize = true; ReplicatedEntry->GetCount() = NewCount;
GetItemList().MarkItemDirty(ItemInstance->GetItemEntry());
GetItemList().MarkItemDirty(ReplicatedEntry);
return true;
} }
if (NewCount < 0) // Hm
return false;
} }
if (OldCount != -1 && (NewCount > 0 || bOverrideChangeStackSize))
{
ItemInstance->GetItemEntry()->GetCount() = NewCount;
ReplicatedEntry->GetCount() = NewCount;
GetItemList().MarkItemDirty(ItemInstance->GetItemEntry());
GetItemList().MarkItemDirty(ReplicatedEntry);
return true;
}
if (NewCount < 0) // Hm
return false;
static auto FortItemEntryStruct = FindObject<UStruct>(L"/Script/FortniteGame.FortItemEntry"); static auto FortItemEntryStruct = FindObject<UStruct>(L"/Script/FortniteGame.FortItemEntry");
static auto FortItemEntrySize = FortItemEntryStruct->GetPropertiesSize(); static auto FortItemEntrySize = FortItemEntryStruct->GetPropertiesSize();
@@ -557,3 +569,9 @@ FFortItemEntry* AFortInventory::FindReplicatedEntry(const FGuid& Guid)
return nullptr; return nullptr;
} }
/* UClass* AFortInventory::StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortInventory");
return Class;
} */

View File

@@ -110,4 +110,6 @@ public:
UFortItem* FindItemInstance(const FGuid& Guid); UFortItem* FindItemInstance(const FGuid& Guid);
FFortItemEntry* FindReplicatedEntry(const FGuid& Guid); FFortItemEntry* FindReplicatedEntry(const FGuid& Guid);
// static UClass* StaticClass();
}; };

View File

@@ -1,5 +1,40 @@
#include "FortItem.h" #include "FortItem.h"
#include "FortWeaponItemDefinition.h"
FFortItemEntry* FFortItemEntry::MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count, int LoadedAmmo, float Durability)
{
auto Entry = // (FFortItemEntry*)FMemory::Realloc(0, GetStructSize(), 0);
Alloc<FFortItemEntry>(GetStructSize());
if (!Entry)
return nullptr;
if (LoadedAmmo == -1)
{
if (auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDefinition)) // bPreventDefaultPreload ?
LoadedAmmo = WeaponDef->GetClipSize();
else
LoadedAmmo = 0;
}
Entry->MostRecentArrayReplicationKey = -1; // idk if we need to set this
Entry->ReplicationID = -1;
Entry->ReplicationKey = -1;
Entry->GetItemDefinition() = ItemDefinition;
Entry->GetCount() = Count;
Entry->GetLoadedAmmo() = LoadedAmmo;
Entry->GetDurability() = Durability;
Entry->GetGameplayAbilitySpecHandle() = FGameplayAbilitySpecHandle(-1);
Entry->GetParentInventory().ObjectIndex = -1;
// We want to add StateValues.Add(DurabilityInitialized); orwnatefc erwgearf yk
// CoCreateGuid((GUID*)&Entry->GetItemGuid());
// Entry->DoesUpdateStatsOnCollection() = true; // I think fortnite does this?
return Entry;
}
void UFortItem::SetOwningControllerForTemporaryItem(UObject* Controller) void UFortItem::SetOwningControllerForTemporaryItem(UObject* Controller)
{ {
static auto SOCFTIFn = FindObject<UFunction>(L"/Script/FortniteGame.FortItem.SetOwningControllerForTemporaryItem"); static auto SOCFTIFn = FindObject<UFunction>(L"/Script/FortniteGame.FortItem.SetOwningControllerForTemporaryItem");

View File

@@ -8,7 +8,7 @@
#include "reboot.h" #include "reboot.h"
enum class EFortItemEntryState : uint8_t // idk if this changes enum class EFortItemEntryState : uint8_t // this changes but its fineee
{ {
NoneState = 0, NoneState = 0,
NewItemCount = 1, NewItemCount = 1,
@@ -74,6 +74,13 @@ struct FFortItemEntry : FFastArraySerializerItem
return *(bool*)(__int64(this) + bIsReplicatedCopyOffset); return *(bool*)(__int64(this) + bIsReplicatedCopyOffset);
} }
bool& DoesUpdateStatsOnCollection()
{
// added like s8+ or somethingf idsk it was on 10.40 but not 7.40
static auto bUpdateStatsOnCollectionOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "bUpdateStatsOnCollection");
return *(bool*)(__int64(this) + bUpdateStatsOnCollectionOffset);
}
class UFortItemDefinition*& GetItemDefinition() class UFortItemDefinition*& GetItemDefinition()
{ {
static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ItemDefinition"); static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ItemDefinition");
@@ -116,6 +123,12 @@ struct FFortItemEntry : FFastArraySerializerItem
return *(FGameplayAbilitySpecHandle*)(__int64(this) + GameplayAbilitySpecHandleOffset); return *(FGameplayAbilitySpecHandle*)(__int64(this) + GameplayAbilitySpecHandleOffset);
} }
TArray<float>& GetGenericAttributeValues()
{
static auto GenericAttributeValuesOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "GenericAttributeValues");
return *(TArray<float>*)(__int64(this) + GenericAttributeValuesOffset);
}
TWeakObjectPtr<class AFortInventory>& GetParentInventory() TWeakObjectPtr<class AFortInventory>& GetParentInventory()
{ {
static auto ParentInventoryOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ParentInventory"); static auto ParentInventoryOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ParentInventory");
@@ -144,6 +157,20 @@ struct FFortItemEntry : FFastArraySerializerItem
if (!bCopyGuid) if (!bCopyGuid)
this->GetItemGuid() = OldGuid; this->GetItemGuid() = OldGuid;
static auto GenericAttributeValuesOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "GenericAttributeValues", false);
if (GenericAttributeValuesOffset != -1)
{
// proper copying
this->GetGenericAttributeValues().CopyFromArray(OtherItemEntry->GetGenericAttributeValues());
/* for (int i = 0; i < OtherItemEntry->GetGenericAttributeValues().Num(); i++)
{
this->GetGenericAttributeValues().Add(OtherItemEntry->GetGenericAttributeValues().at(i));
} */
}
// should we do this? // should we do this?
this->MostRecentArrayReplicationKey = -1; this->MostRecentArrayReplicationKey = -1;
@@ -163,29 +190,7 @@ struct FFortItemEntry : FFastArraySerializerItem
return StructSize; return StructSize;
} }
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000) static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, float Durability = 0x3F800000);
{
auto Entry = // (FFortItemEntry*)FMemory::Realloc(0, GetStructSize(), 0);
Alloc<FFortItemEntry>(GetStructSize());
if (!Entry)
return nullptr;
Entry->MostRecentArrayReplicationKey = -1; // idk if we need to set this
Entry->ReplicationID = -1;
Entry->ReplicationKey = -1;
Entry->GetItemDefinition() = ItemDefinition;
Entry->GetCount() = Count;
Entry->GetLoadedAmmo() = LoadedAmmo;
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;
}
// We need to find a better way for below... Especially since we can't do either method for season 5 or 6. // We need to find a better way for below... Especially since we can't do either method for season 5 or 6.
@@ -196,6 +201,19 @@ struct FFortItemEntry : FFastArraySerializerItem
static __int64 (*FreeEntryOriginal)(__int64 Entry) = decltype(FreeEntryOriginal)(Addresses::FreeEntry); static __int64 (*FreeEntryOriginal)(__int64 Entry) = decltype(FreeEntryOriginal)(Addresses::FreeEntry);
FreeEntryOriginal(__int64(Entry)); FreeEntryOriginal(__int64(Entry));
} }
else
{
static auto GenericAttributeValuesOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "GenericAttributeValues", false);
if (GenericAttributeValuesOffset != -1)
{
Entry->GetGenericAttributeValues().Free();
}
Entry->GetStateValues().Free();
}
RtlZeroMemory(Entry, FFortItemEntry::GetStructSize());
} }
static void FreeArrayOfEntries(TArray<FFortItemEntry>& tarray) static void FreeArrayOfEntries(TArray<FFortItemEntry>& tarray)

View File

@@ -136,7 +136,11 @@ void UFortKismetLibrary::SpawnItemVariantPickupInWorldHook(UObject* Context, FFr
LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z); LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z);
auto Pickup = AFortPickup::SpawnPickup(ItemDefinition, Position, ParamsPtr->GetNumberToSpawn(), ParamsPtr->GetSourceType(), ParamsPtr->GetSource()); PickupCreateData CreateData{};
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, ParamsPtr->GetNumberToSpawn(), -1);
CreateData.SourceType = ParamsPtr->GetSourceType();
CreateData.Source = ParamsPtr->GetSource();
auto Pickup = AFortPickup::SpawnPickup(CreateData);
return SpawnItemVariantPickupInWorldOriginal(Context, Stack, Ret); return SpawnItemVariantPickupInWorldOriginal(Context, Stack, Ret);
} }
@@ -165,7 +169,13 @@ bool UFortKismetLibrary::SpawnInstancedPickupInWorldHook(UObject* Context, FFram
Stack.StepCompiledIn(&bRandomRotation); Stack.StepCompiledIn(&bRandomRotation);
Stack.StepCompiledIn(&bBlockedFromAutoPickup); Stack.StepCompiledIn(&bBlockedFromAutoPickup);
auto Pickup = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::Unset, -1, nullptr, nullptr, bToss); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.SpawnLocation = Position;
CreateData.bToss = bToss;
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
auto Pickup = AFortPickup::SpawnPickup(CreateData);
*Ret = Pickup; *Ret = Pickup;
return *Ret; return *Ret;
@@ -192,8 +202,8 @@ void UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHo
UFortWeaponItemDefinition* WeaponItemDefinition; UFortWeaponItemDefinition* WeaponItemDefinition;
FGameplayTagContainer SourceTags; FGameplayTagContainer SourceTags;
FVector Location; FVector Location;
EFortPickupSourceTypeFlag SourceTypeFlag; uint8 SourceTypeFlag;
EFortPickupSpawnSource SpawnSource; uint8 SpawnSource;
Stack.StepCompiledIn(&WorldContextObject); Stack.StepCompiledIn(&WorldContextObject);
Stack.StepCompiledIn(&WeaponItemDefinition); Stack.StepCompiledIn(&WeaponItemDefinition);
@@ -213,7 +223,13 @@ void UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHo
if (!AmmoDefinition) if (!AmmoDefinition)
return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret); return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret);
auto AmmoPickup = AFortPickup::SpawnPickup(AmmoDefinition, Location, Count, SourceTypeFlag, SpawnSource); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(AmmoDefinition, Count, 0);
CreateData.SourceType = SourceTypeFlag;
CreateData.Source = SpawnSource;
CreateData.SpawnLocation = Location;
auto AmmoPickup = AFortPickup::SpawnPickup(CreateData);
return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret); return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret);
} }
@@ -460,8 +476,8 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con
bool bRandomRotation; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bRandomRotation; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bBlockedFromAutoPickup; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bBlockedFromAutoPickup; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
int PickupInstigatorHandle; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) int PickupInstigatorHandle; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
EFortPickupSourceTypeFlag SourceType; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) uint8 SourceType; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
EFortPickupSpawnSource Source; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) uint8 Source; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
AFortPlayerController* OptionalOwnerPC; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) AFortPlayerController* OptionalOwnerPC; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bPickupOnlyRelevantToOwner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bPickupOnlyRelevantToOwner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
@@ -488,11 +504,19 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con
LOG_INFO(LogDev, __FUNCTION__); LOG_INFO(LogDev, __FUNCTION__);
auto aa = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, SourceType, Source, -1, nullptr, PickupClass, bToss); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.Source = Source;
CreateData.SourceType = SourceType;
CreateData.OverrideClass = PickupClass;
CreateData.bToss = bToss;
CreateData.bRandomRotation = bRandomRotation;
auto NewPickup = AFortPickup::SpawnPickup(CreateData);
K2_SpawnPickupInWorldWithClassOriginal(Context, Stack, Ret); K2_SpawnPickupInWorldWithClassOriginal(Context, Stack, Ret);
*Ret = aa; *Ret = NewPickup;
return *Ret; return *Ret;
} }
@@ -508,8 +532,8 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr
bool bRandomRotation; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bRandomRotation; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bBlockedFromAutoPickup; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bBlockedFromAutoPickup; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
int PickupInstigatorHandle; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) int PickupInstigatorHandle; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
EFortPickupSourceTypeFlag SourceType; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) uint8 SourceType; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
EFortPickupSpawnSource Source; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) uint8 Source; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
AFortPlayerController* OptionalOwnerPC; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) AFortPlayerController* OptionalOwnerPC; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bPickupOnlyRelevantToOwner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bPickupOnlyRelevantToOwner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
@@ -535,11 +559,19 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr
auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr; auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr;
auto aa = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, SourceType, Source, -1, Pawn, AFortPickup::StaticClass(), bToss); PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.SpawnLocation = Position;
CreateData.bToss = bToss;
CreateData.bRandomRotation = bRandomRotation;
CreateData.PawnOwner = Pawn;
CreateData.bShouldFreeItemEntryWhenDeconstructed = true;
auto NewPickup = AFortPickup::SpawnPickup(CreateData);
K2_SpawnPickupInWorldOriginal(Context, Stack, Ret); K2_SpawnPickupInWorldOriginal(Context, Stack, Ret);
*Ret = aa; *Ret = NewPickup;
return *Ret; return *Ret;
} }

View File

@@ -35,16 +35,16 @@ struct FSpawnItemVariantParams
return *(int*)(__int64(this) + NumberToSpawnOffset); return *(int*)(__int64(this) + NumberToSpawnOffset);
} }
EFortPickupSourceTypeFlag& GetSourceType() uint8& GetSourceType()
{ {
static auto SourceTypeOffset = FindOffsetStruct("/Script/FortniteGame.SpawnItemVariantParams", "SourceType"); static auto SourceTypeOffset = FindOffsetStruct("/Script/FortniteGame.SpawnItemVariantParams", "SourceType");
return *(EFortPickupSourceTypeFlag*)(__int64(this) + SourceTypeOffset); return *(uint8*)(__int64(this) + SourceTypeOffset);
} }
EFortPickupSpawnSource& GetSource() uint8& GetSource()
{ {
static auto SourceOffset = FindOffsetStruct("/Script/FortniteGame.SpawnItemVariantParams", "Source"); static auto SourceOffset = FindOffsetStruct("/Script/FortniteGame.SpawnItemVariantParams", "Source");
return *(EFortPickupSpawnSource*)(__int64(this) + SourceOffset); return *(uint8*)(__int64(this) + SourceOffset);
} }
FVector& GetDirection() FVector& GetDirection()

View File

@@ -69,7 +69,7 @@ static T* PickWeightedElement(const std::map<FName, T*>& Elements, std::function
TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<FName, T*>& p) { TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<FName, T*>& p) {
auto Weight = GetWeightFn(p.second); auto Weight = GetWeightFn(p.second);
if (bPrint) if (bPrint && Weight != 0)
{ {
LOG_INFO(LogLoot, "Adding weight: {}", Weight); LOG_INFO(LogLoot, "Adding weight: {}", Weight);
} }
@@ -282,7 +282,7 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
return; return;
if (bPrint) if (bPrint)
LOG_INFO(LogLoot, "PickLootDropsFromLootPackage selected package {} with loot package category {} from LootPackageIDMap of size: {}", PickedPackageRowName.ToString(), LootPackageCategory, LootPackageIDMap.size()); LOG_INFO(LogLoot, "PickLootDropsFromLootPackage selected package {} with loot package category {} with weight {} from LootPackageIDMap of size: {}", PickedPackageRowName.ToString(), LootPackageCategory, PickedPackage->GetWeight(), LootPackageIDMap.size());
if (PickedPackage->GetLootPackageCall().Data.Num() > 1) if (PickedPackage->GetLootPackageCall().Data.Num() > 1)
{ {
@@ -358,12 +358,20 @@ void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, cons
{ {
auto AmmoData = WeaponItemDefinition->GetAmmoData(); auto AmmoData = WeaponItemDefinition->GetAmmoData();
int AmmoCount = AmmoData->GetDropCount(); // idk about this one if (AmmoData)
{
int AmmoCount = AmmoData->GetDropCount(); // idk about this one
OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(WeaponItemDefinition->GetAmmoData(), AmmoCount))); OutEntries->push_back(LootDrop(FFortItemEntry::MakeItemEntry(AmmoData, AmmoCount)));
}
} }
} }
if (bPrint)
{
LOG_INFO(LogLoot, "Adding Item: {}", ItemDefinition->GetPathName());
}
FinalCount -= CurrentCountForEntry; FinalCount -= CurrentCountForEntry;
} }
} }

View File

@@ -48,6 +48,16 @@ void AFortPawn::SetHealth(float NewHealth)
this->ProcessEvent(SetHealthFn, &NewHealth); this->ProcessEvent(SetHealthFn, &NewHealth);
} }
void AFortPawn::SetMaxHealth(float NewHealthVal)
{
static auto SetMaxHealthFn = FindObject<UFunction>("/Script/FortniteGame.FortPawn.SetMaxHealth");
if (!SetMaxHealthFn)
return;
this->ProcessEvent(SetMaxHealthFn, &NewHealthVal);
}
void AFortPawn::SetShield(float NewShield) void AFortPawn::SetShield(float NewShield)
{ {
static auto SetShieldFn = FindObject<UFunction>("/Script/FortniteGame.FortPawn.SetShield"); static auto SetShieldFn = FindObject<UFunction>("/Script/FortniteGame.FortPawn.SetShield");

View File

@@ -28,6 +28,7 @@ public:
} }
void SetHealth(float NewHealth); void SetHealth(float NewHealth);
void SetMaxHealth(float NewHealthVal);
void SetShield(float NewShield); void SetShield(float NewShield);
static void NetMulticast_Athena_BatchedDamageCuesHook(UObject* Context, FFrame* Stack, void* Ret); static void NetMulticast_Athena_BatchedDamageCuesHook(UObject* Context, FFrame* Stack, void* Ret);
static void MovingEmoteStoppedHook(UObject* Context, FFrame* Stack, void* Ret); static void MovingEmoteStoppedHook(UObject* Context, FFrame* Stack, void* Ret);

View File

@@ -10,12 +10,12 @@
#include "GameplayStatics.h" #include "GameplayStatics.h"
#include "gui.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, uint8 InPickupSourceTypeFlags, uint8 InPickupSpawnSource)
{ {
static auto fn = FindObject<UFunction>(L"/Script/FortniteGame.FortPickup.TossPickup"); static auto fn = FindObject<UFunction>(L"/Script/FortniteGame.FortPickup.TossPickup");
struct { FVector FinalLocation; AFortPawn* ItemOwner; int OverrideMaxStackCount; bool bToss; struct { FVector FinalLocation; AFortPawn* ItemOwner; int OverrideMaxStackCount; bool bToss;
EFortPickupSourceTypeFlag InPickupSourceTypeFlags; EFortPickupSpawnSource InPickupSpawnSource; } uint8 InPickupSourceTypeFlags; uint8 InPickupSpawnSource; }
AFortPickup_TossPickup_Params{FinalLocation, ItemOwner, OverrideMaxStackCount, bToss, InPickupSourceTypeFlags, InPickupSpawnSource}; AFortPickup_TossPickup_Params{FinalLocation, ItemOwner, OverrideMaxStackCount, bToss, InPickupSourceTypeFlags, InPickupSpawnSource};
this->ProcessEvent(fn, &AFortPickup_TossPickup_Params); this->ProcessEvent(fn, &AFortPickup_TossPickup_Params);
@@ -29,145 +29,151 @@ void AFortPickup::SpawnMovementComponent()
this->Get(MovementComponentOffset) = UGameplayStatics::SpawnObject(ProjectileMovementComponentClass, this); this->Get(MovementComponentOffset) = UGameplayStatics::SpawnObject(ProjectileMovementComponentClass, this);
} }
AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Location, AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
EFortPickupSourceTypeFlag PickupSource, EFortPickupSpawnSource SpawnSource,
class AFortPawn* Pawn, UClass* OverrideClass, bool bToss, int OverrideCount, AFortPickup* IgnoreCombinePickup)
{ {
if (bToss) if (PickupData.Source == -1)
{ PickupData.Source = 0;
PickupSource |= EFortPickupSourceTypeFlag::Tossed; if (PickupData.SourceType == -1)
} PickupData.SourceType = -1;
/* if (PickupData.bToss)
{
PickupData.SourceType |= EFortPickupSourceTypeFlag::Tossed;
} */
// static auto FortPickupClass = FindObject<UClass>(L"/Script/FortniteGame.FortPickup");
static auto FortPickupAthenaClass = FindObject<UClass>(L"/Script/FortniteGame.FortPickupAthena"); static auto FortPickupAthenaClass = FindObject<UClass>(L"/Script/FortniteGame.FortPickupAthena");
auto PlayerState = Pawn ? Cast<AFortPlayerState>(Pawn->GetPlayerState()) : nullptr; auto PlayerState = PickupData.PawnOwner ? Cast<AFortPlayerState>(PickupData.PawnOwner->GetPlayerState()) : nullptr;
FActorSpawnParameters SpawnParameters{}; FActorSpawnParameters SpawnParameters{};
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; // SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
if (auto Pickup = GetWorld()->SpawnActor<AFortPickup>(OverrideClass ? OverrideClass : FortPickupAthenaClass, Location, FQuat(), FVector(1, 1, 1), SpawnParameters)) auto Pickup = GetWorld()->SpawnActor<AFortPickup>(PickupData.OverrideClass ? PickupData.OverrideClass : FortPickupAthenaClass, PickupData.SpawnLocation, FQuat(), FVector(1, 1, 1), SpawnParameters);
if (!Pickup)
return nullptr;
static auto bRandomRotationOffset = Pickup->GetOffset("bRandomRotation", false);
if (bRandomRotationOffset != -1)
Pickup->Get<bool>(bRandomRotationOffset) = PickupData.bRandomRotation;
static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup");
Pickup->Get<AFortPawn*>(PawnWhoDroppedPickupOffset) = PickupData.PawnOwner;
auto PrimaryPickupItemEntry = Pickup->GetPrimaryPickupItemEntry();
if (Addresses::PickupInitialize)
{ {
static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup"); static void (*SetupPickup)(AFortPickup * Pickup, __int64 ItemEntry, TArray<FFortItemEntry> MultiItemPickupEntriesIGuess, bool bSplitOnPickup)
Pickup->Get<AFortPawn*>(PawnWhoDroppedPickupOffset) = Pawn; = decltype(SetupPickup)(Addresses::PickupInitialize);
auto PrimaryPickupItemEntry = Pickup->GetPrimaryPickupItemEntry(); TArray<FFortItemEntry> MultiItemPickupEntriesIGuess{};
SetupPickup(Pickup, __int64(PickupData.ItemEntry), MultiItemPickupEntriesIGuess, false);
FFortItemEntry::FreeArrayOfEntries(MultiItemPickupEntriesIGuess);
}
else
{
PrimaryPickupItemEntry->CopyFromAnotherItemEntry(PickupData.ItemEntry);
}
if (Addresses::PickupInitialize) static auto PickupSourceTypeFlagsOffset = Pickup->GetOffset("PickupSourceTypeFlags", false);
if (PickupSourceTypeFlagsOffset != -1)
{
// Pickup->Get<int32>(PickupSourceTypeFlagsOffset) |= (int)PickupData.SourceType; // Assuming its the same enum on older versions. // (it is not the same)
}
if (Pickup->Get<AFortPawn*>(PawnWhoDroppedPickupOffset))
{
// TODO Add EFortItemEntryState::DroppedFromPickup or whatever if it isn't found already.
}
PrimaryPickupItemEntry->GetCount() = PickupData.OverrideCount == -1 ? PickupData.ItemEntry->GetCount() : PickupData.OverrideCount;
auto PickupLocationData = Pickup->GetPickupLocationData();
auto CanCombineWithPickup = [&](AActor* OtherPickupActor) -> bool
{
auto OtherPickup = (AFortPickup*)OtherPickupActor;
if (OtherPickup == PickupData.IgnoreCombineTarget || Pickup->GetPickupLocationData()->GetCombineTarget())
return false;
if (OtherPickup->GetPickupLocationData()->GetTossState() != EFortPickupTossState::AtRest)
return false;
if (PrimaryPickupItemEntry->GetItemDefinition() == OtherPickup->GetPrimaryPickupItemEntry()->GetItemDefinition())
{ {
static void (*SetupPickup)(AFortPickup* Pickup, __int64 ItemEntry, TArray<FFortItemEntry> MultiItemPickupEntriesIGuess, bool bSplitOnPickup) if (OtherPickup->GetPrimaryPickupItemEntry()->GetCount() >= PrimaryPickupItemEntry->GetItemDefinition()->GetMaxStackSize()) // Other pickup is already at the max size.
= decltype(SetupPickup)(Addresses::PickupInitialize);
TArray<FFortItemEntry> MultiItemPickupEntriesIGuess{};
SetupPickup(Pickup, __int64(ItemEntry), MultiItemPickupEntriesIGuess, false);
FFortItemEntry::FreeArrayOfEntries(MultiItemPickupEntriesIGuess);
}
else
{
PrimaryPickupItemEntry->CopyFromAnotherItemEntry(ItemEntry);
}
static auto PickupSourceTypeFlagsOffset = Pickup->GetOffset("PickupSourceTypeFlags", false);
if (PickupSourceTypeFlagsOffset != -1)
Pickup->Get<int32>(PickupSourceTypeFlagsOffset) |= (int)PickupSource; // Assuming its the same enum on older versions.
PrimaryPickupItemEntry->GetCount() = OverrideCount == -1 ? ItemEntry->GetCount() : OverrideCount;
// PrimaryPickupItemEntry->GetItemGuid() = OldGuid;
// Pickup->OnRep_PrimaryPickupItemEntry();
// static auto OptionalOwnerIDOffset = Pickup->GetOffset("OptionalOwnerID");
// Pickup->Get<int>(OptionalOwnerIDOffset) = PlayerState ? PlayerState->GetWorldPlayerId() : -1;
auto PickupLocationData = Pickup->GetPickupLocationData();
auto CanCombineWithPickup = [&](AActor* OtherPickupActor) -> bool
{
auto OtherPickup = (AFortPickup*)OtherPickupActor;
if (OtherPickup == IgnoreCombinePickup || OtherPickup->GetPickupLocationData()->GetCombineTarget())
return false; return false;
if (PrimaryPickupItemEntry->GetItemDefinition() == OtherPickup->GetPrimaryPickupItemEntry()->GetItemDefinition()) return true;
{
// auto IncomingCount = OtherPickup->GetPrimaryPickupItemEntry()->GetCount();
// 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 true;
}
return false;
};
if (Addresses::CombinePickupLea)
{
PickupLocationData->GetCombineTarget() = (AFortPickup*)Pickup->GetClosestActor(AFortPickup::StaticClass(), 4, CanCombineWithPickup);
} }
if (!PickupLocationData->GetCombineTarget()) // I don't think we should call TossPickup for every pickup anyways. return false;
{ };
Pickup->TossPickup(Location, Pawn, 0, bToss, PickupSource, SpawnSource);
}
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; if (Addresses::CombinePickupLea && bEnableCombinePickup)
{
// LOG_INFO(LogDev, "Distance: {}", Dist); PickupLocationData->GetCombineTarget() = (AFortPickup*)Pickup->GetClosestActor(AFortPickup::StaticClass(), 4, CanCombineWithPickup);
// 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->ForceNetUpdate();
}
if (PickupSource == EFortPickupSourceTypeFlag::Container) // crashes if we do this then tosspickup
{
static auto bTossedFromContainerOffset = Pickup->GetOffset("bTossedFromContainer");
Pickup->Get<bool>(bTossedFromContainerOffset) = true;
// Pickup->OnRep_TossedFromContainer();
}
if (Fortnite_Version < 6)
{
Pickup->SpawnMovementComponent();
}
return Pickup;
} }
return nullptr; if (!PickupLocationData->GetCombineTarget()) // I don't think we should call TossPickup for every pickup anyways.
{
Pickup->TossPickup(PickupData.SpawnLocation, PickupData.PawnOwner, 0, PickupData.bToss, PickupData.SourceType, PickupData.Source);
}
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() = PickupData.SpawnLocation;
PickupLocationData->GetLootInitialPosition() = Pickup->GetActorLocation();
PickupLocationData->GetFlyTime() = 1.f / Dist; // Higher the dist quicker it should be. // not right
PickupLocationData->GetItemOwner() = PickupData.PawnOwner;
PickupLocationData->GetFinalTossRestLocation() = PickupLocationData->GetCombineTarget()->GetActorLocation();
Pickup->OnRep_PickupLocationData();
Pickup->ForceNetUpdate();
}
if (EFortPickupSourceTypeFlag::GetEnum() && PickupData.SourceType == EFortPickupSourceTypeFlag::GetContainerValue()) // crashes if we do this then tosspickup
{
static auto bTossedFromContainerOffset = Pickup->GetOffset("bTossedFromContainer");
Pickup->Get<bool>(bTossedFromContainerOffset) = true;
// Pickup->OnRep_TossedFromContainer();
}
if (Fortnite_Version < 6)
{
Pickup->SpawnMovementComponent();
}
return Pickup;
} }
AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Location, int Count, EFortPickupSourceTypeFlag PickupSource, EFortPickupSpawnSource SpawnSource, AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Location,
int LoadedAmmo, AFortPawn* Pawn, UClass* OverrideClass, bool bToss, AFortPickup* IgnoreCombinePickup) uint8 PickupSource, uint8 SpawnSource,
class AFortPawn* Pawn, UClass* OverrideClass, bool bToss, int OverrideCount, AFortPickup* IgnoreCombinePickup)
{ {
if (LoadedAmmo == -1) PickupCreateData CreateData;
{ CreateData.ItemEntry = ItemEntry;
if (auto WeaponDef = Cast<UFortWeaponItemDefinition>(ItemDef)) // bPreventDefaultPreload ? CreateData.SpawnLocation = Location;
LoadedAmmo = WeaponDef->GetClipSize(); CreateData.Source = SpawnSource;
else CreateData.SourceType = PickupSource;
LoadedAmmo = 0; CreateData.PawnOwner = Pawn;
} CreateData.OverrideClass = OverrideClass;
CreateData.bToss = bToss;
CreateData.IgnoreCombineTarget = IgnoreCombinePickup;
CreateData.OverrideCount = OverrideCount;
auto ItemEntry = FFortItemEntry::MakeItemEntry(ItemDef, Count, LoadedAmmo); return AFortPickup::SpawnPickup(CreateData);
auto Pickup = SpawnPickup(ItemEntry, Location, PickupSource, SpawnSource, Pawn, OverrideClass, bToss, -1, IgnoreCombinePickup);
// VirtualFree(ItemEntry);
return Pickup;
} }
void AFortPickup::CombinePickupHook(AFortPickup* Pickup) void AFortPickup::CombinePickupHook(AFortPickup* Pickup)
@@ -195,8 +201,14 @@ void AFortPickup::CombinePickupHook(AFortPickup* Pickup)
auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner(); auto ItemOwner = Pickup->GetPickupLocationData()->GetItemOwner();
auto NewOverStackPickup = AFortPickup::SpawnPickup(ItemDefinition, PickupToCombineInto->GetActorLocation(), OverStackCount, PickupCreateData CreateData;
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, ItemOwner, nullptr, false, PickupToCombineInto); CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, OverStackCount, 0);
CreateData.SpawnLocation = PickupToCombineInto->GetActorLocation();
CreateData.PawnOwner = ItemOwner;
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
CreateData.IgnoreCombineTarget = PickupToCombineInto;
auto NewOverStackPickup = AFortPickup::SpawnPickup(CreateData);
} }
PickupToCombineInto->GetPrimaryPickupItemEntry()->GetCount() += CountToAdd; PickupToCombineInto->GetPrimaryPickupItemEntry()->GetCount() += CountToAdd;
@@ -300,7 +312,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped && ItemDefGoingInPrimary) // swap if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped && ItemDefGoingInPrimary) // swap
{ {
auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc, auto SwappedPickup = SpawnPickup(ItemEntryToSwap, PawnLoc,
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, Pawn); EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn);
auto CurrentWeapon = Pawn->GetCurrentWeapon(); auto CurrentWeapon = Pawn->GetCurrentWeapon();
@@ -373,7 +385,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
int LoadedAmmo = 0; int LoadedAmmo = 0;
// SpawnPickup(ItemDefinitionToSpawn, PawnLoc, AmountToSpawn, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, Pawn); // SpawnPickup(ItemDefinitionToSpawn, PawnLoc, AmountToSpawn, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, Pawn);
SpawnPickup(PickupEntry, PawnLoc, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, Pawn, nullptr, true, AmountToSpawn); SpawnPickup(PickupEntry, PawnLoc, EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn, nullptr, true, AmountToSpawn);
cpyCount -= AmountToSpawn; cpyCount -= AmountToSpawn;
bForceOverflow = false; bForceOverflow = false;
} }

View File

@@ -2,33 +2,99 @@
#include "Actor.h" #include "Actor.h"
#include "FortPawn.h" #include "FortPawn.h"
#include "Class.h"
enum class EFortPickupSourceTypeFlag : uint8_t namespace EFortPickupSourceTypeFlag
{ {
Other = 0, static inline UEnum* GetEnum()
Player = 1, {
Destruction = 2, static auto Enum = FindObject<UEnum>("/Script/FortniteGame.EFortPickupSourceTypeFlag");
Container = 3, return Enum;
AI = 4, }
Tossed = 5,
FloorLoot = 6, static inline int64 GetPlayerValue()
EFortPickupSourceTypeFlag_MAX = 7 {
static auto PlayerValue = GetEnum() ? GetEnum()->GetValue("Player") : -1;
return PlayerValue;
}
static inline int64 GetContainerValue()
{
static auto ContainerValue = GetEnum() ? GetEnum()->GetValue("Container") : -1;
return ContainerValue;
}
static inline int64 GetFloorLootValue()
{
static auto FloorLootValue = GetEnum() ? GetEnum()->GetValue("FloorLoot") : -1;
return FloorLootValue;
}
static inline int64 GetOtherValue()
{
static auto OtherValue = GetEnum() ? GetEnum()->GetValue("Other") : -1;
return OtherValue;
}
static inline int64 GetTossedValue()
{
static auto TossedValue = GetEnum() ? GetEnum()->GetValue("Tossed") : -1;
return TossedValue;
}
}
namespace EFortPickupSpawnSource
{
static inline UEnum* GetEnum()
{
static auto Enum = FindObject<UEnum>("/Script/FortniteGame.EFortPickupSpawnSource");
return Enum;
}
static inline int64 GetPlayerEliminationValue()
{
static auto PlayerEliminationValue = GetEnum() ? GetEnum()->GetValue("PlayerElimination") : -1;
return PlayerEliminationValue;
}
static inline int64 GetSupplyDropValue()
{
static auto SupplyDropValue = GetEnum() ? GetEnum()->GetValue("SupplyDrop") : -1;
return SupplyDropValue;
}
}
struct PickupCreateData
{
FFortItemEntry* ItemEntry = nullptr;
AFortPawn* PawnOwner = nullptr;
int OverrideCount = -1;
UClass* OverrideClass = nullptr;
bool bToss = false;
class AFortPickup* IgnoreCombineTarget = nullptr;
bool bRandomRotation = false;
uint8 SourceType = 0;
uint8 Source = 0;
FVector SpawnLocation = FVector(0, 0, 0);
bool bShouldFreeItemEntryWhenDeconstructed = false;
~PickupCreateData()
{
if (bShouldFreeItemEntryWhenDeconstructed)
{
}
}
}; };
enum class EFortPickupSpawnSource : uint8_t enum class EFortPickupTossState : uint8
{ {
Unset = 0, NotTossed = 0,
PlayerElimination = 1, InProgress = 1,
Chest = 2, AtRest = 2,
SupplyDrop = 3, EFortPickupTossState_MAX = 3,
AmmoBox = 4,
Drone = 5,
ItemSpawner = 6,
EFortPickupSpawnSource_MAX = 7
}; };
ENUM_CLASS_FLAGS(EFortPickupSourceTypeFlag)
struct FFortPickupLocationData struct FFortPickupLocationData
{ {
AFortPawn*& GetPickupTarget() AFortPawn*& GetPickupTarget()
@@ -43,6 +109,12 @@ struct FFortPickupLocationData
return *(float*)(__int64(this) + FlyTimeOffset); return *(float*)(__int64(this) + FlyTimeOffset);
} }
EFortPickupTossState& GetTossState()
{
static auto TossStateOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "TossState");
return *(EFortPickupTossState*)(__int64(this) + TossStateOffset);
}
AFortPawn*& GetItemOwner() AFortPawn*& GetItemOwner()
{ {
static auto ItemOwnerOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "ItemOwner"); static auto ItemOwnerOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "ItemOwner");
@@ -91,7 +163,7 @@ class AFortPickup : public AActor
public: public:
static inline char (*CompletePickupAnimationOriginal)(AFortPickup* Pickup); static inline char (*CompletePickupAnimationOriginal)(AFortPickup* Pickup);
void TossPickup(FVector FinalLocation, class AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource); void TossPickup(FVector FinalLocation, class AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, uint8 InPickupSourceTypeFlags, uint8 InPickupSpawnSource);
void SpawnMovementComponent(); // BAD You probably don't wanna use unless absolutely necessary void SpawnMovementComponent(); // BAD You probably don't wanna use unless absolutely necessary
void OnRep_PrimaryPickupItemEntry() void OnRep_PrimaryPickupItemEntry()
@@ -118,13 +190,11 @@ public:
this->ProcessEvent(OnRep_PickupLocationDataFn); this->ProcessEvent(OnRep_PickupLocationDataFn);
} }
static AFortPickup* SpawnPickup(FFortItemEntry* ItemEntry, FVector Location, static AFortPickup* SpawnPickup(PickupCreateData& PickupData);
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
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(FFortItemEntry* ItemEntry, FVector Location,
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset, uint8 PickupSource = 0, uint8 SpawnSource = 0,
int LoadedAmmo = -1, class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true, AFortPickup* IgnoreCombinePickup = nullptr); class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true, int OverrideCount = -1, AFortPickup* IgnoreCombinePickup = nullptr);
static void CombinePickupHook(AFortPickup* Pickup); static void CombinePickupHook(AFortPickup* Pickup);
static char CompletePickupAnimationHook(AFortPickup* Pickup); static char CompletePickupAnimationHook(AFortPickup* Pickup);

View File

@@ -111,8 +111,12 @@ void AFortPlayerController::DropAllItems(const std::vector<UFortItemDefinition*>
if (bRemoveIfNotDroppable && !WorldItemDefinition->CanBeDropped()) if (bRemoveIfNotDroppable && !WorldItemDefinition->CanBeDropped())
continue; continue;
AFortPickup::SpawnPickup(WorldItemDefinition, Location, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, PickupCreateData CreateData;
ItemEntry->GetLoadedAmmo()); CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WorldItemDefinition, ItemEntry->GetCount(), ItemEntry->GetLoadedAmmo());
CreateData.SpawnLocation = Location;
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
AFortPickup::SpawnPickup(CreateData);
} }
for (auto& Pair : GuidAndCountsToRemove) for (auto& Pair : GuidAndCountsToRemove)
@@ -587,8 +591,12 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
{ {
auto Entry = ItemCollection->GetOutputItemEntry()->AtPtr(z, FFortItemEntry::GetStructSize()); auto Entry = ItemCollection->GetOutputItemEntry()->AtPtr(z, FFortItemEntry::GetStructSize());
AFortPickup::SpawnPickup(Entry->GetItemDefinition(), LocationToSpawnLoot, Entry->GetCount(), PickupCreateData CreateData;
EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::Unset, Entry->GetLoadedAmmo(), PlayerController->GetMyFortPawn()); CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(Entry->GetItemDefinition(), Entry->GetCount(), Entry->GetLoadedAmmo());
CreateData.SpawnLocation = LocationToSpawnLoot;
CreateData.PawnOwner = PlayerController->GetMyFortPawn(); // hmm
AFortPickup::SpawnPickup(CreateData);
} }
static auto bCurrentInteractionSuccessOffset = ItemCollector->GetOffset("bCurrentInteractionSuccess", false); static auto bCurrentInteractionSuccessOffset = ItemCollector->GetOffset("bCurrentInteractionSuccess", false);
@@ -840,6 +848,8 @@ void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFra
bool bBuildFree = PlayerController->DoesBuildFree(); bool bBuildFree = PlayerController->DoesBuildFree();
LOG_INFO(LogDev, "MatInstance->GetItemEntry()->GetCount(): {}", MatInstance->GetItemEntry()->GetCount());
bool bShouldDestroy = MatInstance && MatInstance->GetItemEntry() ? MatInstance->GetItemEntry()->GetCount() < 10 : true; bool bShouldDestroy = MatInstance && MatInstance->GetItemEntry() ? MatInstance->GetItemEntry()->GetCount() < 10 : true;
if (bShouldDestroy && !bBuildFree) if (bShouldDestroy && !bBuildFree)
@@ -950,6 +960,7 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController
return; return;
} }
// TODO If the player is in a vehicle and has a vehicle weapon, don't let them drop.
auto WorldInventory = PlayerController->GetWorldInventory(); auto WorldInventory = PlayerController->GetWorldInventory();
auto ReplicatedEntry = WorldInventory->FindReplicatedEntry(ItemGuid); auto ReplicatedEntry = WorldInventory->FindReplicatedEntry(ItemGuid);
@@ -966,8 +977,25 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController
if (!ItemDefinition->ShouldIgnoreRespawningOnDrop() && (DropBehaviorOffset != -1 ? ItemDefinition->GetDropBehavior() != EWorldItemDropBehavior::DestroyOnDrop : true)) if (!ItemDefinition->ShouldIgnoreRespawningOnDrop() && (DropBehaviorOffset != -1 ? ItemDefinition->GetDropBehavior() != EWorldItemDropBehavior::DestroyOnDrop : true))
{ {
/* if (auto GadgetItemDefintiion = Cast<UFortGadgetItemDefinition>(ItemDefinition))
{
for (int i = 0; i < GadgetItemDefintiion->GetTrackedAttributes().Num(); i++)
{
LOG_INFO(LogDev, "[{}] TrackedAttribute Attribute Name {}", i, GadgetItemDefintiion->GetTrackedAttributes().at(i).GetAttributePropertyName());
PadHexA8 StateValue{}; // Alloc<FFortItemEntryStateValue>(FFortItemEntryStateValue::GetStructSize(), true);
((FFortItemEntryStateValue*)&StateValue)->GetIntValue() = 1;
((FFortItemEntryStateValue*)&StateValue)->GetStateType() = EFortItemEntryState::GenericAttributeValueSet;
((FFortItemEntryStateValue*)&StateValue)->GetNameValue() = FName(0);
ReplicatedEntry->GetStateValues().AddPtr((FFortItemEntryStateValue*)&StateValue, FFortItemEntryStateValue::GetStructSize());
ReplicatedEntry->GetGenericAttributeValues().Add(9);
}
} */
auto Pickup = AFortPickup::SpawnPickup(ReplicatedEntry, Pawn->GetActorLocation(), auto Pickup = AFortPickup::SpawnPickup(ReplicatedEntry, Pawn->GetActorLocation(),
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, Pawn, nullptr, true, Count); EFortPickupSourceTypeFlag::GetPlayerValue(), 0, Pawn, nullptr, true, Count);
if (!Pickup) if (!Pickup)
return; return;
@@ -1338,8 +1366,13 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
if (!ShouldBeDropped) if (!ShouldBeDropped)
continue; continue;
AFortPickup::SpawnPickup(WorldItemDefinition, DeathLocation, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::PlayerElimination, PickupCreateData CreateData;
ItemEntry->GetLoadedAmmo()); CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WorldItemDefinition, ItemEntry->GetCount(), ItemEntry->GetLoadedAmmo());
CreateData.SourceType = EFortPickupSourceTypeFlag::GetPlayerValue();
CreateData.Source = EFortPickupSpawnSource::GetPlayerEliminationValue();
CreateData.SpawnLocation = DeathLocation;
AFortPickup::SpawnPickup(CreateData);
GuidAndCountsToRemove.push_back({ ItemEntry->GetItemGuid(), ItemEntry->GetCount() }); GuidAndCountsToRemove.push_back({ ItemEntry->GetItemGuid(), ItemEntry->GetCount() });
// WorldInventory->RemoveItem(ItemEntry->GetItemGuid(), nullptr, ItemEntry->GetCount()); // WorldInventory->RemoveItem(ItemEntry->GetItemGuid(), nullptr, ItemEntry->GetCount());
@@ -1433,29 +1466,39 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
{ {
// wtf // wtf
auto AllPlayerStates = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFortPlayerStateAthena::StaticClass()); if (GameState->GetGamePhase() > EAthenaGamePhase::Warmup)
bool bDidSomeoneWin = AllPlayerStates.Num() == 0;
for (int i = 0; i < AllPlayerStates.Num(); i++)
{ {
if (((AFortPlayerStateAthena*)AllPlayerStates.at(i))->GetPlace() <= 1) auto AllPlayerStates = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFortPlayerStateAthena::StaticClass());
bool bDidSomeoneWin = AllPlayerStates.Num() == 0;
for (int i = 0; i < AllPlayerStates.Num(); i++)
{ {
bDidSomeoneWin = true; auto CurrentPlayerState = (AFortPlayerStateAthena*)AllPlayerStates.at(i);
break;
if (CurrentPlayerState->GetPlace() <= 1)
{
bDidSomeoneWin = true;
break;
}
}
LOG_INFO(LogDev, "bDidSomeoneWin: {}", bDidSomeoneWin);
// if (GameState->GetGamePhase() == EAthenaGamePhase::EndGame)
if (bDidSomeoneWin)
{
CreateThread(0, 0, RestartThread, 0, 0, 0);
} }
} }
LOG_INFO(LogDev, "bDidSomeoneWin: {}", bDidSomeoneWin);
// if (GameState->GetGamePhase() == EAthenaGamePhase::EndGame)
if (bDidSomeoneWin)
{
CreateThread(0, 0, RestartThread, 0, 0, 0);
}
} }
} }
if (DeadPlayerState->IsBot())
{
// AllPlayerBotsToTick.
}
return ClientOnPawnDiedOriginal(PlayerController, DeathReport); return ClientOnPawnDiedOriginal(PlayerController, DeathReport);
} }

View File

@@ -108,6 +108,20 @@ public:
return NewAndModifiedInstances.first.size() > 0 ? NewAndModifiedInstances.first[0] : nullptr; return NewAndModifiedInstances.first.size() > 0 ? NewAndModifiedInstances.first[0] : nullptr;
} }
TSet<FGuid>& GetGadgetTrackedAttributeItemInstanceIds() // actually in zone
{
static auto GadgetTrackedAttributeItemInstanceIdsOffset = GetOffset("GadgetTrackedAttributeItemInstanceIds");
return Get<TSet<FGuid>>(GadgetTrackedAttributeItemInstanceIdsOffset);
}
bool IsPlayingEmote()
{
static auto IsPlayingEmoteFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerController.IsPlayingEmote");
bool Ret;
this->ProcessEvent(IsPlayingEmoteFn, &Ret);
return Ret;
}
bool& ShouldTryPickupSwap() bool& ShouldTryPickupSwap()
{ {
static auto bTryPickupSwapOffset = GetOffset("bTryPickupSwap"); static auto bTryPickupSwapOffset = GetOffset("bTryPickupSwap");

View File

@@ -105,6 +105,9 @@ void AFortPlayerControllerAthena::EndGhostModeHook(AFortPlayerControllerAthena*
auto PickaxeInstance = PlayerController->AddPickaxeToInventory(); auto PickaxeInstance = PlayerController->AddPickaxeToInventory();
WorldInventory->Update(); WorldInventory->Update();
WorldInventory->ForceNetUpdate();
PlayerController->ForceNetUpdate();
if (PickaxeInstance) if (PickaxeInstance)
{ {
PlayerController->ClientEquipItem(PickaxeInstance->GetItemEntry()->GetItemGuid(), true); PlayerController->ClientEquipItem(PickaxeInstance->GetItemEntry()->GetItemGuid(), true);

View File

@@ -6,7 +6,10 @@
FFortAthenaLoadout* AFortPlayerPawn::GetCosmeticLoadout() FFortAthenaLoadout* AFortPlayerPawn::GetCosmeticLoadout()
{ {
static auto CosmeticLoadoutOffset = GetOffset("CosmeticLoadout"); static auto CosmeticLoadoutOffset = GetOffset("CosmeticLoadout", false);
if (CosmeticLoadoutOffset == -1)
CosmeticLoadoutOffset = GetOffset("CustomizationLoadout");
if (CosmeticLoadoutOffset == -1) if (CosmeticLoadoutOffset == -1)
return nullptr; return nullptr;

View File

@@ -26,6 +26,20 @@ public:
return Get<int>(PlaceOffset); return Get<int>(PlaceOffset);
} }
bool IsInAircraft()
{
static auto bInAircraftOffset = GetOffset("bInAircraft");
static auto bInAircraftFieldMask = GetFieldMask(GetProperty("bInAircraft"));
return ReadBitfieldValue(bInAircraftOffset, bInAircraftFieldMask);
}
bool HasThankedBusDriver()
{
static auto bThankedBusDriverOffset = GetOffset("bThankedBusDriver");
static auto bThankedBusDriverFieldMask = GetFieldMask(GetProperty("bThankedBusDriver"));
return ReadBitfieldValue(bThankedBusDriverOffset, bThankedBusDriverFieldMask);
}
void ClientReportKill(AFortPlayerStateAthena* Player) void ClientReportKill(AFortPlayerStateAthena* Player)
{ {
static auto ClientReportKillFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerStateAthena.ClientReportKill"); static auto ClientReportKillFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerStateAthena.ClientReportKill");

View File

@@ -23,9 +23,39 @@ UClass* AGameModeBase::GetDefaultPawnClassForController(AController* InControlle
return AGameModeBase_GetDefaultPawnClassForController_Params.ReturnValue; return AGameModeBase_GetDefaultPawnClassForController_Params.ReturnValue;
} }
void AGameModeBase::ChangeName(AController* Controller, const FString& NewName, bool bNameChange)
{
static auto ChangeNameFn = FindObject<UFunction>("/Script/Engine.GameModeBase.ChangeName");
struct
{
AController* Controller; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
struct FString NewName; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bNameChange; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
} AGameModeBase_ChangeName_Params{ Controller, NewName, bNameChange };
this->ProcessEvent(ChangeNameFn, &AGameModeBase_ChangeName_Params);
}
AActor* AGameModeBase::K2_FindPlayerStart(AController* Player, FString IncomingName)
{
static auto K2_FindPlayerStartFn = FindObject<UFunction>("/Script/Engine.GameModeBase.K2_FindPlayerStart");
struct
{
AController* Player; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FString IncomingName; // (Parm, ZeroConstructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
AActor* ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
} AGameModeBase_K2_FindPlayerStart_Params{ Player, IncomingName };
this->ProcessEvent(K2_FindPlayerStartFn, &AGameModeBase_K2_FindPlayerStart_Params);
return AGameModeBase_K2_FindPlayerStart_Params.ReturnValue;
}
APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AController* NewPlayer, AActor* StartSpot) APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AController* NewPlayer, AActor* StartSpot)
{ {
LOG_INFO(LogDev, "SpawnDefaultPawnFor: 0x{:x}!", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0))); // LOG_INFO(LogDev, "SpawnDefaultPawnFor: 0x{:x}!", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0)));
// auto PawnClass = GameMode->GetDefaultPawnClassForController(NewPlayer); // auto PawnClass = GameMode->GetDefaultPawnClassForController(NewPlayer);
// LOG_INFO(LogDev, "PawnClass: {}", PawnClass->GetFullName()); // LOG_INFO(LogDev, "PawnClass: {}", PawnClass->GetFullName());

View File

@@ -4,11 +4,14 @@
#include "Controller.h" #include "Controller.h"
#include "Pawn.h" #include "Pawn.h"
#include "UnrealString.h"
class AGameModeBase : public AActor // AInfo class AGameModeBase : public AActor // AInfo
{ {
public: public:
UClass* GetDefaultPawnClassForController(AController* InController); UClass* GetDefaultPawnClassForController(AController* InController);
void ChangeName(AController* Controller, const FString& NewName, bool bNameChange);
AActor* K2_FindPlayerStart(AController* Player, FString IncomingName);
static APawn* SpawnDefaultPawnForHook(AGameModeBase* GameMode, AController* NewPlayer, AActor* StartSpot); static APawn* SpawnDefaultPawnForHook(AGameModeBase* GameMode, AController* NewPlayer, AActor* StartSpot);
}; };

View File

@@ -5,6 +5,73 @@
#include "reboot.h" #include "reboot.h"
enum class EDrawDebugTrace : uint8_t
{
None = 0,
ForOneFrame = 1,
ForDuration = 2,
Persistent = 3,
EDrawDebugTrace_MAX = 4
};
enum class ETraceTypeQuery : uint8_t
{
TraceTypeQuery1 = 0,
TraceTypeQuery2 = 1,
TraceTypeQuery3 = 2,
TraceTypeQuery4 = 3,
TraceTypeQuery5 = 4,
TraceTypeQuery6 = 5,
TraceTypeQuery7 = 6,
TraceTypeQuery8 = 7,
TraceTypeQuery9 = 8,
TraceTypeQuery10 = 9,
TraceTypeQuery11 = 10,
TraceTypeQuery12 = 11,
TraceTypeQuery13 = 12,
TraceTypeQuery14 = 13,
TraceTypeQuery15 = 14,
TraceTypeQuery16 = 15,
TraceTypeQuery17 = 16,
TraceTypeQuery18 = 17,
TraceTypeQuery19 = 18,
TraceTypeQuery20 = 19,
TraceTypeQuery21 = 20,
TraceTypeQuery22 = 21,
TraceTypeQuery23 = 22,
TraceTypeQuery24 = 23,
TraceTypeQuery25 = 24,
TraceTypeQuery26 = 25,
TraceTypeQuery27 = 26,
TraceTypeQuery28 = 27,
TraceTypeQuery29 = 28,
TraceTypeQuery30 = 29,
TraceTypeQuery31 = 30,
TraceTypeQuery32 = 31,
TraceTypeQuery_MAX = 32,
ETraceTypeQuery_MAX = 33
};
struct FLinearColor
{
float R; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
float G; // 0x0004(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
float B; // 0x0008(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
float A; // 0x000C(0x0004) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
inline FLinearColor()
: R(0), G(0), B(0), A(0)
{ }
inline FLinearColor(float r, float g, float b, float a)
: R(r),
G(g),
B(b),
A(a)
{ }
};
class UKismetSystemLibrary : public UObject class UKismetSystemLibrary : public UObject
{ {
public: public:
@@ -35,4 +102,109 @@ public:
KismetSystemLibrary->ProcessEvent(fn, &UKismetSystemLibrary_ExecuteConsoleCommand_Params); KismetSystemLibrary->ProcessEvent(fn, &UKismetSystemLibrary_ExecuteConsoleCommand_Params);
} }
static bool LineTraceSingle(UObject* WorldContextObject, FVector Start, FVector End, ETraceTypeQuery TraceChannel, bool bTraceComplex,
TArray<AActor*> ActorsToIgnore, EDrawDebugTrace DrawDebugType, bool bIgnoreSelf, FLinearColor TraceColor, FLinearColor TraceHitColor,
float DrawTime, FHitResult** OutHit)
{
static auto LineTraceSingleFn = FindObject<UFunction>("/Script/Engine.KismetSystemLibrary.LineTraceSingle");
if (!LineTraceSingleFn)
return false;
struct UKismetSystemLibrary_LineTraceSingle_Params
{
UObject* WorldContextObject; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FVector Start; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FVector End; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
ETraceTypeQuery TraceChannel; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bTraceComplex; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
TArray<AActor*> ActorsToIgnore; // (ConstParm, Parm, OutParm, ZeroConstructor, ReferenceParm, NativeAccessSpecifierPublic)
EDrawDebugTrace DrawDebugType; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FHitResult OutHit; // (Parm, OutParm, IsPlainOldData, NoDestructor, ContainsInstancedReference, NativeAccessSpecifierPublic)
bool bIgnoreSelf; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FLinearColor TraceColor; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, AdvancedDisplay, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FLinearColor TraceHitColor; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, AdvancedDisplay, HasGetValueTypeHash, NativeAccessSpecifierPublic)
float DrawTime; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, AdvancedDisplay, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
};
static auto ReturnValueOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingle", "ReturnValue");
static auto OutHitOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingle", "OutHit");
static auto bIgnoreSelfOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingle", "bIgnoreSelf");
static auto ParamsSize = LineTraceSingleFn->GetPropertiesSize();
auto Params = Alloc(ParamsSize);
((UKismetSystemLibrary_LineTraceSingle_Params*)Params)->WorldContextObject = WorldContextObject;
((UKismetSystemLibrary_LineTraceSingle_Params*)Params)->Start = Start;
((UKismetSystemLibrary_LineTraceSingle_Params*)Params)->End = End;
((UKismetSystemLibrary_LineTraceSingle_Params*)Params)->TraceChannel = TraceChannel;
((UKismetSystemLibrary_LineTraceSingle_Params*)Params)->bTraceComplex = bTraceComplex;
*(bool*)(__int64(Params) + bIgnoreSelfOffset) = bIgnoreSelf;
static auto KismetSystemLibrary = FindObject("/Script/Engine.Default__KismetSystemLibrary");
KismetSystemLibrary->ProcessEvent(LineTraceSingleFn, Params);
if (OutHit)
*OutHit = (FHitResult*)(__int64(Params) + OutHitOffset);
return *(bool*)(__int64(Params) + ReturnValueOffset);
// free params frfr
}
static bool LineTraceSingleByProfile(UObject* WorldContextObject, const FVector& Start, const FVector& End, FName ProfileName, bool bTraceComplex,
const TArray<AActor*>& ActorsToIgnore, EDrawDebugTrace DrawDebugType, FHitResult** OutHit, bool bIgnoreSelf, const FLinearColor& TraceColor,
const FLinearColor& TraceHitColor, float DrawTime)
{
auto LineTraceSingleByProfileFn = FindObject<UFunction>("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile");
if (!LineTraceSingleByProfileFn)
return false;
struct UKismetSystemLibrary_LineTraceSingleByProfile_Params
{
UObject* WorldContextObject; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FVector Start; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FVector End; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FName ProfileName; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool bTraceComplex; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
TArray<AActor*> ActorsToIgnore; // (ConstParm, Parm, OutParm, ZeroConstructor, ReferenceParm, NativeAccessSpecifierPublic)
EDrawDebugTrace DrawDebugType; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FHitResult OutHit; // (Parm, OutParm, IsPlainOldData, NoDestructor, ContainsInstancedReference, NativeAccessSpecifierPublic)
bool bIgnoreSelf; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FLinearColor TraceColor; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, AdvancedDisplay, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FLinearColor TraceHitColor; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, AdvancedDisplay, HasGetValueTypeHash, NativeAccessSpecifierPublic)
float DrawTime; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, AdvancedDisplay, HasGetValueTypeHash, NativeAccessSpecifierPublic)
bool ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
};
static auto ParamSize = LineTraceSingleByProfileFn->GetPropertiesSize();
auto Params = Alloc(ParamSize);
static auto WorldContextObjectOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "WorldContextObject");
static auto StartOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "Start");
static auto EndOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "End");
static auto ProfileNameOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "ProfileName");
static auto bTraceComplexOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "bTraceComplex");
static auto ReturnValueOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "ReturnValue");
static auto OutHitOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "OutHit");
static auto bIgnoreSelfOffset = FindOffsetStruct("/Script/Engine.KismetSystemLibrary.LineTraceSingleByProfile", "bIgnoreSelf");
*(UObject**)(__int64(Params) + WorldContextObjectOffset) = WorldContextObject;
*(FVector*)(__int64(Params) + StartOffset) = Start;
*(FVector*)(__int64(Params) + EndOffset) = End;
*(FName*)(__int64(Params) + ProfileNameOffset) = ProfileName;
*(bool*)(__int64(Params) + bTraceComplexOffset) = bTraceComplex;
*(bool*)(__int64(Params) + bIgnoreSelfOffset) = bIgnoreSelf;
static auto KismetSystemLibrary = FindObject("/Script/Engine.Default__KismetSystemLibrary");
KismetSystemLibrary->ProcessEvent(LineTraceSingleByProfileFn, Params);
if (OutHit)
*OutHit = (FHitResult*)(__int64(Params) + OutHitOffset);
return *(bool*)(__int64(Params) + ReturnValueOffset);
}
}; };

View File

@@ -18,5 +18,27 @@ struct FUniqueNetIdRepl // : public FUniqueNetIdWrapper
return Size; return Size;
} }
TArray<uint8>& GetReplicationBytes()
{
static auto ReplicationBytesOffset = FindOffsetStruct("/Script/Engine.UniqueNetIdRepl", "ReplicationBytes");
return *(TArray<uint8>*)(__int64(this) + ReplicationBytesOffset);
}
void CopyFromAnotherUniqueId(FUniqueNetIdRepl* OtherUniqueId)
{
CopyStruct(this, OtherUniqueId, GetSizeOfStruct(), GetStruct());
auto& ReplicationBytes = GetReplicationBytes();
ReplicationBytes.Free();
// Now this is what we call 1 to 1 array copying.
for (int i = 0; i < OtherUniqueId->GetReplicationBytes().Num(); i++)
{
ReplicationBytes.Add(OtherUniqueId->GetReplicationBytes().at(i));
}
}
/* bool IsEqual(FUniqueNetIdRepl* Other) */ /* bool IsEqual(FUniqueNetIdRepl* Other) */
}; };

View File

@@ -3,6 +3,12 @@
#include "reboot.h" #include "reboot.h"
void APlayerController::ServerChangeName(FString& S)
{
static auto ServerChangeNameFn = FindObject<UFunction>("/Script/Engine.PlayerController.ServerChangeName");
this->ProcessEvent(ServerChangeNameFn, &S);
}
UCheatManager*& APlayerController::SpawnCheatManager(UClass* CheatManagerClass) UCheatManager*& APlayerController::SpawnCheatManager(UClass* CheatManagerClass)
{ {
GetCheatManager() = UGameplayStatics::SpawnObject<UCheatManager>(CheatManagerClass, this, true); GetCheatManager() = UGameplayStatics::SpawnObject<UCheatManager>(CheatManagerClass, this, true);

View File

@@ -4,6 +4,7 @@
#include "Controller.h" #include "Controller.h"
#include "CheatManager.h" #include "CheatManager.h"
#include "UnrealString.h"
#include "Rotator.h" #include "Rotator.h"
class APlayerController : public AController class APlayerController : public AController
@@ -39,6 +40,7 @@ public:
return this->Get<UCheatManager*>(CheatManagerOffset); return this->Get<UCheatManager*>(CheatManagerOffset);
} }
void ServerChangeName(FString& S);
UCheatManager*& SpawnCheatManager(UClass* CheatManagerClass); UCheatManager*& SpawnCheatManager(UClass* CheatManagerClass);
FRotator GetControlRotation(); FRotator GetControlRotation();
void Possess(class APawn* Pawn); void Possess(class APawn* Pawn);

View File

@@ -29,3 +29,23 @@ int& APlayerState::GetPlayerID()
return Get<int>(PlayerIDOffset); return Get<int>(PlayerIDOffset);
} }
bool APlayerState::IsBot()
{
static auto bIsABotOffset = GetOffset("bIsABot");
static auto bIsABotFieldMask = GetFieldMask(GetProperty("bIsABot"));
return ReadBitfieldValue(bIsABotOffset, bIsABotFieldMask);
}
void APlayerState::SetIsBot(bool NewValue)
{
static auto bIsABotOffset = GetOffset("bIsABot");
static auto bIsABotFieldMask = GetFieldMask(GetProperty("bIsABot"));
return SetBitfieldValue(bIsABotOffset, bIsABotFieldMask, NewValue);
}
void APlayerState::OnRep_PlayerName()
{
static auto OnRep_PlayerNameFn = FindObject<UFunction>("/Script/Engine.PlayerState.OnRep_PlayerName");
this->ProcessEvent(OnRep_PlayerNameFn);
}

View File

@@ -9,4 +9,7 @@ class APlayerState : public AActor
public: public:
FString GetPlayerName(); FString GetPlayerName();
int& GetPlayerID(); // for future me to deal with (this is a short on some versions). int& GetPlayerID(); // for future me to deal with (this is a short on some versions).
bool IsBot();
void SetIsBot(bool NewValue);
void OnRep_PlayerName();
}; };

View File

@@ -274,6 +274,7 @@
<ClInclude Include="BGA.h" /> <ClInclude Include="BGA.h" />
<ClInclude Include="BinaryHeap.h" /> <ClInclude Include="BinaryHeap.h" />
<ClInclude Include="BitArray.h" /> <ClInclude Include="BitArray.h" />
<ClInclude Include="bots.h" />
<ClInclude Include="BuildingActor.h" /> <ClInclude Include="BuildingActor.h" />
<ClInclude Include="BuildingContainer.h" /> <ClInclude Include="BuildingContainer.h" />
<ClInclude Include="BuildingFoundation.h" /> <ClInclude Include="BuildingFoundation.h" />

View File

@@ -712,9 +712,6 @@
<ClInclude Include="AttributeSet.h"> <ClInclude Include="AttributeSet.h">
<Filter>Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Public</Filter> <Filter>Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Public</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="gui.h">
<Filter>Reboot\Public\GUI</Filter>
</ClInclude>
<ClInclude Include="FortWeaponRangedMountedCannon.h"> <ClInclude Include="FortWeaponRangedMountedCannon.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Athena\Vehicle</Filter> <Filter>FortniteGame\Source\FortniteGame\Public\Athena\Vehicle</Filter>
</ClInclude> </ClInclude>
@@ -851,6 +848,12 @@
<ClInclude Include="FortLootLevel.h"> <ClInclude Include="FortLootLevel.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter> <Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="bots.h">
<Filter>Reboot\Public</Filter>
</ClInclude>
<ClInclude Include="gui.h">
<Filter>Reboot\Public</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Engine"> <Filter Include="Engine">
@@ -1051,9 +1054,6 @@
<Filter Include="Engine\Source\Runtime\Core\Public\Algo\Impl"> <Filter Include="Engine\Source\Runtime\Core\Public\Algo\Impl">
<UniqueIdentifier>{74e42db4-bdac-4e42-bb7e-58f1ab17b738}</UniqueIdentifier> <UniqueIdentifier>{74e42db4-bdac-4e42-bb7e-58f1ab17b738}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Reboot\Public\GUI">
<UniqueIdentifier>{15a7e32e-0505-49cc-9f6a-89d3e5c865b5}</UniqueIdentifier>
</Filter>
<Filter Include="Libaries"> <Filter Include="Libaries">
<UniqueIdentifier>{c0586029-3b4a-48f9-8de9-5b48a972cb5e}</UniqueIdentifier> <UniqueIdentifier>{c0586029-3b4a-48f9-8de9-5b48a972cb5e}</UniqueIdentifier>
</Filter> </Filter>

View File

@@ -5,9 +5,9 @@
MS_ALIGN(16) struct FTransform MS_ALIGN(16) struct FTransform
{ {
FQuat Rotation; // 0x0000(0x0010) (Edit, BlueprintVisible, SaveGame, IsPlainOldData, NoDestructor, NativeAccessSpecifierPublic) FQuat Rotation = FQuat(0, 0, 0, 0); // 0x0000(0x0010) (Edit, BlueprintVisible, SaveGame, IsPlainOldData, NoDestructor, NativeAccessSpecifierPublic)
FVector Translation; // 0x0010(0x000C) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) FVector Translation = FVector(0, 0, 0); // 0x0010(0x000C) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
unsigned char UnknownData00[0x4]; // 0x001C(0x0004) MISSED OFFSET unsigned char UnknownData00[0x4]; // 0x001C(0x0004) MISSED OFFSET
FVector Scale3D; // 0x0020(0x000C) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) FVector Scale3D = FVector(0, 0, 0); // 0x0020(0x000C) (Edit, BlueprintVisible, ZeroConstructor, SaveGame, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
unsigned char UnknownData01[0x4]; // 0x002C(0x0004) MISSED OFFSET unsigned char UnknownData01[0x4]; // 0x002C(0x0004) MISSED OFFSET
}; };

View File

@@ -19,12 +19,12 @@ public:
struct FActorSpawnParameters struct FActorSpawnParameters
{ {
FName Name; FName Name = FName(0);
UObject* Template; UObject* Template = nullptr;
UObject* Owner; UObject* Owner = nullptr;
UObject** Instigator; UObject** Instigator = nullptr;
UObject* OverrideLevel; UObject* OverrideLevel = nullptr;
ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride; ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined;
uint16 bRemoteOwned : 1; uint16 bRemoteOwned : 1;
uint16 bNoFail : 1; uint16 bNoFail : 1;
uint16 bDeferConstruction : 1; uint16 bDeferConstruction : 1;

248
Project Reboot 3.0/bots.h Normal file
View File

@@ -0,0 +1,248 @@
#pragma once
#include "FortGameModeAthena.h"
#include "OnlineReplStructs.h"
#include "BuildingContainer.h"
class PlayerBot
{
public:
AFortPlayerControllerAthena* PlayerController = nullptr;
float NextJumpTime = 1.0f;
void Initialize(FTransform SpawnTransform)
{
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
static auto PawnClass = FindObject<UClass>("/Game/Athena/PlayerPawn_Athena.PlayerPawn_Athena_C");
FActorSpawnParameters PawnSpawnParameters{};
PawnSpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
PlayerController = GetWorld()->SpawnActor<AFortPlayerControllerAthena>(AFortPlayerControllerAthena::StaticClass());
AFortPlayerPawnAthena* Pawn = GetWorld()->SpawnActor<AFortPlayerPawnAthena>(PawnClass, SpawnTransform, PawnSpawnParameters);
AFortPlayerStateAthena* PlayerState = Cast<AFortPlayerStateAthena>(PlayerController->GetPlayerState());
if (!Pawn || !PlayerState)
return;
static int CurrentBotNum = 1;
auto BotNumWStr = std::to_wstring(CurrentBotNum++);
FString NewName = (L"RebootBot" + BotNumWStr).c_str();
PlayerController->ServerChangeName(NewName);
PlayerState->OnRep_PlayerName();
PlayerState->GetTeamIndex() = GameMode->Athena_PickTeamHook(GameMode, 0, PlayerController);
static auto SquadIdOffset = PlayerState->GetOffset("SquadId", false);
if (SquadIdOffset != -1)
PlayerState->GetSquadId() = PlayerState->GetTeamIndex() - 2;
PlayerState->SetIsBot(true);
/*
static auto FortRegisteredPlayerInfoClass = FindObject<UClass>("/Script/FortniteGame.FortRegisteredPlayerInfo");
static auto MyPlayerInfoOffset = PlayerController->GetOffset("MyPlayerInfo");
PlayerController->Get(MyPlayerInfoOffset) = UGameplayStatics::SpawnObject(FortRegisteredPlayerInfoClass, PlayerController);
if (!PlayerController->Get(MyPlayerInfoOffset))
{
LOG_ERROR(LogBots, "Failed to spawn PlayerInfo!");
Pawn->K2_DestroyActor();
PlayerController->K2_DestroyActor();
return nullptr;
}
auto& PlayerInfo = PlayerController->Get(MyPlayerInfoOffset);
static auto UniqueIdOffset = PlayerState->GetOffset("UniqueId");
static auto PlayerInfo_PlayerNameOffset = PlayerInfo->GetOffset("PlayerName");
static auto PlayerIDOffset = PlayerInfo->GetOffset("PlayerID");
PlayerInfo->GetPtr<FUniqueNetIdRepl>(PlayerIDOffset)->CopyFromAnotherUniqueId(PlayerState->GetPtr<FUniqueNetIdRepl>(UniqueIdOffset));
PlayerInfo->Get<FString>(PlayerInfo_PlayerNameOffset) = PlayerState->GetPlayerName();
*/
PlayerController->Possess(Pawn);
Pawn->SetHealth(100);
Pawn->SetMaxHealth(100);
FActorSpawnParameters WorldInventorySpawnParameters{};
WorldInventorySpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
WorldInventorySpawnParameters.Owner = PlayerController;
FTransform WorldInventorySpawnTransform{};
static auto FortInventoryClass = FindObject<UClass>("/Script/FortniteGame.FortInventory"); // AFortInventory::StaticClass()
PlayerController->GetWorldInventory() = GetWorld()->SpawnActor<AFortInventory>(FortInventoryClass, WorldInventorySpawnTransform, WorldInventorySpawnParameters);
if (!PlayerController->GetWorldInventory())
{
LOG_ERROR(LogBots, "Failed to spawn WorldInventory!");
Pawn->K2_DestroyActor();
PlayerController->K2_DestroyActor();
return;
}
PlayerController->GetWorldInventory()->GetInventoryType() = EFortInventoryType::World;
static auto bHasInitializedWorldInventoryOffset = PlayerController->GetOffset("bHasInitializedWorldInventory");
PlayerController->Get<bool>(bHasInitializedWorldInventoryOffset) = true;
auto& StartingItems = GameMode->GetStartingItems();
auto PickaxeInstance = PlayerController->AddPickaxeToInventory();
for (int i = 0; i < StartingItems.Num(); i++)
{
auto& StartingItem = StartingItems.at(i);
PlayerController->GetWorldInventory()->AddItem(StartingItem.GetItem(), nullptr, StartingItem.GetCount());
}
if (PickaxeInstance)
{
PlayerController->ServerExecuteInventoryItemHook(PlayerController, PickaxeInstance->GetItemEntry()->GetItemGuid());
}
PlayerController->GetWorldInventory()->Update();
/* static auto HeroType = FindObject(L"/Game/Athena/Heroes/HID_115_Athena_Commando_M_CarbideBlue.HID_115_Athena_Commando_M_CarbideBlue");
static auto HeroTypeOffset = PlayerState->GetOffset("HeroType");
if (HeroTypeOffset != -1)
PlayerState->Get(HeroTypeOffset) = HeroType; */
auto PlayerAbilitySet = GetPlayerAbilitySet();
auto AbilitySystemComponent = PlayerState->GetAbilitySystemComponent();
if (PlayerAbilitySet)
{
PlayerAbilitySet->GiveToAbilitySystem(AbilitySystemComponent);
}
PlayerController->GetCosmeticLoadout()->GetCharacter() = FindObject("/Game/Athena/Items/Cosmetics/Characters/CID_263_Athena_Commando_F_MadCommander.CID_263_Athena_Commando_F_MadCommander");
Pawn->GetCosmeticLoadout()->GetCharacter() = PlayerController->GetCosmeticLoadout()->GetCharacter();
PlayerController->ApplyCosmeticLoadout();
GameState->GetPlayersLeft()++;
GameState->OnRep_PlayersLeft();
GameMode->GetAlivePlayers().Add(PlayerController);
}
};
static std::vector<PlayerBot> AllPlayerBotsToTick;
namespace Bots
{
static AFortPlayerControllerAthena* SpawnBot(FTransform SpawnTransform)
{
auto playerBot = PlayerBot();
playerBot.Initialize(SpawnTransform);
AllPlayerBotsToTick.push_back(playerBot);
return playerBot.PlayerController;
}
static void SpawnBotsAtPlayerStarts(int AmountOfBots)
{
return;
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
for (int i = 0; i < AmountOfBots; i++)
{
FTransform SpawnTransform{};
SpawnTransform.Translation = FVector(1, 1, 10000);
SpawnTransform.Rotation = FQuat();
SpawnTransform.Scale3D = FVector(1, 1, 1);
auto NewBot = SpawnBot(SpawnTransform);
auto PlayerStart = GameMode->K2_FindPlayerStart(NewBot, NewBot->GetPlayerState()->GetPlayerName()); // i dont think this works
if (!PlayerStart)
{
LOG_ERROR(LogBots, "Failed to find PlayerStart for bot!");
NewBot->GetPawn()->K2_DestroyActor();
NewBot->K2_DestroyActor();
continue;
}
NewBot->TeleportTo(PlayerStart->GetActorLocation(), FRotator());
NewBot->SetCanBeDamaged(Fortnite_Version < 7); // idk lol for spawn island
}
}
static void Tick()
{
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
auto AllBuildingContainers = UGameplayStatics::GetAllActorsOfClass(GetWorld(), ABuildingContainer::StaticClass());
// for (int i = 0; i < GameMode->GetAlivePlayers().Num(); i++)
for (auto& PlayerBot : AllPlayerBotsToTick)
{
auto CurrentPlayer = PlayerBot.PlayerController;
if (CurrentPlayer->IsActorBeingDestroyed())
continue;
auto CurrentPawn = CurrentPlayer->GetMyFortPawn();
auto CurrentPlayerState = Cast<AFortPlayerStateAthena>(CurrentPlayer->GetPlayerState());
if (!CurrentPlayerState || !CurrentPlayerState->IsBot())
continue;
if (GameState->GetGamePhase() == EAthenaGamePhase::Warmup)
{
/* if (!CurrentPlayer->IsPlayingEmote())
{
static auto AthenaDanceItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.AthenaDanceItemDefinition");
auto RandomDanceID = GetRandomObjectOfClass(AthenaDanceItemDefinitionClass);
CurrentPlayer->ServerPlayEmoteItemHook(CurrentPlayer, RandomDanceID);
} */
}
if (CurrentPlayerState->IsInAircraft() && !CurrentPlayerState->HasThankedBusDriver())
{
static auto ServerThankBusDriverFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerAthena.ServerThankBusDriver");
CurrentPlayer->ProcessEvent(ServerThankBusDriverFn);
}
if (CurrentPawn)
{
if (PlayerBot.NextJumpTime <= UGameplayStatics::GetTimeSeconds(GetWorld()))
{
static auto JumpFn = FindObject<UFunction>("/Script/Engine.Character.Jump");
CurrentPawn->ProcessEvent(JumpFn);
PlayerBot.NextJumpTime = UGameplayStatics::GetTimeSeconds(GetWorld()) + (rand() % 4 + 3);
}
}
/* bool bShouldJumpFromBus = CurrentPlayerState->IsInAircraft(); // TODO (Milxnor) add a random percent thing
if (bShouldJumpFromBus)
{
CurrentPlayer->ServerAttemptAircraftJumpHook(CurrentPlayer, FRotator());
} */
}
AllBuildingContainers.Free();
}
}

View File

@@ -7,6 +7,8 @@
#include "FortAthenaMutator_Barrier.h" #include "FortAthenaMutator_Barrier.h"
#include "FortWeaponMeleeItemDefinition.h" #include "FortWeaponMeleeItemDefinition.h"
#include "builder.h" #include "builder.h"
#include "FortLootPackage.h"
#include "bots.h"
bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController) bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController)
{ {
@@ -200,6 +202,25 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
SendMessageToConsole(PlayerController, L"Granted item!"); SendMessageToConsole(PlayerController, L"Granted item!");
} }
else if (Command == "printsimulatelootdrops")
{
if (NumArgs < 1)
{
SendMessageToConsole(PlayerController, L"Please provide a LootTierGroup!");
return;
}
auto& lootTierGroup = Arguments[1];
auto LootDrops = PickLootDrops(UKismetStringLibrary::Conv_StringToName(std::wstring(lootTierGroup.begin(), lootTierGroup.end()).c_str()), true);
for (int i = 0; i < LootDrops.size(); i++)
{
}
SendMessageToConsole(PlayerController, L"Printed!");
}
else if (Command == "setpickaxe") else if (Command == "setpickaxe")
{ {
if (NumArgs < 1) if (NumArgs < 1)
@@ -348,7 +369,12 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
} }
auto Location = Pawn->GetActorLocation(); auto Location = Pawn->GetActorLocation();
AFortPickup::SpawnPickup(WID, Location, count);
PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(WID, count, -1);
CreateData.SpawnLocation = Location;
AFortPickup::SpawnPickup(CreateData);
} }
else if (Command == "listplayers") else if (Command == "listplayers")
{ {
@@ -547,6 +573,60 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
SendMessageToConsole(PlayerController, L"Not a valid class!"); SendMessageToConsole(PlayerController, L"Not a valid class!");
} }
} }
else if (Command == "spawnbot")
{
auto Pawn = ReceivingController->GetPawn();
if (!Pawn)
{
SendMessageToConsole(PlayerController, L"No pawn to spawn bot at!");
return;
}
int Count = 1;
if (Arguments.size() >= 2)
{
try { Count = std::stod(Arguments[1]); }
catch (...) {}
}
constexpr int Max = 99;
if (Count > Max)
{
SendMessageToConsole(PlayerController, (std::wstring(L"You went over the limit! Only spawning ") + std::to_wstring(Max) + L".").c_str());
Count = Max;
}
int AmountSpawned = 0;
for (int i = 0; i < Count; i++)
{
FActorSpawnParameters SpawnParameters{};
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;
auto Loc = Pawn->GetActorLocation();
Loc.Z += 1000;
FTransform Transform;
Transform.Translation = Loc;
Transform.Scale3D = FVector(1, 1, 1);
auto NewActor = Bots::SpawnBot(Transform);
if (!NewActor)
{
SendMessageToConsole(PlayerController, L"Failed to spawn an actor!");
}
else
{
AmountSpawned++;
}
}
SendMessageToConsole(PlayerController, L"Summoned!");
}
else if (Command == "sethealth") else if (Command == "sethealth")
{ {
auto Pawn = ReceivingController->GetMyFortPawn(); auto Pawn = ReceivingController->GetMyFortPawn();

View File

@@ -7,6 +7,7 @@
#include "KismetStringLibrary.h" #include "KismetStringLibrary.h"
#include "DataTableFunctionLibrary.h" #include "DataTableFunctionLibrary.h"
#include "FortPlaysetItemDefinition.h" #include "FortPlaysetItemDefinition.h"
#include "gui.h"
static inline void (*SetZoneToIndexOriginal)(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK); static inline void (*SetZoneToIndexOriginal)(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK);
@@ -178,6 +179,11 @@ void ProcessEventHook(UObject* Object, UFunction* Function, void* Parameters)
if (!Object || !Function) if (!Object || !Function)
return; return;
if (bEnableBotTick)
{
Bots::Tick();
}
if (Globals::bLogProcessEvent) if (Globals::bLogProcessEvent)
{ {
auto FunctionName = Function->GetName(); // UKismetSystemLibrary::GetPathName(Function).ToString(); auto FunctionName = Function->GetName(); // UKismetSystemLibrary::GetPathName(Function).ToString();

View File

@@ -513,9 +513,6 @@ DWORD WINAPI Main(LPVOID)
break; break;
} }
} }
// Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.EndGhostMode"),
// AFortPlayerControllerAthena::EndGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::EndGhostModeOriginal, false);
} }
} }

View File

@@ -627,7 +627,7 @@ static inline uint64 FindUpdateTrackedAttributesLea() // kill me
static inline uint64 FindCombinePickupLea() // kill me static inline uint64 FindCombinePickupLea() // kill me
{ {
return 0; // return 0;
/* uint64 OnRep_PickupLocationDataAddr = 0; // TODO (Idea: Find SetupCombinePickupDelegates from this). /* uint64 OnRep_PickupLocationDataAddr = 0; // TODO (Idea: Find SetupCombinePickupDelegates from this).

View File

@@ -38,6 +38,7 @@
#include "FortWeaponItemDefinition.h" #include "FortWeaponItemDefinition.h"
#include "events.h" #include "events.h"
#include "FortAthenaMutator_Heist.h" #include "FortAthenaMutator_Heist.h"
#include "BGA.h"
#define GAME_TAB 1 #define GAME_TAB 1
#define PLAYERS_TAB 2 #define PLAYERS_TAB 2
@@ -64,6 +65,9 @@ extern inline float AutoBusStartSeconds = 60;
extern inline int NumRequiredPlayersToStart = 2; extern inline int NumRequiredPlayersToStart = 2;
extern inline bool bDebugPrintLooting = false; extern inline bool bDebugPrintLooting = false;
extern inline bool bDebugPrintSwapping = false; extern inline bool bDebugPrintSwapping = false;
extern inline bool bEnableBotTick = false;
extern inline bool bEnableCombinePickup = false;
extern inline int AmountOfBotsToSpawn = 0;
// THE BASE CODE IS FROM IMGUI GITHUB // THE BASE CODE IS FROM IMGUI GITHUB
@@ -279,6 +283,7 @@ static inline void StaticUI()
#ifndef PROD #ifndef PROD
ImGui::Checkbox("Log ProcessEvent", &Globals::bLogProcessEvent); ImGui::Checkbox("Log ProcessEvent", &Globals::bLogProcessEvent);
ImGui::InputInt("Amount of bots to spawn", &AmountOfBotsToSpawn);
#endif #endif
ImGui::Checkbox("Infinite Ammo", &Globals::bInfiniteAmmo); ImGui::Checkbox("Infinite Ammo", &Globals::bInfiniteAmmo);
@@ -470,6 +475,11 @@ static inline void MainUI()
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), cmd, nullptr); UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), cmd, nullptr);
} }
if (ImGui::Button("Spawn BGAs"))
{
SpawnBGAs();
}
/* /*
if (ImGui::Button("New")) if (ImGui::Button("New"))
{ {
@@ -897,6 +907,8 @@ static inline void MainUI()
static std::string FunctionNameToDump; static std::string FunctionNameToDump;
ImGui::Checkbox("Fill Vending Machines", &Globals::bFillVendingMachines); ImGui::Checkbox("Fill Vending Machines", &Globals::bFillVendingMachines);
ImGui::Checkbox("Enable Bot Tick", &bEnableBotTick);
ImGui::Checkbox("Enable Combine Pickup", &bEnableCombinePickup);
ImGui::InputText("Class Name to mess with", &ClassNameToDump); ImGui::InputText("Class Name to mess with", &ClassNameToDump);
ImGui::InputText("Function Name to mess with", &FunctionNameToDump); ImGui::InputText("Function Name to mess with", &FunctionNameToDump);
@@ -1001,7 +1013,8 @@ static inline void PregameUI()
if (!bSwitchedInitialLevel) if (!bSwitchedInitialLevel)
ImGui::SliderInt("Seconds until load into map", &SecondsUntilTravel, 1, 100); ImGui::SliderInt("Seconds until load into map", &SecondsUntilTravel, 1, 100);
ImGui::InputText("Playlist", &PlaylistName); if (!Globals::bCreative)
ImGui::InputText("Playlist", &PlaylistName);
} }
static inline DWORD WINAPI GuiThread(LPVOID) static inline DWORD WINAPI GuiThread(LPVOID)

View File

@@ -81,6 +81,7 @@ inline void InitLogger()
MakeLogger("LogReplication"); MakeLogger("LogReplication");
MakeLogger("LogMutator"); MakeLogger("LogMutator");
MakeLogger("LogVehicles"); MakeLogger("LogVehicles");
MakeLogger("LogBots");
MakeLogger("LogCosmetics"); MakeLogger("LogCosmetics");
} }

View File

@@ -240,6 +240,14 @@ inline std::vector<T*> GetAllObjectsOfClass(UClass* Class)
return Objects; return Objects;
} }
template<typename T = UObject>
inline T* GetRandomObjectOfClass(UClass* Class)
{
auto AllObjectsVec = GetAllObjectsOfClass<T>(Class);
return AllObjectsVec.size() > 0 ? AllObjectsVec.at(std::rand() % AllObjectsVec.size()) : nullptr;
}
inline void* FindPropertyStruct(const std::string& StructName, const std::string& MemberName, bool bWarnIfNotFound = true) inline void* FindPropertyStruct(const std::string& StructName, const std::string& MemberName, bool bWarnIfNotFound = true)
{ {
UObject* Struct = FindObject(StructName); UObject* Struct = FindObject(StructName);
@@ -377,9 +385,9 @@ static void CopyStruct(void* Dest, void* Src, size_t Size, UStruct* Struct = nul
} }
template <typename T = __int64> template <typename T = __int64>
static T* Alloc(size_t Size = sizeof(T), bool bUseRealloc = false) static T* Alloc(size_t Size = sizeof(T), bool bUseFMemoryRealloc = false)
{ {
return bUseRealloc ? (T*)FMemory::Realloc(0, Size, 0) : (T*)VirtualAlloc(0, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); return bUseFMemoryRealloc ? (T*)FMemory::Realloc(0, Size, 0) : (T*)VirtualAlloc(0, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
} }
namespace MemberOffsets namespace MemberOffsets