start work on vending machines, fix some playlist specific things, fixed a bug with <s5 playlist looting,
This commit is contained in:
Milxnor
2023-04-08 19:05:06 -04:00
parent b194527e1b
commit 0d7b45cbbc
27 changed files with 734 additions and 35 deletions

View File

@@ -29,6 +29,15 @@ struct FActiveGameplayEffectHandle
unsigned char UnknownData00[0x3]; // 0x0005(0x0003) MISSED OFFSET
};
struct FGameplayAbilitySpecContainer : public FFastArraySerializer
{
TArray<FGameplayAbilitySpec>& GetItems()
{
static auto ItemsOffset = FindOffsetStruct("/Script/GameplayAbilities.GameplayAbilitySpecContainer", "Items");
return *(TArray<FGameplayAbilitySpec>*)(__int64(this) + ItemsOffset);
}
};
class UAbilitySystemComponent : public UObject
{
public:
@@ -50,11 +59,18 @@ public:
return Get<TArray<UObject*>>(SpawnedAttributesOffset);
}
FActiveGameplayEffectHandle ApplyGameplayEffectToSelf(UClass* GameplayEffectClass, float Level, const FGameplayEffectContextHandle& EffectContext);
FGameplayAbilitySpecContainer* GetActivatableAbilities()
{
static auto ActivatableAbilitiesOffset = this->GetOffset("ActivatableAbilities");
return GetPtr<FGameplayAbilitySpecContainer>(ActivatableAbilitiesOffset);
}
bool HasAbility(UObject* DefaultAbility);
FActiveGameplayEffectHandle ApplyGameplayEffectToSelf(UClass* GameplayEffectClass, float Level, const FGameplayEffectContextHandle& EffectContext = FGameplayEffectContextHandle());
// FGameplayEffectContextHandle MakeEffectContext();
void RemoveActiveGameplayEffectBySourceEffect(UClass* GEClass, int StacksToRemove, UAbilitySystemComponent* Instigator);
void ConsumeAllReplicatedData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey* AbilityOriginalPredictionKey);
FGameplayAbilitySpecHandle GiveAbilityEasy(UClass* AbilityClass, UObject* SourceObject = nullptr);
FGameplayAbilitySpecHandle GiveAbilityEasy(UClass* AbilityClass, UObject* SourceObject = nullptr, bool bDoNotRegive = true);
FGameplayAbilitySpec* FindAbilitySpecFromHandle(FGameplayAbilitySpecHandle Handle);
static void InternalServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, const FPredictionKey* PredictionKey, const FGameplayEventData* TriggerEventData);

View File

@@ -50,6 +50,23 @@ FActiveGameplayEffectHandle UAbilitySystemComponent::ApplyGameplayEffectToSelf(U
return ContextHandle;
} */
bool UAbilitySystemComponent::HasAbility(UObject* DefaultAbility)
{
auto ActivatableAbilities = GetActivatableAbilities();
auto& Items = ActivatableAbilities->GetItems();
for (int i = 0; i < Items.Num(); i++)
{
auto Spec = Items.AtPtr(i, FGameplayAbilitySpec::GetStructSize());
if (Spec->GetAbility() == DefaultAbility)
return true;
}
return false;
}
void UAbilitySystemComponent::RemoveActiveGameplayEffectBySourceEffect(UClass* GEClass, int StacksToRemove, UAbilitySystemComponent* Instigator)
{
static auto RemoveActiveGameplayEffectBySourceEffectFn = FindObject<UFunction>(L"/Script/GameplayAbilities.AbilitySystemComponent.RemoveActiveGameplayEffectBySourceEffect");
@@ -114,8 +131,7 @@ void UAbilitySystemComponent::InternalServerTryActivateAbilityHook(UAbilitySyste
AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset));
SetBitfield((PlaceholderBitfield*)(__int64(Spec) + InputPressedOffset), 1, false); // InputPressed = false
static auto ActivatableAbilitiesOffset = AbilitySystemComponent->GetOffset("ActivatableAbilities");
AbilitySystemComponent->Get<FFastArraySerializer>(ActivatableAbilitiesOffset).MarkItemDirty(Spec);
AbilitySystemComponent->GetActivatableAbilities()->MarkItemDirty(Spec);
}
else
{
@@ -123,11 +139,19 @@ void UAbilitySystemComponent::InternalServerTryActivateAbilityHook(UAbilitySyste
}
}
FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass, UObject* SourceObject)
FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass, UObject* SourceObject, bool bDoNotRegive)
{
// LOG_INFO(LogDev, "Making spec!");
auto NewSpec = MakeNewSpec(AbilityClass, SourceObject);
auto DefaultAbility = AbilityClass->CreateDefaultObject();
if (!DefaultAbility)
return FGameplayAbilitySpecHandle();
if (bDoNotRegive && HasAbility(DefaultAbility))
return FGameplayAbilitySpecHandle();
auto NewSpec = MakeNewSpec((UClass*)DefaultAbility, SourceObject, true);
// LOG_INFO(LogDev, "Made spec!");

View File

@@ -56,6 +56,13 @@ public:
}
}
bool IsPlayerBuildable()
{
static auto bIsPlayerBuildableOffset = GetOffset("bIsPlayerBuildable");
static auto bIsPlayerBuildableFieldMask = GetFieldMask(GetProperty("bIsPlayerBuildable"));
return ReadBitfieldValue(bIsPlayerBuildableOffset, bIsPlayerBuildableFieldMask);
}
static inline void (*OnDamageServerOriginal)(ABuildingActor* BuildingActor, float Damage, FGameplayTagContainer DamageTags,
FVector Momentum, /* FHitResult */ __int64 HitInfo, APlayerController* InstigatedBy, AActor* DamageCauser,
/* FGameplayEffectContextHandle */ __int64 EffectContext);

View File

@@ -0,0 +1,2 @@
#pragma once

View File

@@ -0,0 +1,20 @@
#pragma once
#include "inc.h"
/*
typedef TAlignedBytes<16, 16> FAlignedInlineDelegateType;
#if USE_SMALL_DELEGATES
typedef FHeapAllocator FDelegateAllocatorType;
#else
typedef TInlineAllocator<2> FDelegateAllocatorType;
#endif
*/
class FDelegateBase
{
public:
// FDelegateAllocatorType::ForElementType<FAlignedInlineDelegateType> DelegateAllocator;
// int32 DelegateSize;
};

View File

@@ -0,0 +1,9 @@
#pragma once
#include "DelegateBase.h"
template <typename WrappedRetValType, typename... ParamTypes>
class TBaseDelegate : public FDelegateBase
{
public:
};

View File

@@ -2,6 +2,7 @@
#include "AbilitySystemComponent.h"
#include "reboot.h"
#include "SoftObjectPtr.h"
struct FGameplayEffectApplicationInfoHard
{
@@ -10,6 +11,13 @@ public:
float Level;
};
struct FGameplayEffectApplicationInfo
{
TSoftObjectPtr<UClass> GameplayEffect; // 0x0000(0x0028) UNKNOWN PROPERTY: SoftClassProperty FortniteGame.GameplayEffectApplicationInfo.GameplayEffect
float Level; // 0x0028(0x0004) (Edit, ZeroConstructor, DisableEditOnInstance, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
unsigned char UnknownData01[0x4]; // 0x002C(0x0004) MISSED OFFSET
};
class UFortAbilitySet : public UObject
{
public:

View File

@@ -23,6 +23,7 @@
#include "Map.h"
#include "OnlineReplStructs.h"
#include "BGA.h"
#include "vendingmachine.h"
enum class EDynamicFoundationEnabledState : uint8_t
{
@@ -41,13 +42,16 @@ enum class EDynamicFoundationType : uint8_t
EDynamicFoundationType_MAX = 4
};
std::string PlaylistName = "/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo";
std::string PlaylistName =
"/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo";
// "/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground";
// "/Game/Athena/Playlists/Carmine/Playlist_Carmine.Playlist_Carmine";
// "/Game/Athena/Playlists/Fill/Playlist_Fill_Solo.Playlist_Fill_Solo";
// "/Game/Athena/Playlists/Low/Playlist_Low_Solo.Playlist_Low_Solo";
static UObject* GetPlaylistToUse()
static UFortPlaylist* GetPlaylistToUse()
{
auto Playlist = FindObject(PlaylistName);
auto Playlist = FindObject<UFortPlaylist>(PlaylistName);
if (Globals::bGoingToPlayEvent)
{
@@ -70,7 +74,7 @@ static UObject* GetPlaylistToUse()
// SET OVERRIDE PLAYLIST DOWN HERE
if (Globals::bCreative)
Playlist = FindObject("/Game/Athena/Playlists/Creative/Playlist_PlaygroundV2.Playlist_PlaygroundV2");
Playlist = FindObject<UFortPlaylist>("/Game/Athena/Playlists/Creative/Playlist_PlaygroundV2.Playlist_PlaygroundV2");
return Playlist;
}
@@ -445,9 +449,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game
}
}
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
GET_PLAYLIST(GameState);
if (CurrentPlaylist)
{
@@ -706,6 +708,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
auto GameState = GameMode->GetGameStateAthena();
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
LOG_INFO(LogPlayer, "HandleStartingNewPlayer!");
// if (Engine_Version < 427)
@@ -716,6 +721,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
{
LastNum69 = AmountOfRestarts;
// FillVendingMachines();
SpawnBGAs();
auto SpawnIsland_FloorLoot = FindObject<UClass>("/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_Warmup.Tiered_Athena_FloorLoot_Warmup_C");
@@ -883,7 +889,6 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
PlayerStateAthena->GetWorldPlayerId() = PlayerStateAthena->GetPlayerID(); // ++CurrentPlayerId; // PlayerStateAthena->Get<int>(PlayerIdOffset); //
}
if (Globals::bAbilitiesEnabled)
{
static auto GameplayAbilitySet = (UFortAbilitySet*)(Fortnite_Version >= 8.30 ? // LoadObject<UObject>(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") ?
LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer", UFortAbilitySet::StaticClass()) :
@@ -891,10 +896,19 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
LOG_INFO(LogDev, "GameplayAbilitySet {}", __int64(GameplayAbilitySet));
auto AbilitySystemComponent = PlayerStateAthena->GetAbilitySystemComponent();
if (GameplayAbilitySet)
{
LOG_INFO(LogDev, "GameplayAbilitySet Name {}", GameplayAbilitySet->GetName());
GameplayAbilitySet->GiveToAbilitySystem(PlayerStateAthena->GetAbilitySystemComponent());
GameplayAbilitySet->GiveToAbilitySystem(AbilitySystemComponent);
}
GET_PLAYLIST(GameState);
if (CurrentPlaylist)
{
// CurrentPlaylist->ApplyModifiersToActor(PlayerStateAthena); // scuffed we need to do as pawn spawns
}
}

View File

@@ -9,20 +9,20 @@
} */
UObject*& AFortGameStateAthena::GetCurrentPlaylist()
UFortPlaylist*& AFortGameStateAthena::GetCurrentPlaylist()
{
static auto CurrentPlaylistInfoOffset = GetOffset("CurrentPlaylistInfo", false);
if (CurrentPlaylistInfoOffset == -1)
{
static auto CurrentPlaylistDataOffset = GetOffset("CurrentPlaylistData");
return Get(CurrentPlaylistDataOffset);
return Get<UFortPlaylist*>(CurrentPlaylistDataOffset);
}
auto CurrentPlaylistInfo = this->GetPtr<FFastArraySerializer>(CurrentPlaylistInfoOffset);
static auto BasePlaylistOffset = FindOffsetStruct("/Script/FortniteGame.PlaylistPropertyArray", "BasePlaylist");
return *(UObject**)(__int64(CurrentPlaylistInfo) + BasePlaylistOffset);
return *(UFortPlaylist**)(__int64(CurrentPlaylistInfo) + BasePlaylistOffset);
}
int AFortGameStateAthena::GetAircraftIndex(AFortPlayerState* PlayerState)

View File

@@ -2,6 +2,7 @@
#include "GameState.h"
#include "FortPlayerState.h"
#include "FortPlaylist.h"
enum class EAthenaGamePhase : uint8_t
{
@@ -30,7 +31,7 @@ public:
return Get<EAthenaGamePhase>(GamePhaseOffset);
}
UObject*& GetCurrentPlaylist();
UFortPlaylist*& GetCurrentPlaylist();
// void AddPlayerStateToGameMemberInfo(class AFortPlayerStateAthena* PlayerState);

View File

@@ -0,0 +1,7 @@
#include "FortGameplayAbilityAthena_PeriodicItemGrant.h"
void UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersHook(UObject* Context, FFrame& Stack, void* Ret)
{
LOG_INFO(LogDev, "StartItemAwardTimersHook!");
return StartItemAwardTimersOriginal(Context, Stack, Ret);
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include "Object.h"
#include "Stack.h"
class UFortGameplayAbilityAthena_PeriodicItemGrant : public UObject // UFortGameplayAbility
{
public:
static inline void (*StartItemAwardTimersOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static void StartItemAwardTimersHook(UObject* Context, FFrame& Stack, void* Ret);
};

View File

@@ -42,6 +42,20 @@ struct FFortItemEntry : FFastArraySerializerItem
static auto StructSize = GetStruct()->GetPropertiesSize();
return StructSize;
}
static FFortItemEntry* MakeItemEntry(UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0)
{
auto Entry = Alloc<FFortItemEntry>(GetStructSize());
if (!Entry)
return nullptr;
Entry->GetItemDefinition() = ItemDefinition;
Entry->GetCount() = Count;
Entry->GetLoadedAmmo() = LoadedAmmo;
return Entry;
}
};
class UFortItem : public UObject

View File

@@ -352,6 +352,40 @@ void UFortKismetLibrary::K2_GiveItemToPlayerHook(UObject* Context, FFrame& Stack
return K2_GiveItemToPlayerOriginal(Context, Stack, Ret);
}
void UFortKismetLibrary::K2_GiveBuildingResourceHook(UObject* Context, FFrame& Stack, void* Ret)
{
LOG_INFO(LogDev, "K2_GiveBuildingResourceHook!");
AFortPlayerController* Controller;
EFortResourceType ResourceType;
int ResourceAmount;
Stack.StepCompiledIn(&Controller);
Stack.StepCompiledIn(&ResourceType);
Stack.StepCompiledIn(&ResourceAmount);
if (!Controller)
return K2_GiveBuildingResourceOriginal(Context, Stack, Ret);
auto WorldInventory = Controller->GetWorldInventory();
if (!WorldInventory)
return K2_GiveBuildingResourceOriginal(Context, Stack, Ret);
auto ItemDefinition = UFortKismetLibrary::K2_GetResourceItemDefinition(ResourceType);
if (!ItemDefinition)
return K2_GiveBuildingResourceOriginal(Context, Stack, Ret);
bool bShouldUpdate = false;
WorldInventory->AddItem(ItemDefinition, &bShouldUpdate, ResourceAmount, 0);
if (bShouldUpdate)
WorldInventory->Update();
return K2_GiveBuildingResourceOriginal(Context, Stack, Ret);
}
void UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret)
{
AFortPlayerController* PlayerController = nullptr; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)

View File

@@ -79,6 +79,7 @@ public:
static inline void (*K2_SpawnPickupInWorldWithLootTierOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static inline bool (*SpawnInstancedPickupInWorldOriginal)(UObject* Context, FFrame& Stack, bool* Ret);
static inline void (*SpawnItemVariantPickupInWorldOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static inline void (*K2_GiveBuildingResourceOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static inline void (*PickLootDropsWithNamedWeightsOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static UFortResourceItemDefinition* K2_GetResourceItemDefinition(EFortResourceType ResourceType);
@@ -93,6 +94,7 @@ public:
static void K2_RemoveItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret);
static void K2_RemoveItemFromPlayerByGuidHook(UObject* Context, FFrame& Stack, void* Ret);
static void K2_GiveItemToPlayerHook(UObject* Context, FFrame& Stack, void* Ret);
static void K2_GiveBuildingResourceHook(UObject* Context, FFrame& Stack, void* Ret);
static void K2_RemoveFortItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret);
static AFortPickup* K2_SpawnPickupInWorldHook(UObject* Context, FFrame& Stack, AFortPickup** Ret);
static AFortPickup* K2_SpawnPickupInWorldWithClassHook(UObject* Context, FFrame& Stack, AFortPickup** Ret);

View File

@@ -378,9 +378,6 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
LTDTables.clear();
LPTables.clear();
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
bool bFoundPlaylistTable = false;
if (CurrentPlaylist)
@@ -410,6 +407,12 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
}
}
}
if (!bFoundPlaylistTable)
{
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
}
}
std::vector<FFortLootTierData*> TierGroupLTDs;

View File

@@ -147,7 +147,7 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController
LOG_INFO(LogDev, "Equipping Gadget: {}", ItemDefinition->GetFullName());
}
/*
#if 0
if (GadgetItemDefinition)
{
static auto AbilitySetOffset = GadgetItemDefinition->GetOffset("AbilitySet");
@@ -228,7 +228,7 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController
Pawn->ServerChoosePart((EFortCustomPartType)i, CharacterParts.at(i));
}
}
*/
#endif
if (auto DecoItemDefinition = Cast<UFortDecoItemDefinition>(ItemDefinition))
{
@@ -489,8 +489,6 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController*
// PlayerController->ServerRestartPlayer();
}
void AFortPlayerController::ServerDropAllItemsHook(AFortPlayerController* PlayerController, UFortItemDefinition* IgnoreItemDef)
{
PlayerController->DropAllItems({ IgnoreItemDef });
@@ -605,6 +603,15 @@ void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFra
WorldInventory->Update();
}
auto GameState = Cast<AFortGameStateAthena>(((AFortGameMode*)GetWorld()->GetGameMode())->GetGameState());
GET_PLAYLIST(GameState);
if (CurrentPlaylist)
{
// CurrentPlaylist->ApplyModifiersToActor(BuildingActor); // seems automatic
}
return ServerCreateBuildingActorOriginal(Context, Stack, Ret);
}
@@ -976,6 +983,8 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0);
LOG_INFO(LogDev, "Removed!");
if (Fortnite_Version < 6) // Spectating
{
LOG_INFO(LogDev, "Starting Spectating!");

View File

@@ -20,7 +20,7 @@ void AFortPlayerControllerAthena::ServerRestartPlayerHook(AFortPlayerControllerA
void AFortPlayerControllerAthena::ServerGiveCreativeItemHook(AFortPlayerControllerAthena* Controller, FFortItemEntry CreativeItem)
{
// Don't worry, the validate has a check if it is a creative enabled mode or not, but we need to add a volume check.
// Don't worry, the validate has a check if it is a creative enabled mode or not, but we need to add a volume check and permission check I think.
auto CreativeItemPtr = &CreativeItem;
auto ItemDefinition = CreativeItemPtr->GetItemDefinition();

View File

@@ -0,0 +1,273 @@
#pragma once
#include "Object.h"
#include "Array.h"
#include "FortAbilitySet.h"
#include "SoftObjectPtr.h"
#include "FortPlayerPawnAthena.h"
#include "GameplayTagContainer.h"
#include "BuildingActor.h"
#include "FortPlayerPawnAthena.h"
struct FGameplayTagRequirements
{
FGameplayTagContainer RequireTags; // 0x0000(0x0020) (Edit, BlueprintVisible, NativeAccessSpecifierPublic)
FGameplayTagContainer IgnoreTags; // 0x0020(0x0020) (Edit, BlueprintVisible, NativeAccessSpecifierPublic)
};
enum class EFortDeliveryInfoBuildingActorSpecification : uint8_t
{
All = 0,
PlayerBuildable = 1,
NonPlayerBuildable = 2,
EFortDeliveryInfoBuildingActorSpecification_MAX = 3
};
struct FFortDeliveryInfoRequirementsFilter
{
bool ShouldApplyToPawns()
{
static auto bApplyToPlayerPawnsOffset = FindOffsetStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "bApplyToPlayerPawns");
static auto bApplyToPlayerPawnsFieldMask = GetFieldMask(FindPropertyStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "bApplyToPlayerPawns"));
return ReadBitfield((PlaceholderBitfield*)(__int64(this) + bApplyToPlayerPawnsOffset), bApplyToPlayerPawnsFieldMask);
}
bool ShouldApplyToBuildingActors()
{
static auto bApplyToBuildingActorsOffset = FindOffsetStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "bApplyToBuildingActors");
static auto bApplyToBuildingActorsFieldMask = GetFieldMask(FindPropertyStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "bApplyToBuildingActors"));
return ReadBitfield((PlaceholderBitfield*)(__int64(this) + bApplyToBuildingActorsOffset), bApplyToBuildingActorsFieldMask);
}
bool ShouldConsiderTeam()
{
static auto bConsiderTeamOffset = FindOffsetStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "bConsiderTeam");
static auto bConsiderTeamFieldMask = GetFieldMask(FindPropertyStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "bConsiderTeam"));
return ReadBitfield((PlaceholderBitfield*)(__int64(this) + bConsiderTeamOffset), bConsiderTeamFieldMask);
}
FGameplayTagRequirements& GetTargetTagRequirements()
{
static auto TargetTagRequirementsOffset = FindOffsetStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "TargetTagRequirements");
return *(FGameplayTagRequirements*)(__int64(this) + TargetTagRequirementsOffset);
}
EFortDeliveryInfoBuildingActorSpecification& GetBuildingActorSpecification()
{
static auto BuildingActorSpecificationOffset = FindOffsetStruct("/Script/FortniteGame.FortDeliveryInfoRequirementsFilter", "BuildingActorSpecification");
return *(EFortDeliveryInfoBuildingActorSpecification*)(__int64(this) + BuildingActorSpecificationOffset);
}
bool DoesActorFollowsRequirements(AActor* Actor)
{
// TODO ADD TEAM CHECK! (We can use UFortKismetLibrary::GetActorTeam)
if (auto BuildingActor = Cast<ABuildingActor>(Actor))
{
if (!ShouldApplyToBuildingActors())
return false;
//if (GetTargetTagRequirements().RequireTags.GameplayTags.Num() > 0 && GetTargetTagRequirements().) // idk todo
if (GetBuildingActorSpecification() == EFortDeliveryInfoBuildingActorSpecification::PlayerBuildable && BuildingActor->IsPlayerBuildable())
return true;
if (GetBuildingActorSpecification() == EFortDeliveryInfoBuildingActorSpecification::NonPlayerBuildable && !BuildingActor->IsPlayerBuildable())
return true;
return GetBuildingActorSpecification() == EFortDeliveryInfoBuildingActorSpecification::All;
}
else if (auto Pawn = Cast<AFortPlayerPawnAthena>(Actor))
{
return ShouldApplyToPawns();
}
else if (auto PlayerState = Cast<AFortPlayerState>(Actor))
{
return ShouldApplyToPawns(); // scuffed
}
return false;
}
};
struct FFortGameplayEffectDeliveryInfo
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortGameplayEffectDeliveryInfo");
return Struct;
}
static int GetStructSize()
{
return GetStruct()->GetPropertiesSize();
}
FFortDeliveryInfoRequirementsFilter* GetDeliveryRequirements()
{
static auto DeliveryRequirementsOffset = FindOffsetStruct("/Script/FortniteGame.FortGameplayEffectDeliveryInfo", "DeliveryRequirements");
return (FFortDeliveryInfoRequirementsFilter*)(__int64(this) + DeliveryRequirementsOffset);
}
TArray<FGameplayEffectApplicationInfo>& GetGameplayEffects()
{
static auto GameplayEffectsOffset = FindOffsetStruct("/Script/FortniteGame.FortGameplayEffectDeliveryInfo", "GameplayEffects");
return *(TArray<FGameplayEffectApplicationInfo>*)(__int64(this) + GameplayEffectsOffset);
}
};
struct FFortAbilitySetDeliveryInfo
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.FortAbilitySetDeliveryInfo");
return Struct;
}
static int GetStructSize()
{
return GetStruct()->GetPropertiesSize();
}
FFortDeliveryInfoRequirementsFilter* GetDeliveryRequirements()
{
static auto DeliveryRequirementsOffset = FindOffsetStruct("/Script/FortniteGame.FortAbilitySetDeliveryInfo", "DeliveryRequirements");
return (FFortDeliveryInfoRequirementsFilter*)(__int64(this) + DeliveryRequirementsOffset);
}
TArray<TSoftObjectPtr<UFortAbilitySet>>& GetAbilitySets()
{
static auto AbilitySetsOffset = FindOffsetStruct("/Script/FortniteGame.FortAbilitySetDeliveryInfo", "AbilitySets");
return *(TArray<TSoftObjectPtr<UFortAbilitySet>>*)(__int64(this) + AbilitySetsOffset);
}
};
class UFortGameplayModifierItemDefinition : public UObject
{
public:
TArray<FFortGameplayEffectDeliveryInfo>& GetPersistentGameplayEffects()
{
static auto PersistentGameplayEffectsOffset = GetOffset("PersistentGameplayEffects");
return this->Get<TArray<FFortGameplayEffectDeliveryInfo>>(PersistentGameplayEffectsOffset);
}
TArray<FFortAbilitySetDeliveryInfo>& GetPersistentAbilitySets()
{
static auto PersistentAbilitySetsOffset = GetOffset("PersistentAbilitySets");
return this->Get<TArray<FFortAbilitySetDeliveryInfo>>(PersistentAbilitySetsOffset);
}
void ApplyModifierToActor(AActor* Actor)
{
if (!Actor)
return;
UAbilitySystemComponent* AbilitySystemComponent = nullptr;
if (auto BuildingActor = Cast<ABuildingActor>(Actor))
{
static auto AbilitySystemComponentOffset = BuildingActor->GetOffset("AbilitySystemComponent");
AbilitySystemComponent = BuildingActor->Get<UAbilitySystemComponent*>(AbilitySystemComponentOffset);
}
else if (auto PlayerState = Cast<AFortPlayerState>(Actor))
{
AbilitySystemComponent = PlayerState->GetAbilitySystemComponent();
}
else if (auto Pawn = Cast<AFortPlayerPawnAthena>(Actor))
{
static auto AbilitySystemComponentOffset = Pawn->GetOffset("AbilitySystemComponent");
AbilitySystemComponent = Pawn->Get<UAbilitySystemComponent*>(AbilitySystemComponentOffset);
}
if (!AbilitySystemComponent)
{
LOG_INFO(LogDev, "Unable to find ASC for {}", Actor->GetName());
return;
}
for (int z = 0; z < this->GetPersistentAbilitySets().Num(); z++)
{
auto& AbilitySetDeliveryInfo = this->GetPersistentAbilitySets().at(z, FFortAbilitySetDeliveryInfo::GetStructSize());
if (!AbilitySetDeliveryInfo.GetDeliveryRequirements()->DoesActorFollowsRequirements(Actor))
continue;
auto& CurrentAbilitySets = AbilitySetDeliveryInfo.GetAbilitySets();
for (int j = 0; j < CurrentAbilitySets.Num(); j++)
{
auto& CurrentAbilitySetSoft = CurrentAbilitySets.at(j);
auto CurrentAbilitySet = CurrentAbilitySetSoft.Get(UFortAbilitySet::StaticClass(), true);
if (!CurrentAbilitySet)
continue;
CurrentAbilitySet->GiveToAbilitySystem(AbilitySystemComponent);
}
}
for (int z = 0; z < this->GetPersistentGameplayEffects().Num(); z++)
{
auto& GameplayEffectDeliveryInfo = this->GetPersistentGameplayEffects().at(z, FFortGameplayEffectDeliveryInfo::GetStructSize());
if (!GameplayEffectDeliveryInfo.GetDeliveryRequirements()->DoesActorFollowsRequirements(Actor))
continue;
auto& CurrentGameplayEffects = GameplayEffectDeliveryInfo.GetGameplayEffects();
for (int j = 0; j < CurrentGameplayEffects.Num(); j++)
{
auto& CurrentGameplayEffectInfo = CurrentGameplayEffects.at(j);
auto& CurrentGameplayEffectSoft = CurrentGameplayEffectInfo.GameplayEffect;
static auto ClassClass = FindObject<UClass>("/Script/CoreUObject.Class");
auto CurrentGameplayEffect = CurrentGameplayEffectSoft.Get(ClassClass, true);
if (!CurrentGameplayEffect)
continue;
LOG_INFO(LogDev, "Giving GameplayEffect {}", CurrentGameplayEffect->GetFullName());
AbilitySystemComponent->ApplyGameplayEffectToSelf(CurrentGameplayEffect, CurrentGameplayEffectInfo.Level);
}
}
}
};
class UFortPlaylist : public UObject
{
public:
TArray<TSoftObjectPtr<UFortGameplayModifierItemDefinition>>& GetModifierList()
{
static auto ModifierListOffset = this->GetOffset("ModifierList");
return this->Get<TArray<TSoftObjectPtr<UFortGameplayModifierItemDefinition>>>(ModifierListOffset);
}
void ApplyModifiersToActor(AActor* Actor)
{
if (!Actor)
return;
static auto ModifierListOffset = this->GetOffset("ModifierList", false);
if (ModifierListOffset == -1)
return;
auto& ModifierList = this->GetModifierList();
static auto FortGameplayModifierItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortGameplayModifierItemDefinition");
for (int i = 0; i < ModifierList.Num(); i++)
{
auto& ModifierSoft = ModifierList.at(i);
auto StrongModifier = ModifierSoft.Get(FortGameplayModifierItemDefinitionClass, true);
if (!StrongModifier)
continue;
StrongModifier->ApplyModifierToActor(Actor);
}
}
};

View File

@@ -2,6 +2,7 @@
#include "reboot.h"
#include "FortPlayerControllerAthena.h"
#include "FortGameModeAthena.h"
UClass* AGameModeBase::GetDefaultPawnClassForController(AController* InController)
{
@@ -60,6 +61,15 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
{
auto NewPlayerAsAthena = Cast<AFortPlayerControllerAthena>(NewPlayer);
auto GameState = ((AFortGameModeAthena*)GameMode)->GetGameStateAthena();
GET_PLAYLIST(GameState);
if (CurrentPlaylist)
{
CurrentPlaylist->ApplyModifiersToActor(NewPlayerAsAthena->GetPlayerState()); // We need to move this!
}
/* if (Fortnite_Version >= 18)
{
static auto StormEffectClass = FindObject<UClass>("/Game/Athena/SafeZone/GE_OutsideSafeZoneDamage.GE_OutsideSafeZoneDamage_C");

View File

@@ -186,6 +186,7 @@
<ClCompile Include="FortGameMode.cpp" />
<ClCompile Include="FortGameModeAthena.cpp" />
<ClCompile Include="FortGameModeZone.cpp" />
<ClCompile Include="FortGameplayAbilityAthena_PeriodicItemGrant.cpp" />
<ClCompile Include="FortGameStateAthena.cpp" />
<ClCompile Include="FortInventory.cpp" />
<ClCompile Include="FortInventory.h" />
@@ -253,6 +254,8 @@
<ClInclude Include="CurveTable.h" />
<ClInclude Include="DataTable.h" />
<ClInclude Include="DataTableFunctionLibrary.h" />
<ClInclude Include="Delegate.h" />
<ClInclude Include="DelegateBase.h" />
<ClInclude Include="die.h" />
<ClInclude Include="Engine.h" />
<ClInclude Include="EngineTypes.h" />
@@ -267,6 +270,7 @@
<ClInclude Include="FortGameModeAthena.h" />
<ClInclude Include="FortGameModePvPBase.h" />
<ClInclude Include="FortGameModeZone.h" />
<ClInclude Include="FortGameplayAbilityAthena_PeriodicItemGrant.h" />
<ClInclude Include="FortGameStateAthena.h" />
<ClInclude Include="FortInventoryInterface.h" />
<ClInclude Include="FortItem.h" />
@@ -282,6 +286,7 @@
<ClInclude Include="FortPlayerPawnAthena.h" />
<ClInclude Include="FortPlayerState.h" />
<ClInclude Include="FortPlayerStateAthena.h" />
<ClInclude Include="FortPlaylist.h" />
<ClInclude Include="FortPlaysetItemDefinition.h" />
<ClInclude Include="FortQuickBars.h" />
<ClInclude Include="FortResourceItemDefinition.h" />
@@ -351,6 +356,7 @@
<ClInclude Include="World.h" />
</ItemGroup>
<ItemGroup>
<None Include="DelegateSignatureImpl.inl" />
<None Include="UnrealEngine.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@@ -182,6 +182,9 @@
<ClCompile Include="DataChannel.cpp">
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
</ClCompile>
<ClCompile Include="FortGameplayAbilityAthena_PeriodicItemGrant.cpp">
<Filter>FortniteGame\Source\FortniteGame\Private\Abilities</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="log.h" />
@@ -542,6 +545,18 @@
<ClInclude Include="vendingmachine.h">
<Filter>Reboot\Public</Filter>
</ClInclude>
<ClInclude Include="FortPlaylist.h">
<Filter>FortniteGame\Source\FortniteGame\Public</Filter>
</ClInclude>
<ClInclude Include="FortGameplayAbilityAthena_PeriodicItemGrant.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Abilities</Filter>
</ClInclude>
<ClInclude Include="Delegate.h">
<Filter>Engine\Source\Runtime\Core\Public\Delegates</Filter>
</ClInclude>
<ClInclude Include="DelegateBase.h">
<Filter>Engine\Source\Runtime\Core\Public\Delegates</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Engine">
@@ -730,10 +745,22 @@
<Filter Include="Engine\Source\Runtime\Core\Public\GenericPlatform">
<UniqueIdentifier>{653d6dbf-b361-41ea-a9b8-b85737412d66}</UniqueIdentifier>
</Filter>
<Filter Include="FortniteGame\Source\FortniteGame\Public\Abilities">
<UniqueIdentifier>{8c77fdeb-c742-4e09-9790-7d32f5240b38}</UniqueIdentifier>
</Filter>
<Filter Include="FortniteGame\Source\FortniteGame\Private\Abilities">
<UniqueIdentifier>{d0555c50-6464-4766-ad1f-2a7ae8b3b5dd}</UniqueIdentifier>
</Filter>
<Filter Include="Engine\Source\Runtime\Core\Public\Delegates">
<UniqueIdentifier>{d01c7b5d-ef89-43ec-b94f-882c419aa74b}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="UnrealEngine.cpp">
<Filter>Engine\Source\Runtime\Engine\Private</Filter>
</None>
<None Include="DelegateSignatureImpl.inl">
<Filter>Engine\Source\Runtime\Core\Public\Delegates</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -29,6 +29,9 @@
#include "InventoryManagementLibrary.h"
#include "FortPlayerPawnAthena.h"
#include "FortGameplayAbilityAthena_PeriodicItemGrant.h"
#include "vendingmachine.h"
enum ENetMode
{
NM_Standalone,
@@ -392,8 +395,15 @@ DWORD WINAPI Main(LPVOID)
if (Addresses::FrameStep) // put all non rpc exec hooks in this scope
{
static auto FortGameplayAbilityAthena_PeriodicItemGrantDefault = FindObject<UFortGameplayAbilityAthena_PeriodicItemGrant>("/Script/FortniteGame.Default__FortGameplayAbilityAthena_PeriodicItemGrant");
Hooking::MinHook::Hook(FortGameplayAbilityAthena_PeriodicItemGrantDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortGameplayAbilityAthena_PeriodicItemGrant.StartItemAwardTimers"),
UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersHook, (PVOID*)&UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersOriginal, false, true);
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_GiveItemToPlayer"),
UFortKismetLibrary::K2_GiveItemToPlayerHook, (PVOID*)&UFortKismetLibrary::K2_GiveItemToPlayerOriginal, false, true);
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_GiveBuildingResource"),
UFortKismetLibrary::K2_GiveBuildingResourceHook, (PVOID*)&UFortKismetLibrary::K2_GiveBuildingResourceOriginal, false, true);
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner"),
UFortKismetLibrary::GiveItemToInventoryOwnerHook, (PVOID*)&UFortKismetLibrary::GiveItemToInventoryOwnerOriginal, false, true);
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_RemoveItemFromPlayerByGuid"),
@@ -476,7 +486,6 @@ DWORD WINAPI Main(LPVOID)
static auto PredictionKeyStruct = FindObject<UStruct>("/Script/GameplayAbilities.PredictionKey");
static auto PredictionKeySize = PredictionKeyStruct->GetPropertiesSize();
if (Globals::bAbilitiesEnabled)
{
int InternalServerTryActivateAbilityIndex = 0;
@@ -746,6 +755,11 @@ DWORD WINAPI Main(LPVOID)
stream << Current << '\n';
}
}
/* else if (GetAsyncKeyState(VK_F12) & 1)
{
FillVendingMachines();
} */
Sleep(1000 / 30);
}

View File

@@ -5,6 +5,7 @@
#include "Object.h"
#include "reboot.h"
#include "GameplayStatics.h"
#include "FortPlaylist.h"
struct Event
{
@@ -256,12 +257,12 @@ static inline std::vector<Event> Events =
)
};
static inline UObject* GetEventPlaylist()
static inline UFortPlaylist* GetEventPlaylist()
{
for (auto& CurrentEvent : Events)
{
if (CurrentEvent.Version == Fortnite_Version)
return FindObject(CurrentEvent.PlaylistName, nullptr, ANY_PACKAGE);
return FindObject<UFortPlaylist>(CurrentEvent.PlaylistName, nullptr, ANY_PACKAGE);
}
return nullptr;

View File

@@ -5,6 +5,5 @@ namespace Globals
extern inline bool bCreative = false;
extern inline bool bGoingToPlayEvent = false;
extern inline bool bNoMCP = true;
extern inline bool bAbilitiesEnabled = true;
extern inline bool bLogProcessEvent = false;
}

View File

@@ -207,6 +207,66 @@ inline void SetBitfield(void* Addr, uint8_t FieldMask, bool NewVal)
*(bool*)Bitfield = NewVal;
}
inline void* FindPropertyStruct(const std::string& StructName, const std::string& MemberName, bool bWarnIfNotFound = true)
{
UObject* Struct = FindObject(StructName);
if (!Struct)
{
if (bWarnIfNotFound)
LOG_WARN(LogFinder, "Unable to find struct4 {}", StructName);
return nullptr;
}
// LOG_INFO(LogFinder, "Struct: {}", Struct->GetFullName());
auto getFNameOfProp = [](void* Property) -> FName*
{
FName* NamePrivate = nullptr;
if (Engine_Version >= 425)
NamePrivate = (FName*)(__int64(Property) + 0x28);
else
NamePrivate = &((UField*)Property)->NamePrivate;
return NamePrivate;
};
for (auto CurrentClass = Struct; CurrentClass; CurrentClass = *(UObject**)(__int64(CurrentClass) + Offsets::SuperStruct))
{
void* Property = *(void**)(__int64(CurrentClass) + Offsets::Children);
if (Property)
{
std::string PropName = getFNameOfProp(Property)->ToString();
if (PropName == MemberName)
{
return Property;
}
while (Property)
{
// LOG_INFO(LogFinder, "PropName: {}", PropName);
if (PropName == MemberName)
{
return Property;
}
Property = Engine_Version >= 425 ? *(void**)(__int64(Property) + 0x20) : ((UField*)Property)->Next;
PropName = Property ? getFNameOfProp(Property)->ToString() : "";
}
}
}
if (bWarnIfNotFound)
LOG_WARN(LogFinder, "Unable to find6 {}", MemberName);
return nullptr;
}
inline int FindOffsetStruct(const std::string& StructName, const std::string& MemberName, bool bWarnIfNotFound = true)
{
UObject* Struct = FindObject(StructName);
@@ -310,4 +370,7 @@ namespace MemberOffsets
static inline float GetMaxTickRateHook() { return 30.f; }
#define VALIDATEOFFSET(offset) if (!offset) LOG_WARN(LogDev, "[{}] Invalid offset", __FUNCTIONNAME__);
#define VALIDATEOFFSET(offset) if (!offset) LOG_WARN(LogDev, "[{}] Invalid offset", __FUNCTIONNAME__);
#define GET_PLAYLIST(GameState) static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false); \
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();

View File

@@ -3,19 +3,143 @@
#include "reboot.h"
#include "BuildingGameplayActor.h"
#include "GameplayStatics.h"
#include "FortLootPackage.h"
using ABuildingItemCollectorActor = ABuildingGameplayActor;
void FillVendingMachine(ABuildingItemCollectorActor* VendingMachine)
struct FCollectorUnitInfo
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.CollectorUnitInfo");
return Struct;
}
static int GetPropertiesSize()
{
return GetStruct()->GetPropertiesSize();
}
TArray<FFortItemEntry>* GetOutputItemEntry()
{
static auto OutputItemEntryOffset = FindOffsetStruct("/Script/FortniteGame.CollectorUnitInfo", "OutputItemEntry");
return (TArray<FFortItemEntry>*)(__int64(this) + OutputItemEntryOffset);
}
UFortWorldItemDefinition*& GetOutputItem()
{
static auto OutputItemOffset = FindOffsetStruct("/Script/FortniteGame.CollectorUnitInfo", "OutputItem");
return *(UFortWorldItemDefinition**)(__int64(this) + OutputItemOffset);
}
};
static inline void FillItemCollector(ABuildingItemCollectorActor* ItemCollector, FName& LootTierGroup, bool bUseInstanceLootValueOverrides, int recursive = 0)
{
if (recursive >= 10)
return;
static auto ItemCollectionsOffset = ItemCollector->GetOffset("ItemCollections");
auto& ItemCollections = ItemCollector->Get<TArray<FCollectorUnitInfo>>(ItemCollectionsOffset);
uint8_t RarityToUse = -1;
for (int ItemCollectorIt = 0; ItemCollectorIt < ItemCollections.Num(); ItemCollectorIt++)
{
auto ItemCollection = ItemCollections.AtPtr(ItemCollectorIt, FCollectorUnitInfo::GetPropertiesSize());
if (ItemCollection->GetOutputItemEntry()->Num() > 0)
{
ItemCollection->GetOutputItemEntry()->Free();
ItemCollection->GetOutputItem() = nullptr;
}
constexpr bool bPrint = false;
std::vector<LootDrop> LootDrops = PickLootDrops(LootTierGroup, bPrint);
int tries = 0;
while (LootDrops.size() == 0)
{
tries++;
LootDrops = PickLootDrops(LootTierGroup, bPrint);
if (tries >= 10)
break;
}
if (LootDrops.size() == 0)
continue;
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
{
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(LootDrops[LootDropIt].ItemDefinition);
if (WorldItemDefinition && IsPrimaryQuickbar(WorldItemDefinition)) // nice
{
static auto RarityOffset = WorldItemDefinition->GetOffset("Rarity");
if (RarityToUse == -1)
RarityToUse = WorldItemDefinition->Get<uint8_t>(RarityOffset);
if (WorldItemDefinition->Get<uint8_t>(RarityOffset) == RarityToUse)
{
bool bItemAlreadyInCollector = false;
for (int ItemCollectorIt2 = 0; ItemCollectorIt2 < ItemCollections.Num(); ItemCollectorIt2++)
{
auto ItemCollection2 = ItemCollections.AtPtr(ItemCollectorIt2, FCollectorUnitInfo::GetPropertiesSize());
if (ItemCollection2->GetOutputItem() == WorldItemDefinition)
{
bItemAlreadyInCollector = true;
break;
}
}
if (bItemAlreadyInCollector)
break;
ItemCollection->GetOutputItem() = WorldItemDefinition;
}
break;
}
}
if (!ItemCollection->GetOutputItem())
{
ItemCollectorIt--; // retry
continue;
}
for (int LootDropIt = 0; LootDropIt < LootDrops.size(); LootDropIt++)
{
auto ItemEntry = FFortItemEntry::MakeItemEntry(LootDrops[LootDropIt].ItemDefinition, LootDrops[LootDropIt].Count, LootDrops[LootDropIt].LoadedAmmo);
ItemCollection->GetOutputItemEntry()->Add(*ItemEntry, FFortItemEntry::GetStructSize());
}
}
static auto bUseInstanceLootValueOverridesOffset = ItemCollector->GetOffset("bUseInstanceLootValueOverrides");
ItemCollector->Get<bool>(bUseInstanceLootValueOverridesOffset) = bUseInstanceLootValueOverrides;
static auto VendingMachineClass = FindObject<UClass>("/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C");
if (ItemCollector->IsA(VendingMachineClass))
{
static auto OverrideVendingMachineRarityOffset = ItemCollector->GetOffset("OverrideVendingMachineRarity");
ItemCollector->Get<uint8_t>(OverrideVendingMachineRarityOffset) = RarityToUse;
}
}
void FillVendingMachines()
static inline void FillVendingMachines()
{
static auto VendingMachineClass = FindObject<UClass>("/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C");
auto AllVendingMachines = UGameplayStatics::GetAllActorsOfClass(GetWorld(), VendingMachineClass);
auto OverrideLootTierGroup = UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaVending"); // ItemCollector->GetLootTierGroupOverride();
for (int i = 0; i < AllVendingMachines.Num(); i++)
{
auto VendingMachine = (ABuildingItemCollectorActor*)AllVendingMachines.at(i);
@@ -23,7 +147,7 @@ void FillVendingMachines()
if (!VendingMachine)
continue;
FillVendingMachine(VendingMachine);
FillItemCollector(VendingMachine, OverrideLootTierGroup, true);
}
AllVendingMachines.Free();