diff --git a/Project Reboot 3.0/Array.h b/Project Reboot 3.0/Array.h index 75d77d8..104d5b0 100644 --- a/Project Reboot 3.0/Array.h +++ b/Project Reboot 3.0/Array.h @@ -82,6 +82,25 @@ public: return Emplace(New, Size); } */ + int AddPtr(InElementType* New, size_t Size = sizeof(InElementType)) + { + // LOG_INFO(LogDev, "ArrayMax: {}", ArrayMax); + + if ((ArrayNum + 1) > ArrayMax) + { + Reserve(1, Size); + } + + if (Data) + { + memcpy_s((InElementType*)(__int64(Data) + (ArrayNum * Size)), Size, (void*)New, Size); + ++ArrayNum; + return ArrayNum; // - 1; + } + + return -1; + }; + int Add(const InElementType& New, size_t Size = sizeof(InElementType)) { // LOG_INFO(LogDev, "ArrayMax: {}", ArrayMax); diff --git a/Project Reboot 3.0/FortAthenaCreativePortal.cpp b/Project Reboot 3.0/FortAthenaCreativePortal.cpp index 73ecc82..f307558 100644 --- a/Project Reboot 3.0/FortAthenaCreativePortal.cpp +++ b/Project Reboot 3.0/FortAthenaCreativePortal.cpp @@ -13,8 +13,8 @@ void AFortAthenaCreativePortal::TeleportPlayerToLinkedVolumeHook(UObject* Contex AFortPlayerPawn* PlayerPawn = nullptr; bool bUseSpawnTags; - Stack.Step(Stack.Object, &PlayerPawn); - Stack.Step(Stack.Object, &bUseSpawnTags); + Stack.StepCompiledIn(&PlayerPawn); + Stack.StepCompiledIn(&bUseSpawnTags); LOG_INFO(LogDev, "PlayerPawn: {}", __int64(PlayerPawn)); @@ -45,8 +45,8 @@ void AFortAthenaCreativePortal::TeleportPlayerHook(UObject* Context, FFrame& Sta AFortPlayerPawn* PlayerPawn = nullptr; FRotator TeleportRotation; - Stack.Step(Stack.Object, &PlayerPawn); - Stack.Step(Stack.Object, &TeleportRotation); + Stack.StepCompiledIn(&PlayerPawn); + Stack.StepCompiledIn(&TeleportRotation); LOG_INFO(LogDev, "PlayerPawn: {}", __int64(PlayerPawn)); diff --git a/Project Reboot 3.0/FortAthenaSupplyDrop.cpp b/Project Reboot 3.0/FortAthenaSupplyDrop.cpp index 1a680d6..1f5aee2 100644 --- a/Project Reboot 3.0/FortAthenaSupplyDrop.cpp +++ b/Project Reboot 3.0/FortAthenaSupplyDrop.cpp @@ -8,11 +8,11 @@ AFortPickup* AFortAthenaSupplyDrop::SpawnPickupHook(UObject* Context, FFrame& St FVector Position; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) FVector Direction; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - Stack.Step(Stack.Object, &ItemDefinition); - Stack.Step(Stack.Object, &NumberToSpawn); - Stack.Step(Stack.Object, &TriggeringPawn); - Stack.Step(Stack.Object, &Position); - Stack.Step(Stack.Object, &Direction); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&NumberToSpawn); + Stack.StepCompiledIn(&TriggeringPawn); + Stack.StepCompiledIn(&Position); + Stack.StepCompiledIn(&Direction); SpawnPickupOriginal(Context, Stack, Ret); diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 14f17dc..d71cee7 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -20,6 +20,7 @@ #include "reboot.h" #include "ai.h" #include "Map.h" +#include "OnlineReplStructs.h" enum class EDynamicFoundationEnabledState : uint8_t { @@ -238,7 +239,9 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game } else { - // SetPlaylist(PlaylistToUse, true); + if (Fortnite_Version >= 4) + SetPlaylist(PlaylistToUse, true); + LOG_INFO(LogDev, "Set playlist!"); } @@ -734,6 +737,9 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena // idk if this is needed + double (*sub_7FF753D401D0)(UObject* a1) = decltype(sub_7FF753D401D0)(__int64(GetModuleHandleW(0)) + 0x1A001D0); + LOG_INFO(LogDev, "TIme: {}", sub_7FF753D401D0(GetWorld())); + static auto bHasServerFinishedLoadingOffset = NewPlayer->GetOffset("bHasServerFinishedLoading"); NewPlayer->Get(bHasServerFinishedLoadingOffset) = true; @@ -754,7 +760,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena { static int CurrentPlayerId = 1; // static auto PlayerIdOffset = PlayerStateAthena->GetOffset("PlayerId"); // Unable to find tf - PlayerStateAthena->GetWorldPlayerId() = ++CurrentPlayerId; // PlayerStateAthena->Get(PlayerIdOffset); // + PlayerStateAthena->GetWorldPlayerId() = PlayerStateAthena->GetPlayerID(); // ++CurrentPlayerId; // PlayerStateAthena->Get(PlayerIdOffset); // } if (Globals::bAbilitiesEnabled) @@ -795,10 +801,12 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena unsigned char ahh[0x0028]; }; - FUniqueNetIdReplExperimental Bugha{}; - auto& PlayerStateUniqueId = PlayerStateAthena->Get("UniqueId"); + /* FUniqueNetIdReplExperimental Bugha{}; */ + static auto UniqueIdOffset = PlayerStateAthena->GetOffset("UniqueId"); + auto PlayerStateUniqueId = PlayerStateAthena->GetPtr(UniqueIdOffset); { + LOG_INFO(LogDev, "bruh"); static auto GameMemberInfoArrayOffset = GameState->GetOffset("GameMemberInfoArray", false); // if (false) @@ -816,7 +824,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena static auto GameMemberInfoStructSize = 0x38; // LOG_INFO(LogDev, "Compare: 0x{:x} 0x{:x}", GameMemberInfoStructSize, sizeof(FGameMemberInfo)); - auto GameMemberInfo = Alloc(GameMemberInfoStructSize); + auto GameMemberInfo = Alloc<__int64>(GameMemberInfoStructSize); ((FFastArraySerializerItem*)GameMemberInfo)->MostRecentArrayReplicationKey = -1; ((FFastArraySerializerItem*)GameMemberInfo)->ReplicationID = -1; @@ -827,25 +835,28 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena static auto GameMemberInfo_SquadIdOffset = 0x000C; static auto GameMemberInfo_TeamIndexOffset = 0x000D; static auto GameMemberInfo_MemberUniqueIdOffset = 0x0010; - static auto UniqueIdSize = 0x0028; + static auto UniqueIdSize = FUniqueNetIdRepl::GetSizeOfStruct(); *(uint8*)(__int64(GameMemberInfo) + GameMemberInfo_SquadIdOffset) = PlayerStateAthena->GetSquadId(); *(uint8*)(__int64(GameMemberInfo) + GameMemberInfo_TeamIndexOffset) = PlayerStateAthena->GetTeamIndex(); - CopyStruct((void*)(__int64(GameMemberInfo) + GameMemberInfo_MemberUniqueIdOffset), PlayerStateAthena->Get("UniqueId"), UniqueIdSize); - + CopyStruct((void*)(__int64(GameMemberInfo) + GameMemberInfo_MemberUniqueIdOffset), PlayerStateUniqueId, UniqueIdSize); } else { - GameMemberInfo->SquadId = PlayerStateAthena->GetSquadId(); - GameMemberInfo->TeamIndex = PlayerStateAthena->GetTeamIndex(); - GameMemberInfo->MemberUniqueId = PlayerStateUniqueId; + ((FGameMemberInfo*)GameMemberInfo)->SquadId = PlayerStateAthena->GetSquadId(); + ((FGameMemberInfo*)GameMemberInfo)->TeamIndex = PlayerStateAthena->GetTeamIndex(); + // GameMemberInfo->MemberUniqueId = PlayerStateUniqueId; + CopyStruct(&((FGameMemberInfo*)GameMemberInfo)->MemberUniqueId, PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct()); } static auto GameMemberInfoArray_MembersOffset = FindOffsetStruct("/Script/FortniteGame.GameMemberInfoArray", "Members"); auto GameMemberInfoArray = GameState->GetPtr(GameMemberInfoArrayOffset); - ((TArray*)(__int64(GameMemberInfoArray) + GameMemberInfoArray_MembersOffset))->Add(*GameMemberInfo, GameMemberInfoStructSize); + ((TArray*)(__int64(GameMemberInfoArray) + GameMemberInfoArray_MembersOffset))->AddPtr( + (FGameMemberInfo*)GameMemberInfo, GameMemberInfoStructSize + ); + GameMemberInfoArray->MarkArrayDirty(); } } @@ -901,7 +912,10 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena auto OwningPlayer = Portal->GetOwningPlayer(); if (OwningPlayer != nullptr) - *(FUniqueNetIdReplExperimental*)OwningPlayer = PlayerStateUniqueId; + { + CopyStruct(OwningPlayer, PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct()); + // *(FUniqueNetIdReplExperimental*)OwningPlayer = PlayerStateUniqueId; + } Portal->GetPortalOpen() = true; @@ -909,8 +923,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena if (PlayersReadyOffset != 0) { - auto& PlayersReady = Portal->Get>(PlayersReadyOffset); - PlayersReady.Add(PlayerStateUniqueId); // im not even sure what this is + auto& PlayersReady = Portal->Get>(PlayersReadyOffset); + PlayersReady.AddPtr(PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct()); // im not even sure what this is for } static auto bUserInitiatedLoadOffset = Portal->GetOffset("bUserInitiatedLoad", false); @@ -941,7 +955,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena if (LevelSaveComponent) { static auto AccountIdOfOwnerOffset = LevelSaveComponent->GetOffset("AccountIdOfOwner"); - LevelSaveComponent->Get(AccountIdOfOwnerOffset) = PlayerStateUniqueId; + CopyStruct(LevelSaveComponent->GetPtr(AccountIdOfOwnerOffset), PlayerStateUniqueId, FUniqueNetIdRepl::GetSizeOfStruct()); + // LevelSaveComponent->Get(AccountIdOfOwnerOffset) = PlayerStateUniqueId; static auto bIsLoadedOffset = LevelSaveComponent->GetOffset("bIsLoaded"); LevelSaveComponent->Get(bIsLoadedOffset) = true; diff --git a/Project Reboot 3.0/FortInventory.h b/Project Reboot 3.0/FortInventory.h index e353e85..391a8e3 100644 --- a/Project Reboot 3.0/FortInventory.h +++ b/Project Reboot 3.0/FortInventory.h @@ -45,6 +45,31 @@ enum class EFortInventoryType : unsigned char MAX = 3, }; +struct FItemAndCount +{ +private: + int Count; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + unsigned char UnknownData00[0x4]; // 0x0004(0x0004) MISSED OFFSET + UFortItemDefinition* Item; // 0x0008(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) +public: + int& GetCount() + { + return Count; + } + + UFortItemDefinition*& GetItem() + { + return Item; + } +}; + +struct FItemGuidAndCount +{ +public: + int32 Count; // 0x0(0x4)(Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + struct FGuid ItemGuid; // 0x4(0x10)(Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) +}; + struct FFortItemList : public FFastArraySerializer { TArray& GetItemInstances() diff --git a/Project Reboot 3.0/FortItem.h b/Project Reboot 3.0/FortItem.h index 93f6a71..f4c0bf7 100644 --- a/Project Reboot 3.0/FortItem.h +++ b/Project Reboot 3.0/FortItem.h @@ -30,6 +30,18 @@ struct FFortItemEntry : FFastArraySerializerItem static auto LoadedAmmoOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "LoadedAmmo"); return *(int*)(__int64(this) + LoadedAmmoOffset); } + + static UStruct* GetStruct() + { + static auto Struct = FindObject("/Script/FortniteGame.FortItemEntry"); + return Struct; + } + + static int GetStructSize() + { + static auto StructSize = GetStruct()->GetPropertiesSize(); + return StructSize; + } }; class UFortItem : public UObject diff --git a/Project Reboot 3.0/FortKismetLibrary.cpp b/Project Reboot 3.0/FortKismetLibrary.cpp index 518d817..df1c584 100644 --- a/Project Reboot 3.0/FortKismetLibrary.cpp +++ b/Project Reboot 3.0/FortKismetLibrary.cpp @@ -1,6 +1,7 @@ #include "FortKismetLibrary.h" #include "ScriptInterface.h" #include "FortPickup.h" +#include "FortLootPackage.h" UFortResourceItemDefinition* UFortKismetLibrary::K2_GetResourceItemDefinition(EFortResourceType ResourceType) { @@ -64,19 +65,50 @@ void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, co } } +void UFortKismetLibrary::K2_SpawnPickupInWorldWithLootTierHook(UObject* Context, FFrame& Stack, void* Ret) +{ + LOG_INFO(LogDev, __FUNCTION__); + + return K2_SpawnPickupInWorldWithLootTierOriginal(Context, Stack, Ret); +} + +void UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHook(UObject* Context, FFrame& Stack, void* Ret) +{ + UObject* WorldContextObject; + UFortWeaponItemDefinition* WeaponItemDefinition; + FGameplayTagContainer SourceTags; + FVector Location; + EFortPickupSourceTypeFlag SourceTypeFlag; + EFortPickupSpawnSource SpawnSource; + + Stack.StepCompiledIn(&WorldContextObject); + Stack.StepCompiledIn(&WeaponItemDefinition); + Stack.StepCompiledIn(&SourceTags); + Stack.StepCompiledIn(&Location); + Stack.StepCompiledIn(&SourceTypeFlag); + Stack.StepCompiledIn(&SpawnSource); + + LOG_INFO(LogDev, __FUNCTION__); + + return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret); + + int Count = 1; + + auto AmmoDefinition = WeaponItemDefinition->GetAmmoData(); + + if (!AmmoDefinition) + return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret); + + auto AmmoPickup = AFortPickup::SpawnPickup(AmmoDefinition, Location, Count, SourceTypeFlag, SpawnSource); + + return CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal(Context, Stack, Ret); +} + void UFortKismetLibrary::GiveItemToInventoryOwnerHook(UObject* Context, FFrame& Stack, void* Ret) { - auto Params = /*(UFortKismetLibrary_GiveItemToInventoryOwner_Params*)*/Stack.Locals; - - static auto InventoryOwnerOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "InventoryOwner"); - static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "ItemDefinition"); - static auto NumberToGiveOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "NumberToGive"); - static auto bNotifyPlayerOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "bNotifyPlayer"); static auto ItemLevelOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "ItemLevel", false); static auto PickupInstigatorHandleOffset = FindOffsetStruct("/Script/FortniteGame.FortKismetLibrary.GiveItemToInventoryOwner", "PickupInstigatorHandle", false); - // return GiveItemToInventoryOwnerOriginal(Context, Stack, Ret); - TScriptInterface InventoryOwner; // = *(TScriptInterface*)(__int64(Params) + InventoryOwnerOffset); UFortWorldItemDefinition* ItemDefinition = nullptr; // *(UFortWorldItemDefinition**)(__int64(Params) + ItemDefinitionOffset); int NumberToGive; // = *(int*)(__int64(Params) + NumberToGiveOffset); @@ -84,16 +116,18 @@ void UFortKismetLibrary::GiveItemToInventoryOwnerHook(UObject* Context, FFrame& int ItemLevel; // = *(int*)(__int64(Params) + ItemLevelOffset); int PickupInstigatorHandle; // = *(int*)(__int64(Params) + PickupInstigatorHandleOffset); - Stack.Step(Stack.Object, &InventoryOwner); - Stack.Step(Stack.Object, &ItemDefinition); - Stack.Step(Stack.Object, &NumberToGive); - Stack.Step(Stack.Object, &bNotifyPlayer); + Stack.StepCompiledIn(&InventoryOwner); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&NumberToGive); + Stack.StepCompiledIn(&bNotifyPlayer); + + LOG_INFO(LogDev, __FUNCTION__); if (ItemLevelOffset != 0) - Stack.Step(Stack.Object, &ItemLevel); + Stack.StepCompiledIn(&ItemLevel); if (PickupInstigatorHandleOffset != 0) - Stack.Step(Stack.Object, &PickupInstigatorHandle); + Stack.StepCompiledIn(&PickupInstigatorHandle); if (!ItemDefinition) return GiveItemToInventoryOwnerOriginal(Context, Stack, Ret); @@ -140,9 +174,11 @@ void UFortKismetLibrary::K2_RemoveItemFromPlayerHook(UObject* Context, FFrame& S UFortWorldItemDefinition* ItemDefinition = nullptr; int AmountToRemove; - Stack.Step(Stack.Object, &PlayerController); - Stack.Step(Stack.Object, &ItemDefinition); - Stack.Step(Stack.Object, &AmountToRemove); + Stack.StepCompiledIn(&PlayerController); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&AmountToRemove); + + LOG_INFO(LogDev, __FUNCTION__); auto WorldInventory = PlayerController->GetWorldInventory(); @@ -172,10 +208,12 @@ void UFortKismetLibrary::K2_RemoveItemFromPlayerByGuidHook(UObject* Context, FFr int AmountToRemove; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bForceRemoval; - Stack.Step(Stack.Object, &PlayerController); - Stack.Step(Stack.Object, &ItemGuid); - Stack.Step(Stack.Object, &AmountToRemove); - Stack.Step(Stack.Object, &bForceRemoval); + Stack.StepCompiledIn(&PlayerController); + Stack.StepCompiledIn(&ItemGuid); + Stack.StepCompiledIn(&AmountToRemove); + Stack.StepCompiledIn(&bForceRemoval); + + LOG_INFO(LogDev, __FUNCTION__); if (!PlayerController) return; @@ -203,10 +241,12 @@ void UFortKismetLibrary::K2_GiveItemToPlayerHook(UObject* Context, FFrame& Stack int NumberToGive; bool bNotifyPlayer; - Stack.Step(Stack.Object, &PlayerController); - Stack.Step(Stack.Object, &ItemDefinition); - Stack.Step(Stack.Object, &NumberToGive); - Stack.Step(Stack.Object, &bNotifyPlayer); + Stack.StepCompiledIn(&PlayerController); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&NumberToGive); + Stack.StepCompiledIn(&bNotifyPlayer); + + LOG_INFO(LogDev, __FUNCTION__); if (!PlayerController || !ItemDefinition) return K2_GiveItemToPlayerOriginal(Context, Stack, Ret); @@ -227,10 +267,12 @@ void UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook(UObject* Context, FFram int AmountToRemove; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bForceRemoval; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - Stack.Step(Stack.Object, &PlayerController); - Stack.Step(Stack.Object, &Item); - Stack.Step(Stack.Object, &AmountToRemove); - Stack.Step(Stack.Object, &bForceRemoval); + Stack.StepCompiledIn(&PlayerController); + Stack.StepCompiledIn(&Item); + Stack.StepCompiledIn(&AmountToRemove); + Stack.StepCompiledIn(&bForceRemoval); + + LOG_INFO(LogDev, __FUNCTION__); if (!PlayerController) return; @@ -267,27 +309,28 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con AFortPlayerController* OptionalOwnerPC; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bPickupOnlyRelevantToOwner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - - Stack.Step(Stack.Object, &WorldContextObject); - Stack.Step(Stack.Object, &ItemDefinition); - Stack.Step(Stack.Object, &PickupClass); - Stack.Step(Stack.Object, &NumberToSpawn); - Stack.Step(Stack.Object, &Position); - Stack.Step(Stack.Object, &Direction); - Stack.Step(Stack.Object, &OverrideMaxStackCount); - Stack.Step(Stack.Object, &bToss); - Stack.Step(Stack.Object, &bRandomRotation); - Stack.Step(Stack.Object, &bBlockedFromAutoPickup); - Stack.Step(Stack.Object, &PickupInstigatorHandle); - Stack.Step(Stack.Object, &SourceType); - Stack.Step(Stack.Object, &Source); - Stack.Step(Stack.Object, &OptionalOwnerPC); - Stack.Step(Stack.Object, &bPickupOnlyRelevantToOwner); + Stack.StepCompiledIn(&WorldContextObject); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&PickupClass); + Stack.StepCompiledIn(&NumberToSpawn); + Stack.StepCompiledIn(&Position); + Stack.StepCompiledIn(&Direction); + Stack.StepCompiledIn(&OverrideMaxStackCount); + Stack.StepCompiledIn(&bToss); + Stack.StepCompiledIn(&bRandomRotation); + Stack.StepCompiledIn(&bBlockedFromAutoPickup); + Stack.StepCompiledIn(&PickupInstigatorHandle); + Stack.StepCompiledIn(&SourceType); + Stack.StepCompiledIn(&Source); + Stack.StepCompiledIn(&OptionalOwnerPC); + Stack.StepCompiledIn(&bPickupOnlyRelevantToOwner); if (!ItemDefinition) return K2_SpawnPickupInWorldWithClassOriginal(Context, Stack, Ret); - LOG_INFO(LogDev, "PickupClass: {}", PickupClass ? PickupClass->GetFullName() : "InvalidObject") + LOG_INFO(LogDev, "PickupClass: {}", PickupClass ? PickupClass->GetFullName() : "InvalidObject"); + + LOG_INFO(LogDev, __FUNCTION__); auto aa = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, SourceType, Source, -1, nullptr, PickupClass); @@ -314,20 +357,25 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr AFortPlayerController* OptionalOwnerPC; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) bool bPickupOnlyRelevantToOwner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - Stack.Step(Stack.Object, &WorldContextObject); - Stack.Step(Stack.Object, &ItemDefinition); - Stack.Step(Stack.Object, &NumberToSpawn); - Stack.Step(Stack.Object, &Position); - Stack.Step(Stack.Object, &Direction); - Stack.Step(Stack.Object, &OverrideMaxStackCount); - Stack.Step(Stack.Object, &bToss); - Stack.Step(Stack.Object, &bRandomRotation); - Stack.Step(Stack.Object, &bBlockedFromAutoPickup); - Stack.Step(Stack.Object, &PickupInstigatorHandle); - Stack.Step(Stack.Object, &SourceType); - Stack.Step(Stack.Object, &Source); - Stack.Step(Stack.Object, &OptionalOwnerPC); - Stack.Step(Stack.Object, &bPickupOnlyRelevantToOwner); + Stack.StepCompiledIn(&WorldContextObject); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&NumberToSpawn); + Stack.StepCompiledIn(&Position); + Stack.StepCompiledIn(&Direction); + Stack.StepCompiledIn(&OverrideMaxStackCount); + Stack.StepCompiledIn(&bToss); + Stack.StepCompiledIn(&bRandomRotation); + Stack.StepCompiledIn(&bBlockedFromAutoPickup); + Stack.StepCompiledIn(&PickupInstigatorHandle); + Stack.StepCompiledIn(&SourceType); + Stack.StepCompiledIn(&Source); + Stack.StepCompiledIn(&OptionalOwnerPC); + Stack.StepCompiledIn(&bPickupOnlyRelevantToOwner); + + LOG_INFO(LogDev, "[{}] ItemDefinition: {}", __FUNCTION__, ItemDefinition ? ItemDefinition->GetFullName() : ""); + + if (!ItemDefinition) + return K2_SpawnPickupInWorldOriginal(Context, Stack, Ret); auto aa = AFortPickup::SpawnPickup(ItemDefinition, Position, NumberToSpawn, SourceType, Source); @@ -340,16 +388,32 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr bool UFortKismetLibrary::PickLootDropsHook(UObject* Context, FFrame& Stack, bool* Ret) { UObject* WorldContextObject; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - TArray<__int64> OutLootToDrop; // (Parm, OutParm, ZeroConstructor, NativeAccessSpecifierPublic) + TArray OutLootToDropTempBuf; // (Parm, OutParm, ZeroConstructor, NativeAccessSpecifierPublic) FName TierGroupName; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) int WorldLevel; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) int ForcedLootTier; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - Stack.Step(Stack.Object, &WorldContextObject); - Stack.Step(Stack.Object, &OutLootToDrop); - Stack.Step(Stack.Object, &TierGroupName); - Stack.Step(Stack.Object, &WorldLevel); - Stack.Step(Stack.Object, &ForcedLootTier); + Stack.StepCompiledIn(&WorldContextObject); + auto& OutLootToDrop = Stack.StepCompiledInRef>(&OutLootToDropTempBuf); + Stack.StepCompiledIn(&TierGroupName); + Stack.StepCompiledIn(&WorldLevel); + Stack.StepCompiledIn(&ForcedLootTier); + + LOG_INFO(LogDev, "Picking loot for {}.", TierGroupName.ComparisonIndex.Value ? TierGroupName.ToString() : "InvalidName"); + + auto LootDrops = PickLootDrops(TierGroupName, true); + + for (int i = 0; i < LootDrops.size(); i++) + { + auto NewEntry = Alloc(FFortItemEntry::GetStructSize()); + auto& LootDrop = LootDrops.at(i); + + NewEntry->GetItemDefinition() = LootDrop.ItemDefinition; + NewEntry->GetCount() = LootDrop.Count; + NewEntry->GetLoadedAmmo() = LootDrop.LoadedAmmo; + + OutLootToDrop.AddPtr(NewEntry, FFortItemEntry::GetStructSize()); + } PickLootDropsOriginal(Context, Stack, Ret); diff --git a/Project Reboot 3.0/FortKismetLibrary.h b/Project Reboot 3.0/FortKismetLibrary.h index 9d52620..123801e 100644 --- a/Project Reboot 3.0/FortKismetLibrary.h +++ b/Project Reboot 3.0/FortKismetLibrary.h @@ -7,11 +7,11 @@ #include "BuildingSMActor.h" #include "FortPickup.h" +using UFortInventoryOwnerInterface = UObject; + class UFortKismetLibrary : public UObject { public: - using UFortInventoryOwnerInterface = UObject; - static inline void (*K2_GiveItemToPlayerOriginal)(UObject* Context, FFrame& Stack, void* Ret); static inline void (*K2_RemoveItemFromPlayerOriginal)(UObject* Context, FFrame& Stack, void* Ret); static inline void (*K2_RemoveItemFromPlayerByGuidOriginal)(UObject* Context, FFrame& Stack, void* Ret); @@ -20,10 +20,14 @@ public: static inline AFortPickup* (*K2_SpawnPickupInWorldOriginal)(UObject* Context, FFrame& Stack, AFortPickup** Ret); static inline bool (*PickLootDropsOriginal)(UObject* Context, FFrame& Stack, bool* Ret); static inline AFortPickup* (*K2_SpawnPickupInWorldWithClassOriginal)(UObject* Context, FFrame& Stack, AFortPickup** Ret); + static inline void (*CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*K2_SpawnPickupInWorldWithLootTierOriginal)(UObject* Context, FFrame& Stack, void* Ret); static UFortResourceItemDefinition* K2_GetResourceItemDefinition(EFortResourceType ResourceType); static void ApplyCharacterCosmetics(UObject* WorldContextObject, const TArray& CharacterParts, UObject* PlayerState, bool* bSuccess); + static void K2_SpawnPickupInWorldWithLootTierHook(UObject* Context, FFrame& Stack, void* Ret); + static void CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHook(UObject* Context, FFrame& Stack, void* Ret); static void GiveItemToInventoryOwnerHook(UObject* Context, FFrame& Stack, void* Ret); static void K2_RemoveItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret); static void K2_RemoveItemFromPlayerByGuidHook(UObject* Context, FFrame& Stack, void* Ret); diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index c0cbcb9..2fd4496 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -170,12 +170,12 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs for (int i = 0; i < LTDTables.size(); i++) { - LOG_INFO(LogDev, "[{}] LTD {}", LTDTables.at(i)->GetFullName()); + LOG_INFO(LogDev, "[{}] LTD {}", i, LTDTables.at(i)->GetFullName()); } for (int i = 0; i < LPTables.size(); i++) { - LOG_INFO(LogDev, "[{}] LP {}", LPTables.at(i)->GetFullName()); + LOG_INFO(LogDev, "[{}] LP {}", i, LPTables.at(i)->GetFullName()); } } diff --git a/Project Reboot 3.0/FortMinigame.cpp b/Project Reboot 3.0/FortMinigame.cpp index 88ef0f0..fd4d838 100644 --- a/Project Reboot 3.0/FortMinigame.cpp +++ b/Project Reboot 3.0/FortMinigame.cpp @@ -10,7 +10,7 @@ void AFortMinigame::ClearPlayerInventoryHook(UObject* Context, FFrame& Stack, vo AFortPlayerControllerAthena* PlayerController = nullptr; - Stack.Step(Stack.Object, &PlayerController); + Stack.StepCompiledIn(&PlayerController); if (!PlayerController) return; diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 1c4df2b..e1cc739 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -134,7 +134,7 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* Stack, void* Ret) { - static auto LlamaClass = FindObject("/Game/Athena/SupplyDrops/Llama/AthenaSupplyDrop_Llama.AthenaSupplyDrop_Llama_C"); + // static auto LlamaClass = FindObject("/Game/Athena/SupplyDrops/Llama/AthenaSupplyDrop_Llama.AthenaSupplyDrop_Llama_C"); static auto FortAthenaSupplyDropClass = FindObject("/Script/FortniteGame.FortAthenaSupplyDrop"); LOG_INFO(LogInteraction, "ServerAttemptInteract!"); @@ -277,6 +277,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* return; } + /* else if (ReceivingActor->IsA(FortAthenaSupplyDropClass)) { auto LootTierGroup = ReceivingActor->IsA(LlamaClass) ? UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaLlama") : UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaSupplyDrop"); // SupplyDrop->GetLootTierGroupOverride(); @@ -288,6 +289,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* AFortPickup::SpawnPickup(LootDrop.ItemDefinition, LocationToSpawnLoot, LootDrop.Count, EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource::SupplyDrop); } } + */ return ServerAttemptInteractOriginal(Context, Stack, Ret); } @@ -461,7 +463,7 @@ void AFortPlayerController::DropSpecificItemHook(UObject* Context, FFrame& Stack { UFortItemDefinition* DropItemDef = nullptr; - Stack.Step(Stack.Object, &DropItemDef); + Stack.StepCompiledIn(&DropItemDef); if (!DropItemDef) return; diff --git a/Project Reboot 3.0/FortWeaponItemDefinition.cpp b/Project Reboot 3.0/FortWeaponItemDefinition.cpp index 9932bc3..806a7d6 100644 --- a/Project Reboot 3.0/FortWeaponItemDefinition.cpp +++ b/Project Reboot 3.0/FortWeaponItemDefinition.cpp @@ -1,6 +1,7 @@ #include "FortWeaponItemDefinition.h" #include "DataTable.h" +#include "SoftObjectPtr.h" int UFortWeaponItemDefinition::GetClipSize() { @@ -34,6 +35,13 @@ int UFortWeaponItemDefinition::GetClipSize() return *(int*)(__int64(Row) + ClipSizeOffset); } +UFortWorldItemDefinition* UFortWeaponItemDefinition::GetAmmoData() +{ + static auto AmmoDataOffset = GetOffset("AmmoData"); + auto AmmoData = Get>(AmmoDataOffset); + return AmmoData.Get(); +} + UClass* UFortWeaponItemDefinition::StaticClass() { static auto Class = FindObject(L"/Script/FortniteGame.FortWeaponItemDefinition"); diff --git a/Project Reboot 3.0/FortWeaponItemDefinition.h b/Project Reboot 3.0/FortWeaponItemDefinition.h index 4b3fcb9..6439145 100644 --- a/Project Reboot 3.0/FortWeaponItemDefinition.h +++ b/Project Reboot 3.0/FortWeaponItemDefinition.h @@ -6,6 +6,7 @@ class UFortWeaponItemDefinition : public UFortWorldItemDefinition { public: int GetClipSize(); + UFortWorldItemDefinition* GetAmmoData(); static UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/InventoryManagementLibrary.cpp b/Project Reboot 3.0/InventoryManagementLibrary.cpp new file mode 100644 index 0000000..e7aedac --- /dev/null +++ b/Project Reboot 3.0/InventoryManagementLibrary.cpp @@ -0,0 +1,254 @@ +#include "InventoryManagementLibrary.h" +#include "FortItemDefinition.h" +#include "FortKismetLibrary.h" +#include "ScriptInterface.h" + +void UInventoryManagementLibrary::SwapItemsHook(UObject* Context, FFrame& Stack, void* Ret) +{ + TScriptInterface SourceOwner; + TScriptInterface TargetOwner; + TArray ItemGuids; + + Stack.StepCompiledIn(&SourceOwner); + Stack.StepCompiledIn(&TargetOwner); + Stack.StepCompiledIn(&ItemGuids); + + auto SourceObjectPointer = SourceOwner.ObjectPointer; + auto SourcePlayerController = Cast(SourceObjectPointer); + + LOG_INFO(LogDev, "Swapping."); + + if (!SourcePlayerController) + return SwapItemOriginal(Context, Stack, Ret); + + auto SourceWorldInventory = SourcePlayerController->GetWorldInventory(); + + if (!SourceWorldInventory) + return SwapItemsOriginal(Context, Stack, Ret); + + auto TargetObjectPointer = TargetOwner.ObjectPointer; + auto TargetPlayerController = Cast(TargetObjectPointer); + + if (!TargetPlayerController) + return SwapItemsOriginal(Context, Stack, Ret); + + auto TargetWorldInventory = TargetPlayerController->GetWorldInventory(); + + if (!TargetWorldInventory) + return SwapItemsOriginal(Context, Stack, Ret); + + for (int i = 0; i < ItemGuids.size(); i++) + { + auto& CurrentItemGuid = ItemGuids.at(i); + + auto ItemToSwapInstance = SourceWorldInventory->FindItemInstance(CurrentItemGuid.ItemGuid); + + if (!ItemToSwapInstance) + continue; + + TargetWorldInventory->AddItem(ItemToSwapInstance->GetItemEntry()->GetItemDefinition(), nullptr, CurrentItemGuid.Count, ItemToSwapInstance->GetItemEntry()->GetLoadedAmmo()); + SourceWorldInventory->RemoveItem(CurrentItemGuid.ItemGuid, nullptr, CurrentItemGuid.Count); // should we check return value? + } + + TargetWorldInventory->Update(); + SourceWorldInventory->Update(); + + return SwapItemsOriginal(Context, Stack, Ret); +} + +void UInventoryManagementLibrary::SwapItemHook(UObject* Context, FFrame& Stack, void* Ret) +{ + TScriptInterface SourceOwner; + TScriptInterface TargetOwner; + FGuid ItemGuid; + int32 Count; + + Stack.StepCompiledIn(&SourceOwner); + Stack.StepCompiledIn(&TargetOwner); + Stack.StepCompiledIn(&ItemGuid); + Stack.StepCompiledIn(&Count); + + auto SourceObjectPointer = SourceOwner.ObjectPointer; + auto SourcePlayerController = Cast(SourceObjectPointer); + + LOG_INFO(LogDev, "Swapping."); + + if (!SourcePlayerController) + return SwapItemOriginal(Context, Stack, Ret); + + auto SourceWorldInventory = SourcePlayerController->GetWorldInventory(); + + if (!SourceWorldInventory) + return SwapItemOriginal(Context, Stack, Ret); + + auto TargetObjectPointer = TargetOwner.ObjectPointer; + auto TargetPlayerController = Cast(TargetObjectPointer); + + if (!TargetPlayerController) + return SwapItemOriginal(Context, Stack, Ret); + + auto TargetWorldInventory = TargetPlayerController->GetWorldInventory(); + + if (!TargetWorldInventory) + return SwapItemOriginal(Context, Stack, Ret); + + auto ItemToSwapInstance = SourceWorldInventory->FindItemInstance(ItemGuid); + + if (!ItemToSwapInstance) + return SwapItemOriginal(Context, Stack, Ret); + + bool bShouldUpdateTarget = false; + TargetWorldInventory->AddItem(ItemToSwapInstance->GetItemEntry()->GetItemDefinition(), &bShouldUpdateTarget, Count, ItemToSwapInstance->GetItemEntry()->GetLoadedAmmo()); + + if (bShouldUpdateTarget) + TargetWorldInventory->Update(); + + bool bShouldUpdateSource = false; + SourceWorldInventory->RemoveItem(ItemGuid, &bShouldUpdateSource, Count); // should we check return value? + + if (bShouldUpdateSource) + SourceWorldInventory->Update(); + + return SwapItemOriginal(Context, Stack, Ret); +} + +void UInventoryManagementLibrary::RemoveItemsHook(UObject* Context, FFrame& Stack, void* Ret) +{ + TScriptInterface InventoryOwner; + TArray Items; + + Stack.StepCompiledIn(&InventoryOwner); + Stack.StepCompiledIn(&Items); + + auto ObjectPointer = InventoryOwner.ObjectPointer; + auto PlayerController = Cast(ObjectPointer); + + LOG_INFO(LogDev, "Taking list {} items from {}.", Items.Num(), __int64(PlayerController)); + + if (!PlayerController) + return RemoveItemOriginal(Context, Stack, Ret); + + auto WorldInventory = PlayerController->GetWorldInventory(); + + if (!WorldInventory) + return RemoveItemOriginal(Context, Stack, Ret); + + for (int i = 0; i < Items.Num(); i++) + { + WorldInventory->RemoveItem(Items.at(i).ItemGuid, nullptr, Items.at(i).Count); + } + + WorldInventory->Update(); + + return RemoveItemOriginal(Context, Stack, Ret); +} + +void UInventoryManagementLibrary::RemoveItemHook(UObject* Context, FFrame& Stack, void* Ret) +{ + TScriptInterface InventoryOwner; // 0x0(0x10)(Parm, ZeroConstructor, IsPlainOldData, NoDestructor, UObjectWrapper, NativeAccessSpecifierPublic) + FGuid ItemGuid; // 0x10(0x10)(Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + int32 Count; + + Stack.StepCompiledIn(&InventoryOwner); + Stack.StepCompiledIn(&ItemGuid); + Stack.StepCompiledIn(&Count); + + auto ObjectPointer = InventoryOwner.ObjectPointer; + auto PlayerController = Cast(ObjectPointer); + + LOG_INFO(LogDev, "Taking {} items from {}.", Count, __int64(PlayerController)); + + if (!PlayerController) + return RemoveItemOriginal(Context, Stack, Ret); + + auto WorldInventory = PlayerController->GetWorldInventory(); + + if (!WorldInventory) + return RemoveItemOriginal(Context, Stack, Ret); + + bool bShouldUpdate = false; + WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count); + + if (bShouldUpdate) + WorldInventory->Update(); + + return RemoveItemOriginal(Context, Stack, Ret); +} + +void UInventoryManagementLibrary::GiveItemEntryToInventoryOwnerHook(UObject* Context, FFrame& Stack, void* Ret) +{ + // Idk how to do the step with a itementry, allocate the size and then pass that pointer? idk. + + // TScriptInterface InventoryOwner; // 0x0(0x10)(Parm, ZeroConstructor, IsPlainOldData, NoDestructor, UObjectWrapper, NativeAccessSpecifierPublic) + // __int64 ItemEntry; + + return GiveItemEntryToInventoryOwnerOriginal(Context, Stack, Ret); +} + +void UInventoryManagementLibrary::AddItemsHook(UObject* Context, FFrame& Stack, void* Ret) +{ + TScriptInterface InventoryOwner; // 0x0(0x10)(Parm, ZeroConstructor, IsPlainOldData, NoDestructor, UObjectWrapper, NativeAccessSpecifierPublic) + TArray Items; + + Stack.StepCompiledIn(&InventoryOwner); + Stack.StepCompiledIn(&Items); + + auto ObjectPointer = InventoryOwner.ObjectPointer; + + auto PlayerController = Cast(ObjectPointer); + + LOG_INFO(LogDev, "Giving {} items to {}.", Items.Num(), __int64(PlayerController)); + + if (!PlayerController) + return AddItemsOriginal(Context, Stack, Ret); + + auto WorldInventory = PlayerController->GetWorldInventory(); + + if (!WorldInventory) + return; + + for (int i = 0; i < Items.Num(); i++) + { + WorldInventory->AddItem(Items.at(i).GetItem(), nullptr, Items.at(i).GetCount()); + } + + WorldInventory->Update(); + + return AddItemsOriginal(Context, Stack, Ret); +} + +void UInventoryManagementLibrary::AddItemHook(UObject* Context, FFrame& Stack, void* Ret) +{ + TScriptInterface InventoryOwner; // 0x0(0x10)(Parm, ZeroConstructor, IsPlainOldData, NoDestructor, UObjectWrapper, NativeAccessSpecifierPublic) + UFortItemDefinition* ItemDefinition; + int32 Count; // 0x18(0x4)(Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + + Stack.StepCompiledIn(&InventoryOwner); + Stack.StepCompiledIn(&ItemDefinition); + Stack.StepCompiledIn(&Count); + + LOG_INFO(LogDev, "[{}] ItemDefinition: {}", __FUNCTION__, __int64(ItemDefinition)); + + if (!ItemDefinition) + return AddItemOriginal(Context, Stack, Ret); + + auto ObjectPointer = InventoryOwner.ObjectPointer; + + auto PlayerController = Cast(ObjectPointer); + + if (!PlayerController) + return AddItemOriginal(Context, Stack, Ret); + + auto WorldInventory = PlayerController->GetWorldInventory(); + + if (!WorldInventory) + return; + + bool bShouldUpdate = false; + WorldInventory->AddItem(ItemDefinition, &bShouldUpdate, bShouldUpdate, Count); + + if (bShouldUpdate) + WorldInventory->Update(); + + return AddItemOriginal(Context, Stack, Ret); +} \ No newline at end of file diff --git a/Project Reboot 3.0/InventoryManagementLibrary.h b/Project Reboot 3.0/InventoryManagementLibrary.h new file mode 100644 index 0000000..a643285 --- /dev/null +++ b/Project Reboot 3.0/InventoryManagementLibrary.h @@ -0,0 +1,24 @@ +#pragma once + +#include "Object.h" +#include "Stack.h" + +class UInventoryManagementLibrary : public UObject // UBlueprintFunctionLibrary +{ +public: + static inline void (*AddItemOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*AddItemsOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*GiveItemEntryToInventoryOwnerOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*RemoveItemOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*RemoveItemsOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*SwapItemOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline void (*SwapItemsOriginal)(UObject* Context, FFrame& Stack, void* Ret); + + static void SwapItemsHook(UObject* Context, FFrame& Stack, void* Ret); + static void SwapItemHook(UObject* Context, FFrame& Stack, void* Ret); + static void RemoveItemsHook(UObject* Context, FFrame& Stack, void* Ret); + static void RemoveItemHook(UObject* Context, FFrame& Stack, void* Ret); + static void GiveItemEntryToInventoryOwnerHook(UObject* Context, FFrame& Stack, void* Ret); + static void AddItemsHook(UObject* Context, FFrame& Stack, void* Ret); + static void AddItemHook(UObject* Context, FFrame& Stack, void* Ret); +}; \ No newline at end of file diff --git a/Project Reboot 3.0/OnlineReplStructs.h b/Project Reboot 3.0/OnlineReplStructs.h new file mode 100644 index 0000000..15760d3 --- /dev/null +++ b/Project Reboot 3.0/OnlineReplStructs.h @@ -0,0 +1,22 @@ +// this file wasn't fun + +#pragma once + +#include "reboot.h" + +struct FUniqueNetIdRepl // : public FUniqueNetIdWrapper +{ + static UStruct* GetStruct() + { + static auto Struct = FindObject("/Script/Engine.UniqueNetIdRepl"); + return Struct; + } + + static int GetSizeOfStruct() + { + static auto Size = GetStruct()->GetPropertiesSize(); + return Size; + } + + /* bool IsEqual(FUniqueNetIdRepl* Other) */ +}; \ No newline at end of file diff --git a/Project Reboot 3.0/PlayerState.cpp b/Project Reboot 3.0/PlayerState.cpp index f4445a7..538b333 100644 --- a/Project Reboot 3.0/PlayerState.cpp +++ b/Project Reboot 3.0/PlayerState.cpp @@ -4,6 +4,13 @@ int& APlayerState::GetPlayerID() { - static auto PlayerIDOffset = FindOffsetStruct("/Script/Engine.PlayerState", "PlayerID"); + static auto PlayerIDOffset = FindOffsetStruct("/Script/Engine.PlayerState", "PlayerID", false); + + if (PlayerIDOffset == 0) + { + static auto PlayerIdOffset = FindOffsetStruct("/Script/Engine.PlayerState", "PlayerId", false); + return Get(PlayerIdOffset); + } + return Get(PlayerIDOffset); } \ No newline at end of file diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj b/Project Reboot 3.0/Project Reboot 3.0.vcxproj index be3d5ac..d5ab8c7 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -1,4 +1,4 @@ - + @@ -204,6 +204,7 @@ + @@ -284,6 +285,7 @@ + @@ -295,6 +297,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 8c4c96b..8f56583 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -158,6 +158,9 @@ Engine\Source\Runtime\Engine\Private + + FortniteGame\Source\FortniteGame\Private + @@ -452,6 +455,12 @@ Engine\Source\Runtime\Engine\Classes\Engine + + FortniteGame\Source\FortniteGame\Public + + + Engine\Source\Runtime\Engine\Classes\GameFramework + diff --git a/Project Reboot 3.0/Stack.h b/Project Reboot 3.0/Stack.h index 032a8a0..54a8e81 100644 --- a/Project Reboot 3.0/Stack.h +++ b/Project Reboot 3.0/Stack.h @@ -18,6 +18,18 @@ public: // MORE STUFF HERE + void* MostRecentProperty; + uint8_t* MostRecentPropertyAddress; + + uint8_t*& GetMostRecentPropertyAddress() + { + auto off = (void*)(&((struct FFrame*)NULL)->MostRecentPropertyAddress); + LOG_INFO(LogDev, "{}", off); + return MostRecentPropertyAddress; + static auto MostRecentPropertyAddressOffset = 56; + return *(uint8_t**)(__int64(this) + MostRecentPropertyAddressOffset); + } + void Step(UObject* Context, RESULT_DECL) { static void (*StepOriginal)(__int64 frame, UObject* Context, RESULT_DECL) = decltype(StepOriginal)(Addresses::FrameStep); @@ -26,4 +38,44 @@ public: // int32 B = *Code++; // (GNatives[B])(Context, *this, RESULT_PARAM); } + + __forceinline void StepCompiledIn(void* Result/*, const FFieldClass* ExpectedPropertyType*/) // https://github.com/EpicGames/UnrealEngine/blob/cdaec5b33ea5d332e51eee4e4866495c90442122/Engine/Source/Runtime/CoreUObject/Public/UObject/Stack.h#L444 + { + if (Code) + { + Step(Object, Result); + } + else + { + LOG_INFO(LogDev, "UNIMPLENTED!"); + /* checkSlow(ExpectedPropertyType && ExpectedPropertyType->IsChildOf(FProperty::StaticClass())); + checkSlow(PropertyChainForCompiledIn && PropertyChainForCompiledIn->IsA(ExpectedPropertyType)); + FProperty* Property = (FProperty*)PropertyChainForCompiledIn; + PropertyChainForCompiledIn = Property->Next; + StepExplicitProperty(Result, Property); */ + } + } + + template + __forceinline TNativeType& StepCompiledInRef(void* const TemporaryBuffer) + { + GetMostRecentPropertyAddress() = nullptr; + // GetMostRecentPropertyContainer() = nullptr; // added in ue5.1 + + if (Code) + { + Step(Object, TemporaryBuffer); + } + else + { + LOG_INFO(LogDev, "UNIMPLENTED2!"); + + /* checkSlow(CastField(PropertyChainForCompiledIn) && CastField(PropertyChainForCompiledIn)); + TProperty* Property = (TProperty*)PropertyChainForCompiledIn; + PropertyChainForCompiledIn = Property->Next; + StepExplicitProperty(TemporaryBuffer, Property); */ + } + + return (GetMostRecentPropertyAddress() != NULL) ? *(TNativeType*)(GetMostRecentPropertyAddress()) : *(TNativeType*)TemporaryBuffer; + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 65a79fc..b335056 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -24,6 +24,7 @@ #include "FortMinigame.h" #include "KismetSystemLibrary.h" #include "die.h" +#include "InventoryManagementLibrary.h" enum ENetMode { @@ -46,6 +47,17 @@ static void CollectGarbageHook() { return; } static __int64 (*DispatchRequestOriginal)(__int64 a1, __int64* a2, int a3); static __int64 DispatchRequestHook(__int64 a1, __int64* a2, int a3) { return DispatchRequestOriginal(a1, a2, 3); } +double GetServerDeltaTimeFromObjectHook(UObject* Object) +{ + auto World = GetWorld(); + + auto GameState = Cast(((AFortGameMode*)World->GetGameMode())->GetGameState()); + + if (!GameState) + return 0; + + return GameState->GetServerWorldTimeSeconds(); +} DWORD WINAPI Main(LPVOID) { @@ -241,28 +253,51 @@ DWORD WINAPI Main(LPVOID) UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook, (PVOID*)&UFortKismetLibrary::K2_RemoveFortItemFromPlayerOriginal, false, true); Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.K2_SpawnPickupInWorld"), UFortKismetLibrary::K2_SpawnPickupInWorldHook, (PVOID*)&UFortKismetLibrary::K2_SpawnPickupInWorldOriginal, false, true); - Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary:K2_SpawnPickupInWorldWithClass"), + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.K2_SpawnPickupInWorldWithLootTier"), + UFortKismetLibrary::K2_SpawnPickupInWorldWithLootTierHook, (PVOID*)&UFortKismetLibrary::K2_SpawnPickupInWorldWithLootTierOriginal, false, true); + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.K2_SpawnPickupInWorldWithClass"), UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook, (PVOID*)&UFortKismetLibrary::K2_SpawnPickupInWorldWithClassOriginal, false, true); + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.PickLootDrops"), + UFortKismetLibrary::PickLootDropsHook, (PVOID*)&UFortKismetLibrary::PickLootDropsOriginal, false, true); + Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject(L"/Script/FortniteGame.FortKismetLibrary.CreateTossAmmoPickupForWeaponItemDefinitionAtLocation"), + UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationHook, (PVOID*)&UFortKismetLibrary::CreateTossAmmoPickupForWeaponItemDefinitionAtLocationOriginal, false, true); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.DropSpecificItem"), AFortPlayerController::DropSpecificItemHook, (PVOID*)&AFortPlayerController::DropSpecificItemOriginal, false, true); - static auto FortAthenaSupplyDropDefault = FindObject("/Script/FortniteGame.Default__FortAthenaSupplyDrop"); + static auto FortAthenaSupplyDropDefault = FindObject(L"/Script/FortniteGame.Default__FortAthenaSupplyDrop"); Hooking::MinHook::Hook(FortAthenaSupplyDropDefault, FindObject(L"/Script/FortniteGame.FortAthenaSupplyDrop.SpawnPickup"), AFortAthenaSupplyDrop::SpawnPickupHook, (PVOID*)&AFortAthenaSupplyDrop::SpawnPickupOriginal, false, true); - static auto FortAthenaCreativePortalDefault = FindObject("/Script/FortniteGame.Default__FortAthenaCreativePortal"); + static auto FortAthenaCreativePortalDefault = FindObject(L"/Script/FortniteGame.Default__FortAthenaCreativePortal"); Hooking::MinHook::Hook(FortAthenaCreativePortalDefault, FindObject(L"/Script/FortniteGame.FortAthenaCreativePortal.TeleportPlayerToLinkedVolume"), AFortAthenaCreativePortal::TeleportPlayerToLinkedVolumeHook, (PVOID*)&AFortAthenaCreativePortal::TeleportPlayerToLinkedVolumeOriginal, false, true); Hooking::MinHook::Hook(FortAthenaCreativePortalDefault, FindObject(L"/Script/FortniteGame.FortAthenaCreativePortal.TeleportPlayer"), AFortAthenaCreativePortal::TeleportPlayerHook, (PVOID*)&AFortAthenaCreativePortal::TeleportPlayerOriginal, false, true); - static auto FortMinigameDefault = FindObject("/Script/FortniteGame.Default__FortMinigame"); + static auto FortMinigameDefault = FindObject(L"/Script/FortniteGame.Default__FortMinigame"); Hooking::MinHook::Hook(FortMinigameDefault, FindObject(L"/Script/FortniteGame.FortMinigame.ClearPlayerInventory"), AFortMinigame::ClearPlayerInventoryHook, (PVOID*)&AFortMinigame::ClearPlayerInventoryOriginal, false, true); + + static auto InventoryManagementLibraryDefault = FindObject(L"/Script/FortniteGame.Default__InventoryManagementLibrary"); + + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.AddItem"), + UInventoryManagementLibrary::AddItemHook, (PVOID*)&UInventoryManagementLibrary::AddItemOriginal, false, true); + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.AddItems"), + UInventoryManagementLibrary::AddItemsHook, (PVOID*)&UInventoryManagementLibrary::AddItemsOriginal, false, true); + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.GiveItemEntryToInventoryOwner"), + UInventoryManagementLibrary::GiveItemEntryToInventoryOwnerHook, (PVOID*)&UInventoryManagementLibrary::GiveItemEntryToInventoryOwnerOriginal, false, true); + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.RemoveItem"), + UInventoryManagementLibrary::RemoveItemHook, (PVOID*)&UInventoryManagementLibrary::RemoveItemOriginal, false, true); + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.RemoveItems"), + UInventoryManagementLibrary::RemoveItemsHook, (PVOID*)&UInventoryManagementLibrary::RemoveItemsOriginal, false, true); + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.SwapItem"), + UInventoryManagementLibrary::SwapItemHook, (PVOID*)&UInventoryManagementLibrary::SwapItemOriginal, false, true); + Hooking::MinHook::Hook(InventoryManagementLibraryDefault, FindObject(L"/Script/FortniteGame.InventoryManagementLibrary.SwapItems"), + UInventoryManagementLibrary::SwapItemsHook, (PVOID*)&UInventoryManagementLibrary::SwapItemsOriginal, false, true); } static auto ServerHandlePickupInfoFn = FindObject("/Script/FortniteGame.FortPlayerPawn.ServerHandlePickupInfo"); @@ -316,6 +351,7 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook((PVOID)Addresses::GetPlayerViewpoint, (PVOID)AFortPlayerControllerAthena::GetPlayerViewPointHook, (PVOID*)&AFortPlayerControllerAthena::GetPlayerViewPointOriginal); Hooking::MinHook::Hook((PVOID)Addresses::TickFlush, (PVOID)UNetDriver::TickFlushHook, (PVOID*)&UNetDriver::TickFlushOriginal); + // Hooking::MinHook::Hook((PVOID)(__int64(GetModuleHandleW(0)) + 0x1A001D0), GetServerDeltaTimeFromObjectHook); if (Engine_Version < 427) Hooking::MinHook::Hook((PVOID)Addresses::OnDamageServer, (PVOID)ABuildingActor::OnDamageServerHook, (PVOID*)&ABuildingActor::OnDamageServerOriginal); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index d63cf03..83d90bf 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -487,7 +487,7 @@ static inline uint64 FindSetZoneToIndex() // actually StartNewSafeZonePhase for (int i = 0; i < 100000; i++) { - if (*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x53) + if ((*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x53) || (*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x55)) { return Addr - i; } @@ -924,7 +924,9 @@ static inline uint64 FindGiveAbility() // auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!"); // has 2 refs for some reason on some versions // auto realGiveAbility = Memcury::Scanner(FindBytes(Addr, { 0xE8 }, 500, 0, false, 0, true)).RelativeOffset(1).Get(); - Memcury::Scanner addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500); // Memcury::Scanner(FindGiveAbilityAndActivateOnce()); + Memcury::Scanner addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 1, Engine_Version >= 500); // Memcury::Scanner(FindGiveAbilityAndActivateOnce()); + + // LOG_INFO(LogDev, "aaaaa: 0x{:x}", addr.Get() - __int64(GetModuleHandleW(0))); return Memcury::Scanner(FindBytes(addr, { 0xE8 }, 500, 0, false)).RelativeOffset(1).Get(); } diff --git a/Project Reboot 3.0/hooking.h b/Project Reboot 3.0/hooking.h index 6428273..7b34d16 100644 --- a/Project Reboot 3.0/hooking.h +++ b/Project Reboot 3.0/hooking.h @@ -244,6 +244,8 @@ namespace Hooking if (bHookExec) { + LOG_INFO(LogDev, "Hooking Exec {}", Function->GetName()); + if (Original) *Original = Exec; diff --git a/Project Reboot 3.0/log.h b/Project Reboot 3.0/log.h index 559d7e6..08afa37 100644 --- a/Project Reboot 3.0/log.h +++ b/Project Reboot 3.0/log.h @@ -62,6 +62,7 @@ inline void InitLogger() MakeLogger("LogDev"); MakeLogger("LogPlayer"); MakeLogger("LogLoot"); + MakeLogger("LogMinigame"); MakeLogger("LogLoading"); MakeLogger("LogHook"); MakeLogger("LogAbilities"); diff --git a/Project Reboot 3.0/reboot.h b/Project Reboot 3.0/reboot.h index a4b035b..2ac1649 100644 --- a/Project Reboot 3.0/reboot.h +++ b/Project Reboot 3.0/reboot.h @@ -340,7 +340,7 @@ static UObject* GetPlaylistToUse() } */ - // Playlist = FindObject("/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground"); + Playlist = FindObject("/Game/Athena/Playlists/Playground/Playlist_Playground.Playlist_Playground"); // Playlist = FindObject("/MoleGame/Playlists/Playlist_MoleGame.Playlist_MoleGame"); // Playlist = FindObject("/Game/Athena/Playlists/DADBRO/Playlist_DADBRO_Squads_8.Playlist_DADBRO_Squads_8");