From 5f5d7fb649dcb0a90102869f3fc4e76c0dd3ed0c Mon Sep 17 00:00:00 2001 From: Milxnor Date: Sat, 8 Apr 2023 00:35:54 -0400 Subject: [PATCH] a bit cheat spawnpickup, teams on >s4, bga spawning, gameplayeffects apply from abilityset --- Project Reboot 3.0/AbilitySystemComponent.h | 22 +- .../AbilitySystemComponent_Abilities.cpp | 29 ++- Project Reboot 3.0/BGA.h | 49 ++++ Project Reboot 3.0/FortAbilitySet.h | 64 +++++ Project Reboot 3.0/FortGadgetItemDefinition.h | 25 ++ Project Reboot 3.0/FortGameModeAthena.cpp | 110 +++++---- Project Reboot 3.0/FortInventory.cpp | 28 +++ Project Reboot 3.0/FortInventory.h | 1 - Project Reboot 3.0/FortItemDefinition.h | 6 + Project Reboot 3.0/FortLootPackage.cpp | 43 +++- Project Reboot 3.0/FortPickup.cpp | 9 + Project Reboot 3.0/FortPlayerController.cpp | 226 ++++++++++++++---- Project Reboot 3.0/FortPlayerController.h | 1 + .../FortPlayerControllerAthena.cpp | 2 +- .../FortPlayerControllerAthena.h | 21 +- Project Reboot 3.0/FortWorldItemDefinition.h | 11 + Project Reboot 3.0/Map.h | 6 +- Project Reboot 3.0/NetDriver.cpp | 19 +- Project Reboot 3.0/Project Reboot 3.0.vcxproj | 4 + .../Project Reboot 3.0.vcxproj.filters | 12 + Project Reboot 3.0/Set.h | 6 +- Project Reboot 3.0/SparseArray.h | 57 ++++- Project Reboot 3.0/addresses.cpp | 5 + Project Reboot 3.0/commands.h | 45 +++- Project Reboot 3.0/dllmain.cpp | 2 + Project Reboot 3.0/finder.h | 4 +- Project Reboot 3.0/vendingmachine.h | 30 +++ 27 files changed, 712 insertions(+), 125 deletions(-) create mode 100644 Project Reboot 3.0/BGA.h create mode 100644 Project Reboot 3.0/FortAbilitySet.h create mode 100644 Project Reboot 3.0/FortGadgetItemDefinition.h create mode 100644 Project Reboot 3.0/vendingmachine.h diff --git a/Project Reboot 3.0/AbilitySystemComponent.h b/Project Reboot 3.0/AbilitySystemComponent.h index 318b961..d3d594b 100644 --- a/Project Reboot 3.0/AbilitySystemComponent.h +++ b/Project Reboot 3.0/AbilitySystemComponent.h @@ -17,6 +17,18 @@ using FGameplayEventData = PadHexB0; using FPredictionKey = __int64; // using FGameplayEventData = __int64; +struct FGameplayEffectContextHandle +{ + unsigned char UnknownData00[0x18]; // 0x0000(0x0018) MISSED OFFSET +}; + +struct FActiveGameplayEffectHandle +{ + int Handle; // 0x0000(0x0004) (ZeroConstructor, IsPlainOldData) + bool bPassedFiltersAndWasExecuted; // 0x0004(0x0001) (ZeroConstructor, IsPlainOldData) + unsigned char UnknownData00[0x3]; // 0x0005(0x0003) MISSED OFFSET +}; + class UAbilitySystemComponent : public UObject { public: @@ -32,9 +44,17 @@ public: this->ProcessEvent(fn, &UAbilitySystemComponent_ClientActivateAbilityFailed_Params); } + TArray& GetSpawnedAttributes() + { + static auto SpawnedAttributesOffset = GetOffset("SpawnedAttributes"); + return Get>(SpawnedAttributesOffset); + } + + FActiveGameplayEffectHandle ApplyGameplayEffectToSelf(UClass* GameplayEffectClass, float Level, const FGameplayEffectContextHandle& EffectContext); + // FGameplayEffectContextHandle MakeEffectContext(); void RemoveActiveGameplayEffectBySourceEffect(UClass* GEClass, int StacksToRemove, UAbilitySystemComponent* Instigator); void ConsumeAllReplicatedData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey* AbilityOriginalPredictionKey); - FGameplayAbilitySpecHandle GiveAbilityEasy(UClass* AbilityClass); + FGameplayAbilitySpecHandle GiveAbilityEasy(UClass* AbilityClass, UObject* SourceObject = nullptr); FGameplayAbilitySpec* FindAbilitySpecFromHandle(FGameplayAbilitySpecHandle Handle); static void InternalServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, const FPredictionKey* PredictionKey, const FGameplayEventData* TriggerEventData); diff --git a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp index 771e553..fb9c21b 100644 --- a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp +++ b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp @@ -25,6 +25,31 @@ void LoopSpecs(UAbilitySystemComponent* AbilitySystemComponent, std::function("/Script/GameplayAbilities.AbilitySystemComponent.BP_ApplyGameplayEffectToSelf"); + + struct + { + UClass* GameplayEffectClass; // (Parm, ZeroConstructor, IsPlainOldData) + float Level; // (Parm, ZeroConstructor, IsPlainOldData) + FGameplayEffectContextHandle EffectContext; // (Parm) + FActiveGameplayEffectHandle ReturnValue; // (Parm, OutParm, ReturnParm) + }UAbilitySystemComponent_BP_ApplyGameplayEffectToSelf_Params{GameplayEffectClass, Level, EffectContext}; + + this->ProcessEvent(BP_ApplyGameplayEffectToSelfFn, &UAbilitySystemComponent_BP_ApplyGameplayEffectToSelf_Params); + + return UAbilitySystemComponent_BP_ApplyGameplayEffectToSelf_Params.ReturnValue; +} + +/* FGameplayEffectContextHandle UAbilitySystemComponent::MakeEffectContext() +{ + static auto MakeEffectContextFn = FindObject("/Script/GameplayAbilities.AbilitySystemComponent.MakeEffectContext"); + FGameplayEffectContextHandle ContextHandle; + this->ProcessEvent(MakeEffectContextFn, &ContextHandle); + return ContextHandle; +} */ + void UAbilitySystemComponent::RemoveActiveGameplayEffectBySourceEffect(UClass* GEClass, int StacksToRemove, UAbilitySystemComponent* Instigator) { static auto RemoveActiveGameplayEffectBySourceEffectFn = FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.RemoveActiveGameplayEffectBySourceEffect"); @@ -98,11 +123,11 @@ void UAbilitySystemComponent::InternalServerTryActivateAbilityHook(UAbilitySyste } } -FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass) +FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass, UObject* SourceObject) { // LOG_INFO(LogDev, "Making spec!"); - auto NewSpec = MakeNewSpec(AbilityClass); + auto NewSpec = MakeNewSpec(AbilityClass, SourceObject); // LOG_INFO(LogDev, "Made spec!"); diff --git a/Project Reboot 3.0/BGA.h b/Project Reboot 3.0/BGA.h new file mode 100644 index 0000000..dda3615 --- /dev/null +++ b/Project Reboot 3.0/BGA.h @@ -0,0 +1,49 @@ +#pragma once + +#include "reboot.h" +#include "GameplayStatics.h" +#include "FortLootPackage.h" +#include "FortPickup.h" + +void SpawnBGAs() +{ + static auto BGAConsumableSpawnerClass = FindObject("/Script/FortniteGame.BGAConsumableSpawner"); + + if (!BGAConsumableSpawnerClass) + return; + + auto AllBGAConsumableSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), BGAConsumableSpawnerClass); + + LOG_INFO(LogDev, "AllBGAConsumableSpawners.Num(): ", (int)AllBGAConsumableSpawners.Num()); + + for (int i = 0; i < AllBGAConsumableSpawners.Num(); i++) + { + auto BGAConsumableSpawner = AllBGAConsumableSpawners.at(i); + auto SpawnLocation = BGAConsumableSpawner->GetActorLocation(); + SpawnLocation.Z += 100; + + static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup"); + auto& SpawnLootTierGroup = BGAConsumableSpawner->Get(SpawnLootTierGroupOffset); + + auto LootDrops = PickLootDrops(SpawnLootTierGroup, true); + + for (auto& LootDrop : LootDrops) + { + static auto ConsumableClassOffset = LootDrop.ItemDefinition->GetOffset("ConsumableClass"); + auto& ConsumableClassSoft = LootDrop.ItemDefinition->Get>(ConsumableClassOffset); + + static auto BlueprintGeneratedClassClass = FindObject("/Script/Engine.BlueprintGeneratedClass"); + auto StrongConsumableClass = ConsumableClassSoft.Get(BlueprintGeneratedClassClass, true); + + if (!StrongConsumableClass) + { + LOG_INFO(LogDev, "Invalid consumable class!"); + continue; + } + + auto ConsumableActor = GetWorld()->SpawnActor(StrongConsumableClass, SpawnLocation); + } + } + + AllBGAConsumableSpawners.Free(); +} \ No newline at end of file diff --git a/Project Reboot 3.0/FortAbilitySet.h b/Project Reboot 3.0/FortAbilitySet.h new file mode 100644 index 0000000..571ba40 --- /dev/null +++ b/Project Reboot 3.0/FortAbilitySet.h @@ -0,0 +1,64 @@ +#pragma once + +#include "AbilitySystemComponent.h" +#include "reboot.h" + +struct FGameplayEffectApplicationInfoHard +{ +public: + UClass* GameplayEffect; // 0x0(0x8)(Edit, ZeroConstructor, DisableEditOnInstance, IsPlainOldData, NoDestructor, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic) + float Level; +}; + +class UFortAbilitySet : public UObject +{ +public: + void GiveToAbilitySystem(UAbilitySystemComponent* AbilitySystemComponent, UObject* SourceObject = nullptr) + { + static auto GameplayAbilitiesOffset = this->GetOffset("GameplayAbilities"); + auto GameplayAbilities = this->GetPtr>(GameplayAbilitiesOffset); + + for (int i = 0; i < GameplayAbilities->Num(); i++) + { + UClass* AbilityClass = GameplayAbilities->At(i); + + if (!AbilityClass) + continue; + + LOG_INFO(LogDev, "Giving AbilityClass {}", AbilityClass->GetFullName()); + + AbilitySystemComponent->GiveAbilityEasy(AbilityClass, SourceObject); + } + + static auto GameplayEffectApplicationInfoHardStruct = FindObject("/Script/FortniteGame.GameplayEffectApplicationInfoHard"); + + if (!GameplayEffectApplicationInfoHardStruct) + return; + + static auto GameplayEffectApplicationInfoHardSize = GameplayEffectApplicationInfoHardStruct->GetPropertiesSize(); + static auto GrantedGameplayEffectsOffset = this->GetOffset("GrantedGameplayEffects"); + auto GrantedGameplayEffects = this->GetPtr>(GrantedGameplayEffectsOffset); + + for (int i = 0; i < GrantedGameplayEffects->Num(); i++) + { + auto& EffectToGrant = GrantedGameplayEffects->at(i, GameplayEffectApplicationInfoHardSize); + + if (!EffectToGrant.GameplayEffect) + { + continue; + } + + LOG_INFO(LogDev, "Giving GameplayEffect {}", EffectToGrant.GameplayEffect->GetFullName()); + + // UObject* GameplayEffect = EffectToGrant.GameplayEffect->CreateDefaultObject(); + FGameplayEffectContextHandle EffectContext{}; // AbilitySystemComponent->MakeEffectContext() + AbilitySystemComponent->ApplyGameplayEffectToSelf(EffectToGrant.GameplayEffect, EffectToGrant.Level, EffectContext); + } + } + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.FortAbilitySet"); + return Class; + } +}; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGadgetItemDefinition.h b/Project Reboot 3.0/FortGadgetItemDefinition.h new file mode 100644 index 0000000..3916b2e --- /dev/null +++ b/Project Reboot 3.0/FortGadgetItemDefinition.h @@ -0,0 +1,25 @@ +#pragma once + +#include "FortWorldItemDefinition.h" + +class UFortGadgetItemDefinition : public UFortWorldItemDefinition +{ +public: + + bool ShouldDropAllItemsOnEquip() + { + static auto bDropAllOnEquipOffset = GetOffset("bDropAllOnEquip", false); + + if (bDropAllOnEquipOffset == -1) + return false; + + static auto bDropAllOnEquipFieldMask = GetFieldMask(GetProperty("bDropAllOnEquip")); + return ReadBitfieldValue(bDropAllOnEquipOffset, bDropAllOnEquipFieldMask); + } + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.FortGadgetItemDefinition"); + return Class; + } +}; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 9dfd4c6..aea5cd2 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -9,6 +9,7 @@ #include "FortPlayerPawn.h" #include "FortPickup.h" +#include "FortAbilitySet.h" #include "NetSerialization.h" #include "GameplayStatics.h" #include "KismetStringLibrary.h" @@ -21,6 +22,7 @@ #include "ai.h" #include "Map.h" #include "OnlineReplStructs.h" +#include "BGA.h" enum class EDynamicFoundationEnabledState : uint8_t { @@ -39,10 +41,13 @@ enum class EDynamicFoundationType : uint8_t EDynamicFoundationType_MAX = 4 }; +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"; + static UObject* GetPlaylistToUse() { - auto Playlist = FindObject("/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo"); - // Playlist = FindObject("/BlueCheese/Playlists/Playlist_ShowdownAlt_BlueCheese_Trios.Playlist_ShowdownAlt_BlueCheese_Trios"); + auto Playlist = FindObject(PlaylistName); if (Globals::bGoingToPlayEvent) { @@ -64,23 +69,27 @@ static UObject* GetPlaylistToUse() // SET OVERRIDE PLAYLIST DOWN HERE - // Playlist = FindObject("/Game/Athena/Playlists/Playlist_DefaultDuo.Playlist_DefaultDuo"); - - // Playlist = FindObject("/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground"); - - // Playlist = FindObject("/Game/Athena/Playlists/Carmine/Playlist_Carmine.Playlist_Carmine"); - - // Playlist = FindObject("/MoleGame/Playlists/Playlist_MoleGame.Playlist_MoleGame"); - // Playlist = FindObject("/Game/Athena/Playlists/DADBRO/Playlist_DADBRO_Squads_8.Playlist_DADBRO_Squads_8"); - - // Playlist = FindObject("/Game/Athena/Playlists/Low/Playlist_Low_Solo.Playlist_Low_Solo"); - if (Globals::bCreative) Playlist = FindObject("/Game/Athena/Playlists/Creative/Playlist_PlaygroundV2.Playlist_PlaygroundV2"); return Playlist; } +enum class EFortAthenaPlaylist : uint8_t +{ + AthenaSolo = 0, + AthenaDuo = 1, + AthenaSquad = 2, + EFortAthenaPlaylist_MAX = 3 +}; + +EFortAthenaPlaylist GetPlaylistForOldVersion() +{ + return PlaylistName.contains("Solo") ? EFortAthenaPlaylist::AthenaSolo : PlaylistName.contains("Duo") + ? EFortAthenaPlaylist::AthenaDuo : PlaylistName.contains("Squad") + ? EFortAthenaPlaylist::AthenaSquad : EFortAthenaPlaylist::AthenaSolo; +} + void ShowFoundation(UObject* BuildingFoundation) { if (!BuildingFoundation) @@ -274,8 +283,10 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game LOG_INFO(LogDev, "Presetup!"); GameMode->Get("WarmupRequiredPlayerCount") = 1; - - if (Fortnite_Version >= 3) // idk when they switched off id + + static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false); + + if (CurrentPlaylistDataOffset != -1 || Fortnite_Version >= 6) // idk when they switched off id { auto PlaylistToUse = GetPlaylistToUse(); @@ -294,6 +305,10 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game } } } + else + { + auto OldPlaylist = GetPlaylistForOldVersion(); + } // if (false) { @@ -613,7 +628,7 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false); - auto Playlist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist(); + UObject* Playlist = nullptr; static int CurrentTeamMembers = 0; // bad static int Current = 3; @@ -630,13 +645,30 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint // std::cout << "Dru!\n"; - if (!Playlist) + int MaxSquadSize = 1; + + if (CurrentPlaylistDataOffset != -1 || Fortnite_Version >= 6) { - CurrentTeamMembers = 0; - LOG_INFO(LogTeams, "Player is going on team {} with {} members (No Playlist).", Current, CurrentTeamMembers); - CurrentTeamMembers++; - return Current; - return Current++; + Playlist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist(); + + if (!Playlist) + { + CurrentTeamMembers = 0; + LOG_INFO(LogTeams, "Player is going on team {} with {} members (No Playlist).", Current, CurrentTeamMembers); + CurrentTeamMembers++; + return Current++; + } + + static auto MaxSquadSizeOffset = Playlist->GetOffset("MaxSquadSize"); + MaxSquadSize = Playlist->Get(MaxSquadSizeOffset); + } + else + { + auto OldPlaylist = GetPlaylistForOldVersion(); + MaxSquadSize = OldPlaylist == EFortAthenaPlaylist::AthenaSolo ? 1 + : OldPlaylist == EFortAthenaPlaylist::AthenaDuo ? 2 + : OldPlaylist == EFortAthenaPlaylist::AthenaSquad ? 4 + : 1; } static int NextTeamIndex = 3; // Playlist->Get("DefaultFirstTeam"); // + 1? @@ -652,9 +684,7 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint // std::cout << "CurrentTeamMembers: " << CurrentTeamMembers << '\n'; - static auto MaxSquadSizeOffset = Playlist->GetOffset("MaxSquadSize"); - - if (CurrentTeamMembers >= Playlist->Get(MaxSquadSizeOffset)) + if (CurrentTeamMembers >= MaxSquadSize) { // std::cout << "Moving next team!\n"; @@ -686,6 +716,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena { LastNum69 = AmountOfRestarts; + SpawnBGAs(); + auto SpawnIsland_FloorLoot = FindObject("/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_Warmup.Tiered_Athena_FloorLoot_Warmup_C"); auto BRIsland_FloorLoot = FindObject("/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_01.Tiered_Athena_FloorLoot_01_C"); @@ -699,6 +731,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena EFortPickupSourceTypeFlag SpawnFlag = EFortPickupSourceTypeFlag::Container; + bool bTest = false; bool bPrintWarmup = false; for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++) @@ -729,7 +762,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena } } - CurrentActor->K2_DestroyActor(); + if (!bTest) + CurrentActor->K2_DestroyActor(); } bool bPrint = false; @@ -760,7 +794,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena } } - CurrentActor->K2_DestroyActor(); + if (!bTest) + CurrentActor->K2_DestroyActor(); } // SpawnIsland_FloorLoot_Actors.Free(); @@ -850,29 +885,16 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena if (Globals::bAbilitiesEnabled) { - static auto FortAbilitySetClass = FindObject("/Script/FortniteGame.FortAbilitySet"); - - static auto GameplayAbilitySet = Fortnite_Version >= 8.30 ? // LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") ? - LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer", FortAbilitySetClass) : - LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer", FortAbilitySetClass); + static auto GameplayAbilitySet = (UFortAbilitySet*)(Fortnite_Version >= 8.30 ? // LoadObject(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()) : + LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer", UFortAbilitySet::StaticClass())); LOG_INFO(LogDev, "GameplayAbilitySet {}", __int64(GameplayAbilitySet)); if (GameplayAbilitySet) { LOG_INFO(LogDev, "GameplayAbilitySet Name {}", GameplayAbilitySet->GetName()); - static auto GameplayAbilitiesOffset = GameplayAbilitySet->GetOffset("GameplayAbilities"); - auto GameplayAbilities = GameplayAbilitySet->GetPtr>(GameplayAbilitiesOffset); - - for (int i = 0; i < GameplayAbilities->Num(); i++) - { - UClass* AbilityClass = GameplayAbilities->At(i); - - if (!AbilityClass) - continue; - - PlayerStateAthena->GetAbilitySystemComponent()->GiveAbilityEasy(AbilityClass); - } + GameplayAbilitySet->GiveToAbilitySystem(PlayerStateAthena->GetAbilitySystemComponent()); } } diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index 714fa53..ed23822 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -2,6 +2,9 @@ #include "FortPlayerController.h" #include "FortPickup.h" #include "FortQuickBars.h" +#include "FortPlayerPawnAthena.h" +#include "FortGameStateAthena.h" +#include "FortGameModeAthena.h" UFortItem* CreateItemInstance(AFortPlayerController* PlayerController, UFortItemDefinition* ItemDefinition, int Count) { @@ -29,6 +32,10 @@ std::pair, std::vector> AFortInventory::AddI LoadedAmmo = 0; } + // ShouldForceFocusWhenAdded + + auto WorldItemDefinition = Cast(ItemDefinition); + auto& ItemInstances = GetItemList().GetItemInstances(); auto MaxStackSize = ItemDefinition->GetMaxStackSize(); @@ -159,6 +166,27 @@ std::pair, std::vector> AFortInventory::AddI } } + /* if (FortPlayerController && WorldItemDefinition) // Hmm + { + auto Pawn = Cast(FortPlayerController->GetMyFortPawn()); + auto GameState = Cast(((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameState()); + + if (Pawn) + { + static auto InventorySpecialActorUniqueIDOffset = WorldItemDefinition->GetOffset("InventorySpecialActorUniqueID"); + auto& InventorySpecialActorUniqueID = WorldItemDefinition->Get(InventorySpecialActorUniqueIDOffset); + + static auto ItemSpecialActorIDOffset = Pawn->GetOffset("ItemSpecialActorID"); + Pawn->Get(ItemSpecialActorIDOffset) = InventorySpecialActorUniqueID; + + static auto ItemSpecialActorCategoryIDOffset = Pawn->GetOffset("ItemSpecialActorCategoryID"); + Pawn->Get(ItemSpecialActorCategoryIDOffset) = InventorySpecialActorUniqueID; + + static auto BecameSpecialActorTimeOffset = Pawn->GetOffset("BecameSpecialActorTime"); + Pawn->Get(BecameSpecialActorTimeOffset) = GameState->GetServerWorldTimeSeconds(); + } + } */ + if (bShouldUpdate) *bShouldUpdate = true; } diff --git a/Project Reboot 3.0/FortInventory.h b/Project Reboot 3.0/FortInventory.h index da890e9..143d01d 100644 --- a/Project Reboot 3.0/FortInventory.h +++ b/Project Reboot 3.0/FortInventory.h @@ -9,7 +9,6 @@ #include "reboot.h" - static bool IsPrimaryQuickbar(UFortItemDefinition* ItemDefinition) { /* if (ItemDefinition->IsA(UFortDecoItemDefinition::StaticClass())) diff --git a/Project Reboot 3.0/FortItemDefinition.h b/Project Reboot 3.0/FortItemDefinition.h index 91bd7a8..dca69ac 100644 --- a/Project Reboot 3.0/FortItemDefinition.h +++ b/Project Reboot 3.0/FortItemDefinition.h @@ -18,4 +18,10 @@ public: static auto bAllowMultipleStacksFieldMask = GetFieldMask(GetProperty("bAllowMultipleStacks")); return ReadBitfieldValue(bAllowMultipleStacksOffset, bAllowMultipleStacksFieldMask); } + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.FortItemDefinition"); + return Class; + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index af87095..ebe2cc7 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -163,6 +163,9 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs static std::vector LTDTables; static std::vector LPTables; + static auto DataTableClass = FindObject("/Script/Engine.DataTable"); + static auto CompositeDataTableClass = FindObject("/Script/Engine.CompositeDataTable"); + static bool bHasFoundTables = false; auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist(); @@ -173,9 +176,6 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs bool bFoundPlaylistTable = false; - static auto DataTableClass = FindObject("/Script/Engine.DataTable"); - static auto CompositeDataTableClass = FindObject("/Script/Engine.CompositeDataTable"); - if (CurrentPlaylist) { static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData"); @@ -380,6 +380,36 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs LTDTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")); LPTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")); + + bool bFoundPlaylistTable = false; + + if (CurrentPlaylist) + { + static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData"); + auto& LootTierDataSoft = CurrentPlaylist->Get>(LootTierDataOffset); + + static auto LootPackagesOffset = CurrentPlaylist->GetOffset("LootPackages"); + auto& LootPackagesSoft = CurrentPlaylist->Get>(LootPackagesOffset); + + if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid()) + { + auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite"); + auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite"); + + auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : DataTableClass, true); + auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : DataTableClass, true); + + if (StrongLootTierData && StrongLootPackage) + { + LTDTables.push_back(StrongLootTierData); + LPTables.push_back(StrongLootPackage); + + bFoundPlaylistTable = true; + } + } + } } std::vector TierGroupLTDs; @@ -421,11 +451,6 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs return LootDrops; } - if (bPrint) - { - std::cout << "TierGroupLTDs.size(): " << TierGroupLTDs.size() << '\n'; - } - FFortLootTierData* ChosenRowLootTierData = GetLootTierData(TierGroupLTDs, bPrint); if (!ChosenRowLootTierData) // Should NEVER happen @@ -644,7 +669,7 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs continue; } - auto ItemDef = LootPackageCall->GetItemDefinition().Get(); + auto ItemDef = LootPackageCall->GetItemDefinition().Get(UFortItemDefinition::StaticClass(), true); if (!ItemDef) { diff --git a/Project Reboot 3.0/FortPickup.cpp b/Project Reboot 3.0/FortPickup.cpp index 05420c3..471a149 100644 --- a/Project Reboot 3.0/FortPickup.cpp +++ b/Project Reboot 3.0/FortPickup.cpp @@ -30,6 +30,15 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup"); Pickup->Get(PawnWhoDroppedPickupOffset) = Pawn; + /* static auto SpecialActorIDOffset = Pickup->GetOffset("SpecialActorID"); + + if (auto WorldItemDefinition = Cast(ItemDef)) + { + static auto PickupSpecialActorUniqueIDOffset = WorldItemDefinition->GetOffset("PickupSpecialActorUniqueID"); + auto& PickupSpecialActorUniqueID = WorldItemDefinition->Get(PickupSpecialActorUniqueIDOffset); + Pickup->Get(SpecialActorIDOffset) = PickupSpecialActorUniqueID; + } */ + auto PrimaryPickupItemEntry = Pickup->GetPrimaryPickupItemEntry(); PrimaryPickupItemEntry->GetCount() = Count; diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 6e16860..889e6be 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -17,6 +17,8 @@ #include "FortPlayerPawn.h" #include #include "KismetStringLibrary.h" +#include "FortGadgetItemDefinition.h" +#include "FortAbilitySet.h" void AFortPlayerController::ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot) { @@ -35,6 +37,72 @@ bool AFortPlayerController::DoesBuildFree() return ReadBitfieldValue(bBuildFreeOffset, bBuildFreeFieldMask); } +void AFortPlayerController::DropAllItems(const std::vector& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar, bool bRemoveIfNotDroppable) +{ + auto Pawn = this->GetMyFortPawn(); + + if (!Pawn) + return; + + auto WorldInventory = this->GetWorldInventory(); + + if (!WorldInventory) + return; + + auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances(); + auto Location = Pawn->GetActorLocation(); + + std::vector> GuidAndCountsToRemove; + + for (int i = 0; i < ItemInstances.Num(); i++) + { + auto ItemInstance = ItemInstances.at(i); + + if (!ItemInstance) + continue; + + auto ItemEntry = ItemInstance->GetItemEntry(); + auto WorldItemDefinition = Cast(ItemEntry->GetItemDefinition()); + + if (!WorldItemDefinition || std::find(IgnoreItemDefs.begin(), IgnoreItemDefs.end(), WorldItemDefinition) != IgnoreItemDefs.end()) + continue; + + if (bIgnoreSecondaryQuickbar && !IsPrimaryQuickbar(WorldItemDefinition)) + continue; + + auto ShouldBeDropped = !WorldItemDefinition->CanBeDropped(); + + if (!bRemoveIfNotDroppable && ShouldBeDropped) + continue; + + GuidAndCountsToRemove.push_back({ ItemEntry->GetItemGuid(), ItemEntry->GetCount() }); + + if (!ShouldBeDropped) + continue; + + AFortPickup::SpawnPickup(WorldItemDefinition, Location, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, + ItemEntry->GetLoadedAmmo()); + } + + for (auto& Pair : GuidAndCountsToRemove) + { + WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true); + } + + WorldInventory->Update(); +} + +class Wtf +{ +public: + AFortPlayerController* Controller; + + virtual AFortPlayerController* GetController() + { + return Controller; + } +}; + void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController* PlayerController, FGuid ItemGuid) { if (Engine_Version <= 420) @@ -46,7 +114,7 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController } auto ItemInstance = PlayerController->GetWorldInventory()->FindItemInstance(ItemGuid); - auto Pawn = Cast(PlayerController->GetPawn()); + auto Pawn = Cast(PlayerController->GetPawn()); if (!ItemInstance || !Pawn) return; @@ -56,11 +124,13 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController if (!ItemDefinition) return; - // LOG_INFO(LogDev, "ItemDefinition: {}", ItemDefinition->GetFullName()); + // LOG_INFO(LogDev, "Equipping ItemDefinition: {}", ItemDefinition->GetFullName()); static auto FortGadgetItemDefinitionClass = FindObject("/Script/FortniteGame.FortGadgetItemDefinition"); - if (ItemDefinition->IsA(FortGadgetItemDefinitionClass)) + UFortGadgetItemDefinition* GadgetItemDefinition = nullptr; + + if (GadgetItemDefinition = Cast(ItemDefinition)) { static auto GetWeaponItemDefinition = FindObject("/Script/FortniteGame.FortGadgetItemDefinition.GetWeaponItemDefinition"); @@ -73,11 +143,96 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController static auto GetDecoItemDefinition = FindObject("/Script/FortniteGame.FortGadgetItemDefinition.GetDecoItemDefinition"); ItemDefinition->ProcessEvent(GetDecoItemDefinition, &ItemDefinition); } + + LOG_INFO(LogDev, "Equipping Gadget: {}", ItemDefinition->GetFullName()); } + /* + if (GadgetItemDefinition) + { + static auto AbilitySetOffset = GadgetItemDefinition->GetOffset("AbilitySet"); + auto& AbilitySetSoft = GadgetItemDefinition->Get>(AbilitySetOffset); + + auto StrongAbilitySet = AbilitySetSoft.Get(UFortAbilitySet::StaticClass(), true); + + if (StrongAbilitySet) + { + auto PlayerState = (AFortPlayerStateAthena*)PlayerController->GetPlayerState(); + StrongAbilitySet->GiveToAbilitySystem(PlayerState->GetAbilitySystemComponent()); + } + + static auto AttributeSetOffset = GadgetItemDefinition->GetOffset("AttributeSet"); + auto& AttributeSetSoft = GadgetItemDefinition->Get>(AttributeSetOffset); + + static auto AttributeClass = FindObject("/Script/GameplayAbilities.AttributeSet"); + auto StrongAttributeSet = AttributeSetSoft.Get(AttributeClass, true); + AttributeSetSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + + if (StrongAttributeSet) + { + + } + + if (GadgetItemDefinition->ShouldDropAllItemsOnEquip()) + { + PlayerController->DropAllItems({ GadgetItemDefinition }); + } + + static auto AnimBPOverrideOffset = GadgetItemDefinition->GetOffset("AnimBPOverride"); + UObject* AnimBPOverride = nullptr; + + if (Fortnite_Version >= 6) + { + auto& AnimBPOverrideSoft = GadgetItemDefinition->Get>(AnimBPOverrideOffset); + + static auto AnimInstanceClass = FindObject("/Script/Engine.AnimInstance"); + AnimBPOverride = AnimBPOverrideSoft.Get(AnimInstanceClass, true); + } + else + { + AnimBPOverride = GadgetItemDefinition->Get(AnimBPOverrideOffset); + } + + if (AnimBPOverride) + { + static auto Pawn_AnimBPOverrideOffset = Pawn->GetOffset("AnimBPOverride"); + Pawn->Get(Pawn_AnimBPOverrideOffset) = AnimBPOverride; + } + + static auto FootstepBankOverrideOffset = GadgetItemDefinition->GetOffset("FootstepBankOverride"); + UObject* FootstepBankOverride = nullptr; + + if (Fortnite_Version >= 6) + { + auto& FootstepBankOverrideSoft = GadgetItemDefinition->Get>(FootstepBankOverrideOffset); + + static auto FortFootstepAudioBankClass = FindObject("/Script/FortniteGame.FortFootstepAudioBank"); + FootstepBankOverride = FootstepBankOverrideSoft.Get(FortFootstepAudioBankClass, true); + } + else + { + FootstepBankOverride = GadgetItemDefinition->Get(FootstepBankOverrideOffset); + } + + if (FootstepBankOverride) + { + static auto Pawn_FootstepBankOverrideOffset = Pawn->GetOffset("FootstepBankOverride"); + Pawn->Get(Pawn_FootstepBankOverrideOffset) = FootstepBankOverride; + } + + static auto CharacterPartsOffset = GadgetItemDefinition->GetOffset("CharacterParts"); + auto& CharacterParts = GadgetItemDefinition->Get>(CharacterPartsOffset); + + for (int i = 0; i < CharacterParts.Num(); i++) + { + Pawn->ServerChoosePart((EFortCustomPartType)i, CharacterParts.at(i)); + } + } + */ + if (auto DecoItemDefinition = Cast(ItemDefinition)) { - Pawn->PickUpActor(nullptr, DecoItemDefinition); // todo check ret value? + Pawn->PickUpActor(nullptr, DecoItemDefinition); // todo check ret value? // I checked on 1.7.2 and it only returns true if the new weapon is a FortDecoTool Pawn->GetCurrentWeapon()->GetItemEntryGuid() = ItemGuid; static auto FortDecoTool_ContextTrapStaticClass = FindObject("/Script/FortniteGame.FortDecoTool_ContextTrap"); @@ -220,7 +375,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* auto Vehicle = ReceivingActor; ServerAttemptInteractOriginal(Context, Stack, Ret); - // return; + return; auto Pawn = (AFortPlayerPawn*)PlayerController->GetMyFortPawn(); @@ -270,18 +425,26 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* LOG_INFO(LogDev, "Vehicle eaponb name: {}", VehicleWeaponDef->GetFullName()); auto WorldInventory = PlayerController->GetWorldInventory(); - auto ahh = WorldInventory->AddItem(VehicleWeaponDef, nullptr); - auto newitem = ahh.first[0]; + if (!WorldInventory) + continue; - LOG_INFO(LogDev, "newitem: {}", __int64(newitem)); + { + auto ahh = WorldInventory->AddItem(VehicleWeaponDef, nullptr); - if (!newitem) - return; + auto newitem = ahh.first[0]; - PlayerController->ServerExecuteInventoryItemHook(PlayerController, newitem->GetItemEntry()->GetItemGuid()); + LOG_INFO(LogDev, "newitem: {}", __int64(newitem)); + + if (!newitem) + return; + + WorldInventory->Update(); + + Pawn->EquipWeaponDefinition(VehicleWeaponDef, newitem->GetItemEntry()->GetItemGuid()); + // PlayerController->ServerExecuteInventoryItemHook(PlayerController, newitem->GetItemEntry()->GetItemGuid()); + } - WorldInventory->Update(); break; } @@ -326,44 +489,11 @@ void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController* // PlayerController->ServerRestartPlayer(); } + + void AFortPlayerController::ServerDropAllItemsHook(AFortPlayerController* PlayerController, UFortItemDefinition* IgnoreItemDef) { - auto Pawn = PlayerController->GetMyFortPawn(); - - if (!Pawn) - return; - - auto WorldInventory = PlayerController->GetWorldInventory(); - - if (!WorldInventory) - return; - - auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances(); - auto Location = Pawn->GetActorLocation(); - - for (int i = 0; i < ItemInstances.Num(); i++) - { - auto ItemInstance = ItemInstances.at(i); - - if (!ItemInstance) - continue; - - auto ItemEntry = ItemInstance->GetItemEntry(); - auto WorldItemDefinition = Cast(ItemEntry->GetItemDefinition()); - - if (!WorldItemDefinition) - continue; - - // if (!WorldItemDefinition->ShouldDropOnDeath()) - // continue; - - AFortPickup::SpawnPickup(WorldItemDefinition, Location, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::PlayerElimination, - ItemEntry->GetLoadedAmmo()); // I do playerelimation flag here ik we shouldnt but it makes it go in circle iirc - - WorldInventory->RemoveItem(ItemEntry->GetItemGuid(), nullptr, ItemEntry->GetCount()); - } - - WorldInventory->Update(); + PlayerController->DropAllItems({ IgnoreItemDef }); } void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFrame* Stack, void* Ret) diff --git a/Project Reboot 3.0/FortPlayerController.h b/Project Reboot 3.0/FortPlayerController.h index baf07d9..265a1b3 100644 --- a/Project Reboot 3.0/FortPlayerController.h +++ b/Project Reboot 3.0/FortPlayerController.h @@ -80,6 +80,7 @@ public: } bool DoesBuildFree(); + void DropAllItems(const std::vector& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar = false, bool bRemoveIfNotDroppable = false); static void ServerExecuteInventoryItemHook(AFortPlayerController* PlayerController, FGuid ItemGuid); static void ServerAttemptInteractHook(UObject* Context, FFrame* Stack, void* Ret); diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.cpp b/Project Reboot 3.0/FortPlayerControllerAthena.cpp index a83edd3..028a176 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.cpp +++ b/Project Reboot 3.0/FortPlayerControllerAthena.cpp @@ -100,7 +100,7 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl CopyStruct(PawnAsFort->GetPtr<__int64>(Pawn_CosmeticLoadoutOffset), CosmeticLoadout, FFortAthenaLoadout::GetStructSize()); } */ - ApplyCID(PawnAsFort, CosmeticLoadout->GetCharacter()); + ApplyCID(PawnAsFort, CosmeticLoadout->GetCharacter(), true); auto Backpack = CosmeticLoadout->GetBackpack(); diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.h b/Project Reboot 3.0/FortPlayerControllerAthena.h index 0a001bb..9d728d4 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.h +++ b/Project Reboot 3.0/FortPlayerControllerAthena.h @@ -7,11 +7,14 @@ #include "FortKismetLibrary.h" #include "AthenaMarkerComponent.h" -static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID) +static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID, bool bUseServerChoosePart = false) { if (!CID) return; + if (!Pawn && bUseServerChoosePart) + return; + static auto HeroDefinitionOffset = CID->GetOffset("HeroDefinition"); auto HeroDefinition = CID->Get(HeroDefinitionOffset); @@ -34,6 +37,18 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID) static auto Specialization_CharacterPartsOffset = Specialization->GetOffset("CharacterParts"); auto& CharacterParts = Specialization->Get>>(Specialization_CharacterPartsOffset); + static auto CustomCharacterPartClass = FindObject("/Script/FortniteGame.CustomCharacterPart"); + + /* if (bUseServerChoosePart) + { + for (int z = 0; z < CharacterParts.Num(); z++) + { + Pawn->ServerChoosePart((EFortCustomPartType)z, CharacterParts.at(z).Get(CustomCharacterPartClass, true)); + } + + continue; // hm? + } */ + bool aa; TArray CharacterPartsaa; @@ -41,7 +56,6 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID) for (int z = 0; z < CharacterParts.Num(); z++) { auto& CharacterPartSoft = CharacterParts.at(z); - static auto CustomCharacterPartClass = FindObject("/Script/FortniteGame.CustomCharacterPart"); auto CharacterPart = CharacterPartSoft.Get(CustomCharacterPartClass, true); CharacterPartsaa.Add(CharacterPart); @@ -53,6 +67,9 @@ static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID) CharacterPartsaa.Free(); } } + + static auto HeroTypeOffset = PlayerState->GetOffset("HeroType"); + // PlayerState->Get(HeroTypeOffset) = HeroDefinition; } class AFortPlayerControllerAthena : public AFortPlayerController diff --git a/Project Reboot 3.0/FortWorldItemDefinition.h b/Project Reboot 3.0/FortWorldItemDefinition.h index 7859f18..ca93031 100644 --- a/Project Reboot 3.0/FortWorldItemDefinition.h +++ b/Project Reboot 3.0/FortWorldItemDefinition.h @@ -30,6 +30,17 @@ public: return ReadBitfieldValue(bPersistInInventoryWhenFinalStackEmptyOffset, bPersistInInventoryWhenFinalStackEmptyFieldMask); } + bool ShouldForceFocusWhenAdded() + { + static auto bForceFocusWhenAddedOffset = GetOffset("bForceFocusWhenAdded"); + + if (bForceFocusWhenAddedOffset == -1) + return false; + + static auto bForceFocusWhenAddedFieldMask = GetFieldMask(GetProperty("bForceFocusWhenAdded")); + return ReadBitfieldValue(bForceFocusWhenAddedOffset, bForceFocusWhenAddedFieldMask); + } + static UClass* StaticClass() { static auto Class = FindObject("/Script/FortniteGame.FortWorldItemDefinition"); diff --git a/Project Reboot 3.0/Map.h b/Project Reboot 3.0/Map.h index 46fc26e..1bcdcc2 100644 --- a/Project Reboot 3.0/Map.h +++ b/Project Reboot 3.0/Map.h @@ -117,7 +117,7 @@ public: } FORCEINLINE bool Contains(const KeyType& ElementToLookFor) const { - for (auto Element : *this) + for (auto& Element : *this) { if (Element.Key() == ElementToLookFor) return true; @@ -126,7 +126,7 @@ public: } FORCEINLINE ValueType& GetByKey(const KeyType& Key) { - for (auto Pair : *this) + for (auto& Pair : *this) { if (Pair.Key() == Key) { @@ -142,7 +142,7 @@ public: } FORCEINLINE ValueType GetByKeyNoRef(const KeyType& Key) { - for (auto Pair : *this) + for (auto& Pair : *this) { if (Pair.Key() == Key) { diff --git a/Project Reboot 3.0/NetDriver.cpp b/Project Reboot 3.0/NetDriver.cpp index 1612db2..8dc6659 100644 --- a/Project Reboot 3.0/NetDriver.cpp +++ b/Project Reboot 3.0/NetDriver.cpp @@ -100,6 +100,13 @@ float GetTimeSecondsForWorld(UWorld* World) return *(float*)(__int64(World) + TimeSecondsOffset); } +template +T* AllocForReplication(size_t Size) +{ + return (T*)FMemory::Realloc(nullptr, Size, 0); + return Alloc(Size); +} + void SetChannelActorForDestroy(UActorChannel* ActorChannel, FActorDestructionInfo* DestructInfo) { static auto ConnectionOffset = ActorChannel->GetOffset("Connection"); @@ -115,7 +122,7 @@ void SetChannelActorForDestroy(UActorChannel* ActorChannel, FActorDestructionInf static auto PackageMapOffset = Connection->GetOffset("PackageMap"); auto PackageMap = Connection->Get(PackageMapOffset); - FOutBunch* CloseBunch = Alloc(0x200); + FOutBunch* CloseBunch = AllocForReplication(0x200); if (!CloseBunch) return; @@ -124,20 +131,17 @@ void SetChannelActorForDestroy(UActorChannel* ActorChannel, FActorDestructionInf FPacketIdRange Range(0); FPacketIdRange* (*SendBunchOriginal)(UActorChannel * Channel, FPacketIdRange * OutRange, FOutBunch * Bunch, bool Merge) = decltype(SendBunchOriginal)(ActorChannel->VFTable[0x288 / 8]); bool (*UPackageMap_WriteObjectOriginal)(UObject * PackageMap, FOutBunch * Ar, UObject * InOuter, FNetworkGUID NetGUID, FString ObjectName) = decltype(UPackageMap_WriteObjectOriginal)(PackageMap->VFTable[0x238 / 8]); - static void (*FArchiveDeconstructor)(FOutBunch * Ar) = decltype(FArchiveDeconstructor)(__int64(GetModuleHandleW(0)) + 0xC36500); + static void (*FArchiveDeconstructor)(FOutBunch* Ar) = decltype(FArchiveDeconstructor)(__int64(GetModuleHandleW(0)) + 0xC36500); FOutBunchConstructor(CloseBunch, ActorChannel, true); // we could set bDormant but it's set by default to 0. SetBitfield((PlaceholderBitfield*)(__int64(CloseBunch) + 0x30), 4, true); // bReliable - /* LOG_INFO(LogDev, "UPackageMap_WriteObjectOriginal: 0x{:x}", __int64(UPackageMap_WriteObjectOriginal) - __int64(GetModuleHandleW(0))); + LOG_INFO(LogDev, "UPackageMap_WriteObjectOriginal: 0x{:x}", __int64(UPackageMap_WriteObjectOriginal) - __int64(GetModuleHandleW(0))); LOG_INFO(LogDev, "DestructInfo->PathName: {} Num: {} Max: {} Data: {}", DestructInfo->PathName.ToString(), DestructInfo->PathName.Data.Num(), DestructInfo->PathName.Data.ArrayMax, __int64(DestructInfo->PathName.Data.Data)); // LOG_INFO(LogDev, "DestructInfo->ObjOuter: {}", DestructInfo->ObjOuter.Get()->IsValidLowLevel() ? DestructInfo->ObjOuter.Get()->GetFullName() : "BadRead"); - if (DestructInfo->PathName.ToString() == "???") - return; */ - UPackageMap_WriteObjectOriginal(PackageMap, CloseBunch, DestructInfo->ObjOuter.Get(), DestructInfo->NetGUID, DestructInfo->PathName); SendBunchOriginal(ActorChannel, &Range, CloseBunch, false); @@ -683,7 +687,7 @@ int32 UNetDriver::ServerReplicateActors_PrioritizeActors(UNetConnection* Connect // Add in deleted actors - /* for (auto& CurrentGuid : Connection_DestroyedStartupOrDormantActors) + /*for (auto& CurrentGuid : Connection_DestroyedStartupOrDormantActors) { FActorDestructionInfo& DInfo = GetDriverDestroyedStartupOrDormantActors(this).Find(CurrentGuid); OutPriorityList[FinalSortedCount] = FActorPriority(Connection, &DInfo, ConnectionViewers); @@ -753,6 +757,7 @@ int32 UNetDriver::ServerReplicateActors_ProcessPrioritizedActors(UNetConnection* SetChannelActorForDestroy(Channel, PriorityActors[j]->DestructionInfo); // Send a close bunch on the new channel Connection_DestroyedStartupOrDormantActors.Remove(PriorityActors[j]->DestructionInfo->NetGUID); // Remove from connections to-be-destroyed list (close bunch of reliable, so it will make it there) + LOG_INFO(LogDev, "Finished!"); } continue; diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj b/Project Reboot 3.0/Project Reboot 3.0.vcxproj index e84d1c1..0130d3f 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -236,6 +236,7 @@ + @@ -257,9 +258,11 @@ + + @@ -342,6 +345,7 @@ + diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters index 19062c5..79e5888 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -530,6 +530,18 @@ Engine\Source\Runtime\Core\Public\Math + + FortniteGame\Source\FortniteGame\Public\Items + + + FortniteGame\Source\FortniteGame\Public + + + Reboot\Public + + + Reboot\Public + diff --git a/Project Reboot 3.0/Set.h b/Project Reboot 3.0/Set.h index fcceb91..973599f 100644 --- a/Project Reboot 3.0/Set.h +++ b/Project Reboot 3.0/Set.h @@ -190,11 +190,13 @@ public: } FORCEINLINE bool Remove(const SetType& ElementToRemove) { - return Elements.RemoveAt(Find(ElementToRemove)); + Elements.RemoveAt(Find(ElementToRemove)); + return true; } FORCEINLINE bool Remove(int Index) { - return Elements.RemoveAt(Index); + Elements.RemoveAt(Index); + return true; } }; diff --git a/Project Reboot 3.0/SparseArray.h b/Project Reboot 3.0/SparseArray.h index 3f67759..4698b75 100644 --- a/Project Reboot 3.0/SparseArray.h +++ b/Project Reboot 3.0/SparseArray.h @@ -4,6 +4,8 @@ #include "BitArray.h" #include "log.h" +#define INDEX_NONE -1 + template union TSparseArrayElementOrListLink { @@ -151,6 +153,18 @@ public: { return Data; } + FSparseArrayElement& GetData(int32 Index) + { + return *(FSparseArrayElement*)&Data.at(Index).ElementData; + // return ((FSparseArrayElement*)Data.Data)[Index]; + } + + /** Accessor for the element or free list data. */ + const FSparseArrayElement& GetData(int32 Index) const + { + return *(const FSparseArrayElement*)&Data.at(Index).ElementData; + // return ((FSparseArrayElement*)Data.Data)[Index]; + } FORCEINLINE const TBitArray& GetAllocationFlags() const { return AllocationFlags; @@ -160,6 +174,44 @@ public: return AllocationFlags.IsSet(IndexToCheck); } + void RemoveAt(int32 Index, int32 Count = 1) + { + /* if (!TIsTriviallyDestructible::Value) + { + for (int32 It = Index, ItCount = Count; ItCount; ++It, --ItCount) + { + ((ElementType&)GetData(It).ElementData).~ElementType(); + } + } */ + + RemoveAtUninitialized(Index, Count); + } + + /** Removes Count elements from the array, starting from Index, without destructing them. */ + void RemoveAtUninitialized(int32 Index, int32 Count = 1) + { + for (; Count; --Count) + { + // check(AllocationFlags[Index]); + + // Mark the element as free and add it to the free element list. + if (NumFreeIndices) + { + GetData(FirstFreeIndex).PrevFreeIndex = Index; + } + auto& IndexData = GetData(Index); + IndexData.PrevFreeIndex = -1; + IndexData.NextFreeIndex = NumFreeIndices > 0 ? FirstFreeIndex : INDEX_NONE; + FirstFreeIndex = Index; + ++NumFreeIndices; + AllocationFlags.Set(Index, false); + // AllocationFlags[Index] = false; + + ++Index; + } + } + + /* FORCEINLINE bool RemoveAt(const int32 IndexToRemove) { LOG_INFO(LogDev, "IndexToRemove: {}", IndexToRemove); @@ -173,12 +225,12 @@ public: LOG_INFO(LogDev, "NumFreeIndices: {}", NumFreeIndices); - /* if (NumFreeIndices == 0) + if (NumFreeIndices == 0) { FirstFreeIndex = IndexToRemove; Data.at(IndexToRemove) = { -1, -1 }; } - else */ + else { for (auto It = AllocationFlags.begin(); It != AllocationFlags.end(); ++It) { @@ -204,4 +256,5 @@ public: } return false; } + */ }; \ No newline at end of file diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index d95fe8e..831830c 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -413,6 +413,11 @@ std::vector Addresses::GetFunctionsToNull() // toNull.push_back(Memcury::Scanner::FindPattern("E8 ? ? ? ? EB 26 40 38 3D ? ? ? ?").RelativeOffset(1).Get()); // collectgarbage } + if (Fortnite_Version == 4.1) + { + toNull.push_back(Memcury::Scanner::FindPattern("4C 8B DC 55 49 8D AB ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 49 89 5B 10 48 8D 05 ? ? ? ? 48 8B 1D ? ? ? ? 49 89 73 18 33 F6 40").Get()); // grassupdate + } + if (Engine_Version == 421) { toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 48 89 70 10 57 48 81 EC ? ? ? ? 48 8B BA ? ? ? ? 48 8B DA 0F 29").Get()); // Pawn Overlap diff --git a/Project Reboot 3.0/commands.h b/Project Reboot 3.0/commands.h index 7e58104..3583d69 100644 --- a/Project Reboot 3.0/commands.h +++ b/Project Reboot 3.0/commands.h @@ -194,6 +194,47 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) SendMessageToConsole(PlayerController, L"Granted item!"); } + else if (Command == "spawnpickup") + { + if (NumArgs < 1) + { + SendMessageToConsole(PlayerController, L"Please provide a WID!"); + return; + } + + auto Pawn = PlayerController->GetMyFortPawn(); + + if (!Pawn) + { + SendMessageToConsole(PlayerController, L"No pawn!"); + return; + } + + auto& weaponName = Arguments[1]; + int count = 1; + + try + { + if (NumArgs >= 2) + count = std::stoi(Arguments[2]); + } + catch (...) + { + } + + // LOG_INFO(LogDev, "weaponName: {}", weaponName); + + auto WID = Cast(FindObject(weaponName, nullptr, ANY_PACKAGE)); + + if (!WID) + { + SendMessageToConsole(PlayerController, L"Invalid WID!"); + return; + } + + auto Location = Pawn->GetActorLocation(); + AFortPickup::SpawnPickup(WID, Location, count); + } else if (Command == "listplayers") { std::string PlayerNames; @@ -284,7 +325,7 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) Pawn->SetCanBeDamaged(!Pawn->CanBeDamaged()); SendMessageToConsole(PlayerController, std::wstring(L"God set to " + std::to_wstring(!(bool)Pawn->CanBeDamaged())).c_str()); - } + } */ else if (Command == "applycid") { auto PlayerState = Cast(ReceivingController->GetPlayerState()); @@ -309,7 +350,7 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) ApplyCID(Pawn, CIDDef); SendMessageToConsole(PlayerController, L"Applied CID!"); - } */ + } else if (Command == "summon") { if (Arguments.size() <= 1) diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 643309f..a507142 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -159,6 +159,8 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook((PVOID)Addresses::KickPlayer, (PVOID)AGameSession::KickPlayerHook, (PVOID*)&AGameSession::KickPlayerOriginal); + LOG_INFO(LogDev, "Built on {} {}", __DATE__, __TIME__); + LOG_INFO(LogDev, "[bNoMCP] {}", Globals::bNoMCP); LOG_INFO(LogDev, "Size: 0x{:x}", sizeof(TMap)); Hooking::MinHook::Hook((PVOID)Addresses::ActorGetNetMode, (PVOID)GetNetModeHook2, nullptr); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 2acb7c8..eb93de8 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -844,6 +844,8 @@ static inline uint64 FindGIsServer() } } */ + if (Fortnite_Version == 4.1) + return __int64(GetModuleHandleW(0)) + 0x4BF6F18; if (Fortnite_Version == 10.40) return __int64(GetModuleHandleW(0)) + 0x637925C; if (Fortnite_Version == 12.41) @@ -1148,7 +1150,7 @@ static inline uint64 FindPickTeam() if (!Addr.Get()) Addr = Memcury::Scanner::FindStringRef(L"PickTeam for [%s] used beacon value [%s]"); // i don't even know what version this is - return FindBytes(Addr, Fortnite_Version <= 2.5 ? std::vector{ 0x48, 0x89, 0x6C } : std::vector{ 0x40, 0x55 }, 1000, 0, true); + return FindBytes(Addr, Fortnite_Version <= 4.1 ? std::vector{ 0x48, 0x89, 0x6C } : std::vector{ 0x40, 0x55 }, 1000, 0, true); } static inline uint64 FindInternalTryActivateAbility() diff --git a/Project Reboot 3.0/vendingmachine.h b/Project Reboot 3.0/vendingmachine.h new file mode 100644 index 0000000..742cc57 --- /dev/null +++ b/Project Reboot 3.0/vendingmachine.h @@ -0,0 +1,30 @@ +#pragma once + +#include "reboot.h" +#include "BuildingGameplayActor.h" +#include "GameplayStatics.h" + +using ABuildingItemCollectorActor = ABuildingGameplayActor; + +void FillVendingMachine(ABuildingItemCollectorActor* VendingMachine) +{ + +} + +void FillVendingMachines() +{ + static auto VendingMachineClass = FindObject("/Game/Athena/Items/Gameplay/VendingMachine/B_Athena_VendingMachine.B_Athena_VendingMachine_C"); + auto AllVendingMachines = UGameplayStatics::GetAllActorsOfClass(GetWorld(), VendingMachineClass); + + for (int i = 0; i < AllVendingMachines.Num(); i++) + { + auto VendingMachine = (ABuildingItemCollectorActor*)AllVendingMachines.at(i); + + if (!VendingMachine) + continue; + + FillVendingMachine(VendingMachine); + } + + AllVendingMachines.Free(); +} \ No newline at end of file