diff --git a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp index 90f2f29..771e553 100644 --- a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp +++ b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp @@ -96,46 +96,6 @@ void UAbilitySystemComponent::InternalServerTryActivateAbilityHook(UAbilitySyste { // LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Activated {}", AbilityToActivate->GetName()); } - - // bro ignore this next part idk where to put it ok - - /* static auto OwnerActorOffset = AbilitySystemComponent->GetOffset("OwnerActor"); - auto PlayerState = Cast(AbilitySystemComponent->Get(OwnerActorOffset)); - - if (!PlayerState) - return; - - auto Controller = Cast(PlayerState->GetOwner()); - LOG_INFO(LogAbilities, "Owner {}", PlayerState->GetOwner()->GetFullName()); - - if (!Controller) - return; - - auto Pawn = Controller->GetMyFortPawn(); - - if (!Pawn) - return; - - auto CurrentWeapon = Pawn->GetCurrentWeapon(); - auto WorldInventory = Controller ? Controller->GetWorldInventory() : nullptr; - - if (!WorldInventory || !CurrentWeapon) - return; - - auto CurrentWeaponInstance = WorldInventory->FindItemInstance(CurrentWeapon->GetItemEntryGuid()); - auto CurrentWeaponReplicatedEntry = WorldInventory->FindReplicatedEntry(CurrentWeapon->GetItemEntryGuid()); - - static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount"); - auto AmmoCount = CurrentWeapon->Get(AmmoCountOffset); - - if (CurrentWeaponReplicatedEntry->GetLoadedAmmo() != AmmoCount) - { - CurrentWeaponInstance->GetItemEntry()->GetLoadedAmmo() = AmmoCount; - CurrentWeaponReplicatedEntry->GetLoadedAmmo() = AmmoCount; - - WorldInventory->GetItemList().MarkItemDirty(CurrentWeaponInstance->GetItemEntry()); - WorldInventory->GetItemList().MarkItemDirty(CurrentWeaponReplicatedEntry); - } */ } FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass) diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 155679c..d45ef6a 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -72,6 +72,8 @@ static UObject* GetPlaylistToUse() // 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"); @@ -613,7 +615,9 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint auto GameState = Cast(GameMode->GetGameState()); - auto Playlist = GameState->GetCurrentPlaylist(); + static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false); + + auto Playlist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist(); static int CurrentTeamMembers = 0; // bad static int Current = 3; diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index 43c0dac..0824710 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -170,7 +170,7 @@ std::pair, std::vector> AFortInventory::AddI return std::make_pair(NewItemInstances, ModifiedItemInstances); } -bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count) +bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval) { if (bShouldUpdate) *bShouldUpdate = false; @@ -188,8 +188,11 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int auto NewCount = ReplicatedEntry->GetCount() - Count; - if (NewCount > 0) + if (NewCount > 0 || (ItemDefinition->ShouldPersistWhenFinalStackEmpty() && !bForceRemoval)) { + if (ItemDefinition->ShouldPersistWhenFinalStackEmpty()) + NewCount = NewCount < 0 ? 0 : NewCount; // min(NewCount, 0) or something i forgot + ItemInstance->GetItemEntry()->GetCount() = NewCount; ReplicatedEntry->GetCount() = NewCount; @@ -291,6 +294,28 @@ UFortItem* AFortInventory::FindItemInstance(UFortItemDefinition* ItemDefinition) return nullptr; } +void AFortInventory::CorrectLoadedAmmo(const FGuid& Guid, int NewAmmoCount) +{ + auto CurrentWeaponInstance = FindItemInstance(Guid); + + if (!CurrentWeaponInstance) + return; + + auto CurrentWeaponReplicatedEntry = FindReplicatedEntry(Guid); + + if (!CurrentWeaponReplicatedEntry) + return; + + if (CurrentWeaponReplicatedEntry->GetLoadedAmmo() != NewAmmoCount) + { + CurrentWeaponInstance->GetItemEntry()->GetLoadedAmmo() = NewAmmoCount; + CurrentWeaponReplicatedEntry->GetLoadedAmmo() = NewAmmoCount; + + GetItemList().MarkItemDirty(CurrentWeaponInstance->GetItemEntry()); + GetItemList().MarkItemDirty(CurrentWeaponReplicatedEntry); + } +} + UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid) { auto& ItemInstances = GetItemList().GetItemInstances(); diff --git a/Project Reboot 3.0/FortInventory.h b/Project Reboot 3.0/FortInventory.h index 391a8e3..da890e9 100644 --- a/Project Reboot 3.0/FortInventory.h +++ b/Project Reboot 3.0/FortInventory.h @@ -117,12 +117,14 @@ public: } std::pair, std::vector> AddItem(UFortItemDefinition* ItemDefinition, bool* bShouldUpdate, int Count = 1, int LoadedAmmo = -1, bool bShouldAddToStateValues = false); - bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count); + bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval = false); void ModifyCount(UFortItem* ItemInstance, int New, bool bRemove = false, std::pair* outEntries = nullptr, bool bUpdate = true); UFortItem* GetPickaxeInstance(); UFortItem* FindItemInstance(UFortItemDefinition* ItemDefinition); + void CorrectLoadedAmmo(const FGuid& Guid, int NewAmmoCount); + UFortItem* FindItemInstance(const FGuid& Guid); FFortItemEntry* FindReplicatedEntry(const FGuid& Guid); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortInventoryInterface.cpp b/Project Reboot 3.0/FortInventoryInterface.cpp index b96c31e..22e0876 100644 --- a/Project Reboot 3.0/FortInventoryInterface.cpp +++ b/Project Reboot 3.0/FortInventoryInterface.cpp @@ -11,8 +11,9 @@ char UFortInventoryInterface::RemoveInventoryItemHook(__int64 a1, FGuid a2, int int SuperAdditionalOffset = Engine_Version >= 427 ? 16 : 8; auto ControllerObject = (UObject*)(__int64(a1) - (FortPlayerControllerSuperSize + SuperAdditionalOffset)); - LOG_INFO(LogDev, "FortPlayerControllerSuperSize: {}", FortPlayerControllerSuperSize); - LOG_INFO(LogDev, "ControllerObject: {}", ControllerObject->GetFullName()); + LOG_INFO(LogDev, "bForceRemoval: {}", (bool)bForceRemoval); + // LOG_INFO(LogDev, "FortPlayerControllerSuperSize: {}", FortPlayerControllerSuperSize); + // LOG_INFO(LogDev, "ControllerObject: {}", ControllerObject->GetFullName()); if (!ControllerObject) return false; @@ -28,7 +29,7 @@ char UFortInventoryInterface::RemoveInventoryItemHook(__int64 a1, FGuid a2, int return false; bool bShouldUpdate = false; - WorldInventory->RemoveItem(a2, &bShouldUpdate, Count); + WorldInventory->RemoveItem(a2, &bShouldUpdate, Count, bForceRemoval); if (bShouldUpdate) WorldInventory->Update(); diff --git a/Project Reboot 3.0/FortKismetLibrary.cpp b/Project Reboot 3.0/FortKismetLibrary.cpp index 5ed421f..a25bcc9 100644 --- a/Project Reboot 3.0/FortKismetLibrary.cpp +++ b/Project Reboot 3.0/FortKismetLibrary.cpp @@ -312,7 +312,7 @@ void UFortKismetLibrary::K2_RemoveItemFromPlayerByGuidHook(UObject* Context, FFr return K2_RemoveItemFromPlayerByGuidOriginal(Context, Stack, Ret); bool bShouldUpdate = false; - WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, AmountToRemove); + WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, AmountToRemove, bForceRemoval); if (bShouldUpdate) WorldInventory->Update(); @@ -374,8 +374,9 @@ void UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook(UObject* Context, FFram if (!WorldInventory) return K2_RemoveFortItemFromPlayerOriginal(Context, Stack, Ret); + LOG_INFO(LogDev, "bForceRemoval: {}", bForceRemoval); bool bShouldUpdate = false; - WorldInventory->RemoveItem(Item->GetItemEntry()->GetItemGuid(), &bShouldUpdate, AmountToRemove); + WorldInventory->RemoveItem(Item->GetItemEntry()->GetItemGuid(), &bShouldUpdate, AmountToRemove, bForceRemoval); if (bShouldUpdate) WorldInventory->Update(); diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index 8756521..4e6d87f 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -7,38 +7,42 @@ #include "GameplayTagContainer.h" #include "FortGameModeAthena.h" +#include + +float GetRandomFloatForLooting(float min, float max) +{ + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> dis(min, max); + float random_number = dis(gen); + + return random_number; + + return UKismetMathLibrary::RandomFloatInRange(min, max); +} + static FFortLootTierData* GetLootTierData2(std::vector& LootTierData, bool bPrint) { float TotalWeight = 0; + FFortLootTierData* SelectedItem = nullptr; for (auto Item : LootTierData) { TotalWeight += Item->GetWeight(); } - float RandomNumber = TotalWeight * (rand() * 0.000030518509); // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed? - - FFortLootTierData* SelectedItem = nullptr; - - if (bPrint) - { - std::cout << std::format("TotalWeight: {}\n", TotalWeight); - } + float RandomNumber = GetRandomFloatForLooting(0, 1); + float cumulative_weight = 0.0f; for (auto Item : LootTierData) { - if (bPrint) - { - std::cout << std::format("Rand: {} Weight: {}\n", RandomNumber, Item->GetWeight()); - } + cumulative_weight += Item->GetWeight() / TotalWeight; if (RandomNumber <= Item->GetWeight()) { SelectedItem = Item; break; } - - RandomNumber -= Item->GetWeight(); } if (!SelectedItem) @@ -50,25 +54,25 @@ static FFortLootTierData* GetLootTierData2(std::vector& Loot static FFortLootPackageData* GetLootPackage2(std::vector& LootPackages) { float TotalWeight = 0; + FFortLootPackageData* SelectedItem = nullptr; for (auto Item : LootPackages) { TotalWeight += Item->GetWeight(); } - float RandomNumber = TotalWeight * (rand() * 0.000030518509); // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed? - - FFortLootPackageData* SelectedItem = nullptr; + float RandomNumber = GetRandomFloatForLooting(0, 1); + float cumulative_weight = 0.0f; for (auto Item : LootPackages) { + cumulative_weight += Item->GetWeight() / TotalWeight; + if (RandomNumber <= Item->GetWeight()) { SelectedItem = Item; break; } - - RandomNumber -= Item->GetWeight(); } if (!SelectedItem) @@ -79,31 +83,20 @@ static FFortLootPackageData* GetLootPackage2(std::vector& static FFortLootTierData* GetLootTierData(std::vector& LootTierData, bool bPrint) { - return GetLootTierData2(LootTierData, bPrint); + // return GetLootTierData2(LootTierData, bPrint); float TotalWeight = 0; + FFortLootTierData* SelectedItem = nullptr; for (auto Item : LootTierData) { TotalWeight += Item->GetWeight(); } - float RandomNumber = UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed? - - FFortLootTierData* SelectedItem = nullptr; - - if (bPrint) - { - std::cout << std::format("TotalWeight: {}\n", TotalWeight); - } + float RandomNumber = GetRandomFloatForLooting(0, TotalWeight); // is -1 needed? for (auto Item : LootTierData) { - if (bPrint) - { - std::cout << std::format("Rand: {} Weight: {}\n", RandomNumber, Item->GetWeight()); - } - if (RandomNumber <= Item->GetWeight()) { SelectedItem = Item; @@ -121,18 +114,17 @@ static FFortLootTierData* GetLootTierData(std::vector& LootT static FFortLootPackageData* GetLootPackage(std::vector& LootPackages) { - return GetLootPackage2(LootPackages); + // return GetLootPackage2(LootPackages); float TotalWeight = 0; + FFortLootPackageData* SelectedItem = nullptr; for (auto Item : LootPackages) { TotalWeight += Item->GetWeight(); } - float RandomNumber = UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed? - - FFortLootPackageData* SelectedItem = nullptr; + float RandomNumber = GetRandomFloatForLooting(0, TotalWeight); // is -1 needed? for (auto Item : LootPackages) { @@ -158,8 +150,6 @@ public: TSoftObjectPtr LootPackageData; // 0x28(0x28)(Edit, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic) }; - - std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recursive) { std::vector LootDrops; @@ -168,8 +158,9 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs return LootDrops; auto GameState = ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena(); + static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false); -// #define BELUGA +#define BELUGA #ifndef BELUGA /* static */ std::vector LTDTables; @@ -183,19 +174,56 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs static bool bHasFoundTables = false; #endif - auto CurrentPlaylist = GameState->GetCurrentPlaylist(); + auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist(); if (!bHasFoundTables) { bHasFoundTables = true; - 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; + + static auto DataTableClass = FindObject("/Script/Engine.DataTable"); + static auto CompositeDataTableClass = FindObject("/Script/Engine.CompositeDataTable"); + + 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; + } + } + } + + if (!bFoundPlaylistTable) + { + LTDTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")); + LPTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")); + } + + // LTDTables.push_back(LoadObject(L"/Game/Athena/Playlists/Playground/AthenaLootTierData_Client.AthenaLootTierData_Client")); + // LPTables.push_back(LoadObject(L"/Game/Athena/Playlists/Playground/AthenaLootPackages_Client.AthenaLootPackages_Client")); #ifdef BELUGA static auto FortGameFeatureDataClass = FindObject("/Script/FortniteGame.FortGameFeatureData"); - static auto DataTableClass = FindObject("/Script/Engine.DataTable"); - static auto CompositeDataTableClass = FindObject("/Script/Engine.CompositeDataTable"); if (FortGameFeatureDataClass) { @@ -340,15 +368,17 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs } #endif - /* for (int i = 0; i < LTDTables.size(); i++) + for (int i = 0; i < LTDTables.size(); i++) { + LTDTables.at(i)->AddToRoot(); LOG_INFO(LogDev, "[{}] LTD {}", i, LTDTables.at(i)->GetFullName()); } for (int i = 0; i < LPTables.size(); i++) { + LPTables.at(i)->AddToRoot(); LOG_INFO(LogDev, "[{}] LP {}", i, LPTables.at(i)->GetFullName()); - } */ + } } std::vector TierGroupLTDs; @@ -357,7 +387,10 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs { auto LTD = LTDTables[p]; - if (!LTD) + // if (bPrint) + // LOG_INFO(LogLoot, "LTD: {}", !LTD->IsValidLowLevel() ? "BadRead" : LTD->GetFullName()); + + if (!LTD->IsValidLowLevel()) continue; auto& LTDRowMap = LTD->GetRowMap(); @@ -365,9 +398,6 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs // auto TierGroupNameStr = TierGroupName.ToString(); - // if (bPrint) - // LOG_INFO(LogLoot, "LTDRowMapNum: {} LTD: {}", LTDRowMapNum, IsBadReadPtr(LTD, 8) ? "BadRead" : LTD->GetFullName()); - for (int i = 0; i < LTDRowMapNum; i++) { auto& CurrentLTD = LTDRowMap.Pairs.Elements[i].ElementData.Value; @@ -474,6 +504,10 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs for (int p = 0; p < LPTables.size(); p++) { auto LP = LPTables[p]; + + if (!LP->IsValidLowLevel()) + continue; + auto& LPRowMap = LP->GetRowMap(); for (int i = 0; i < LPRowMap.Pairs.Elements.Num(); i++) @@ -573,6 +607,9 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs { for (int p = 0; p < LPTables.size(); p++) { + if (!LPTables[p]->IsValidLowLevel()) + continue; + auto& LPRowMap = LPTables[p]->GetRowMap(); for (int j = 0; j < LPRowMap.Pairs.Elements.Num(); j++) diff --git a/Project Reboot 3.0/FortPickup.cpp b/Project Reboot 3.0/FortPickup.cpp index 966a5b1..05420c3 100644 --- a/Project Reboot 3.0/FortPickup.cpp +++ b/Project Reboot 3.0/FortPickup.cpp @@ -145,7 +145,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup) auto SwappedPickup = SpawnPickup(ItemDefinitionToSwap, PawnLoc, ItemEntryToSwap->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, ItemEntryToSwap->GetLoadedAmmo(), Pawn); - WorldInventory->RemoveItem(CurrentItemGuid, nullptr, ItemEntryToSwap->GetCount()); + WorldInventory->RemoveItem(CurrentItemGuid, nullptr, ItemEntryToSwap->GetCount(), true); bHasSwapped = true; diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 28d3d99..5dae15d 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -489,6 +489,34 @@ void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFra return ServerCreateBuildingActorOriginal(Context, Stack, Ret); } +AActor* AFortPlayerController::SpawnToyInstanceHook(UObject* Context, FFrame* Stack, AActor** Ret) +{ + LOG_INFO(LogDev, "SpawnToyInstance!"); + + auto PlayerController = Cast(Context); + + UClass* ToyClass = nullptr; + FTransform SpawnPosition; + + Stack->StepCompiledIn(&ToyClass); + Stack->StepCompiledIn(&SpawnPosition); + + SpawnToyInstanceOriginal(Context, Stack, Ret); + + if (!ToyClass) + return nullptr; + + FActorSpawnParameters SpawnParameters{}; + SpawnParameters.Owner = PlayerController; + auto NewToy = GetWorld()->SpawnActor(ToyClass, SpawnPosition, SpawnParameters); + + static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances"); + + + *Ret = NewToy; + return *Ret; +} + void AFortPlayerController::DropSpecificItemHook(UObject* Context, FFrame& Stack, void* Ret) { UFortItemDefinition* DropItemDef = nullptr; @@ -546,7 +574,7 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController bool bShouldUpdate = false; - if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count)) + if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count, true)) return; if (bShouldUpdate) @@ -564,6 +592,7 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe UObject* AbilityToUse = nullptr; static auto AthenaSprayItemDefinitionClass = FindObject("/Script/FortniteGame.AthenaSprayItemDefinition"); + static auto AthenaToyItemDefinitionClass = FindObject("/Script/FortniteGame.AthenaToyItemDefinition"); if (EmoteAsset->IsA(AthenaSprayItemDefinitionClass)) { @@ -571,6 +600,21 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe AbilityToUse = SprayGameplayAbilityDefault; } + else if (EmoteAsset->IsA(AthenaToyItemDefinitionClass)) + { + static auto ToySpawnAbilityOffset = EmoteAsset->GetOffset("ToySpawnAbility"); + auto& ToySpawnAbilitySoft = EmoteAsset->Get>(ToySpawnAbilityOffset); + + static auto BGAClass = FindObject("/Script/Engine.BlueprintGeneratedClass"); + + auto ToySpawnAbility = ToySpawnAbilitySoft.Get(BGAClass, true); + + if (ToySpawnAbility) + AbilityToUse = ToySpawnAbility->CreateDefaultObject(); + } + + // LOG_INFO(LogDev, "Before AbilityToUse: {}", AbilityToUse ? AbilityToUse->GetFullName() : "InvalidObject"); + if (!AbilityToUse) { static auto EmoteGameplayAbilityDefault = FindObject("/Game/Abilities/Emotes/GAB_Emote_Generic.Default__GAB_Emote_Generic_C"); @@ -767,7 +811,7 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo for (auto& Pair : GuidAndCountsToRemove) { - WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second); + WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true); } WorldInventory->Update(); diff --git a/Project Reboot 3.0/FortPlayerController.h b/Project Reboot 3.0/FortPlayerController.h index 28b157f..b781751 100644 --- a/Project Reboot 3.0/FortPlayerController.h +++ b/Project Reboot 3.0/FortPlayerController.h @@ -31,6 +31,7 @@ public: static inline void (*ServerAttemptInteractOriginal)(UObject* Context, FFrame* Stack, void* Ret); static inline void (*ServerEditBuildingActorOriginal)(UObject* Context, FFrame& Stack, void* Ret); static inline void (*DropSpecificItemOriginal)(UObject* Context, FFrame& Stack, void* Ret); + static inline AActor* (*SpawnToyInstanceOriginal)(UObject* Context, FFrame* Stack, AActor** Ret); void ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot); @@ -69,6 +70,7 @@ public: static void ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation); // static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData); static void ServerCreateBuildingActorHook(UObject* Context, FFrame* Stack, void* Ret); + static AActor* SpawnToyInstanceHook(UObject* Context, FFrame* Stack, AActor** Ret); static void DropSpecificItemHook(UObject* Context, FFrame& Stack, void* Ret); static void ServerDropAllItemsHook(AFortPlayerController* PlayerController, UFortItemDefinition* IgnoreItemDef); diff --git a/Project Reboot 3.0/FortPlayerStateAthena.cpp b/Project Reboot 3.0/FortPlayerStateAthena.cpp index b658322..8c29902 100644 --- a/Project Reboot 3.0/FortPlayerStateAthena.cpp +++ b/Project Reboot 3.0/FortPlayerStateAthena.cpp @@ -43,7 +43,7 @@ void AFortPlayerStateAthena::ServerSetInAircraftHook(UObject* Context, FFrame& S for (auto& Pair : GuidAndCountsToRemove) { - WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second); + WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true); } WorldInventory->Update(); diff --git a/Project Reboot 3.0/FortWeapon.cpp b/Project Reboot 3.0/FortWeapon.cpp index 26c1efa..7cd82c4 100644 --- a/Project Reboot 3.0/FortWeapon.cpp +++ b/Project Reboot 3.0/FortWeapon.cpp @@ -1,6 +1,35 @@ #include "FortWeapon.h" +#include "FortPlayerPawn.h" #include "reboot.h" +#include "FortPlayerController.h" + +void AFortWeapon::ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret) +{ + // I don't know where to put this.. + + auto Weapon = (AFortWeapon*)Context; + auto Pawn = Cast(Weapon->GetOwner()); + + // LOG_INFO(LogDev, "Owner: {}", Weapon->GetOwner() ? Weapon->GetOwner()->GetFullName() : "InvalidObject"); + + if (!Pawn) + return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret); + + auto Controller = Cast(Pawn->GetController()); + auto CurrentWeapon = Weapon; // Pawn->GetCurrentWeapon(); + auto WorldInventory = Controller ? Controller->GetWorldInventory() : nullptr; + + if (!WorldInventory || !CurrentWeapon) + return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret); + + static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount"); + auto AmmoCount = CurrentWeapon->Get(AmmoCountOffset); + + WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount); + + return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret); +} UClass* AFortWeapon::StaticClass() { diff --git a/Project Reboot 3.0/FortWeapon.h b/Project Reboot 3.0/FortWeapon.h index 50e0f7d..b5b5164 100644 --- a/Project Reboot 3.0/FortWeapon.h +++ b/Project Reboot 3.0/FortWeapon.h @@ -1,10 +1,14 @@ #pragma once #include "Actor.h" +#include "GameplayAbilitySpec.h" +#include "Stack.h" class AFortWeapon : public AActor { public: + static inline void (*ServerReleaseWeaponAbilityOriginal)(UObject* Context, FFrame* Stack, void* Ret); + template T* GetWeaponData() { @@ -18,5 +22,7 @@ public: return Get(ItemEntryGuidOffset); } + static void ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret); + static UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortWorldItemDefinition.h b/Project Reboot 3.0/FortWorldItemDefinition.h index b672677..ae7bfbe 100644 --- a/Project Reboot 3.0/FortWorldItemDefinition.h +++ b/Project Reboot 3.0/FortWorldItemDefinition.h @@ -19,6 +19,13 @@ public: return ReadBitfieldValue(bDropOnDeathOffset, bDropOnDeathFieldMask); } + bool ShouldPersistWhenFinalStackEmpty() + { + static auto bPersistInInventoryWhenFinalStackEmptyOffset = GetOffset("bPersistInInventoryWhenFinalStackEmpty"); + static auto bPersistInInventoryWhenFinalStackEmptyFieldMask = GetFieldMask(GetProperty("bPersistInInventoryWhenFinalStackEmpty")); + return ReadBitfieldValue(bPersistInInventoryWhenFinalStackEmptyOffset, bPersistInInventoryWhenFinalStackEmptyFieldMask); + } + static UClass* StaticClass() { static auto Class = FindObject("/Script/FortniteGame.FortWorldItemDefinition"); diff --git a/Project Reboot 3.0/Object.cpp b/Project Reboot 3.0/Object.cpp index 0f4ec0e..21d90c6 100644 --- a/Project Reboot 3.0/Object.cpp +++ b/Project Reboot 3.0/Object.cpp @@ -4,6 +4,7 @@ #include "Class.h" #include "KismetSystemLibrary.h" +#include "UObjectArray.h" FName* getFNameOfProp(void* Property) { @@ -99,4 +100,36 @@ bool UObject::IsA(UClass* otherClass) { static auto Class = FindObject("/Script/CoreUObject.Object"); return Class; -} */ \ No newline at end of file +} */ + +void UObject::AddToRoot() +{ + auto Item = GetItemByIndex(InternalIndex); + + if (!Item) + { + LOG_INFO(LogDev, "Invalid item"); + return; + } + + Item->SetRootSet(); +} + +bool UObject::IsValidLowLevel() +{ + if (this == nullptr) + { + // UE_LOG(LogUObjectBase, Warning, TEXT("NULL object")); + return false; + } + if (IsBadReadPtr(this, 8)) // needed? + { + return false; + } + if (!ClassPrivate) + { + // UE_LOG(LogUObjectBase, Warning, TEXT("Object is not registered")); + return false; + } + return ChunkedObjects ? ChunkedObjects->IsValid(this) : UnchunkedObjects ? UnchunkedObjects->IsValid(this) : false; +} \ No newline at end of file diff --git a/Project Reboot 3.0/Object.h b/Project Reboot 3.0/Object.h index b8eb8cd..a7cf0cd 100644 --- a/Project Reboot 3.0/Object.h +++ b/Project Reboot 3.0/Object.h @@ -88,5 +88,8 @@ public: template T* GetPtr(const std::string& ChildName) { return GetPtr(GetOffset(ChildName)); } + void AddToRoot(); + bool IsValidLowLevel(); + // static class UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/ObjectMacros.h b/Project Reboot 3.0/ObjectMacros.h index 4f0889b..eeea069 100644 --- a/Project Reboot 3.0/ObjectMacros.h +++ b/Project Reboot 3.0/ObjectMacros.h @@ -1,5 +1,7 @@ #pragma once +#include "inc.h" + enum EObjectFlags { RF_NoFlags = 0x00000000, @@ -32,4 +34,32 @@ enum EObjectFlags RF_WillBeLoaded = 0x08000000, RF_HasExternalPackage = 0x10000000, RF_AllocatedInSharedPage = 0x80000000, -}; \ No newline at end of file +}; + +enum class EInternalObjectFlags : int +{ + None = 0, + + LoaderImport = 1 << 20, ///< Object is ready to be imported by another package during loading + Garbage = 1 << 21, ///< Garbage from logical point of view and should not be referenced. This flag is mirrored in EObjectFlags as RF_Garbage for performance + PersistentGarbage = 1 << 22, ///< Same as above but referenced through a persistent reference so it can't be GC'd + ReachableInCluster = 1 << 23, ///< External reference to object in cluster exists + ClusterRoot = 1 << 24, ///< Root of a cluster + Native = 1 << 25, ///< Native (UClass only). + Async = 1 << 26, ///< Object exists only on a different thread than the game thread. + AsyncLoading = 1 << 27, ///< Object is being asynchronously loaded. + Unreachable = 1 << 28, ///< Object is not reachable on the object graph. + // PendingKill UE_DEPRECATED(5.0, "PendingKill flag should no longer be used. Use Garbage flag instead.") = 1 << 29, ///< Objects that are pending destruction (invalid for gameplay but valid objects). This flag is mirrored in EObjectFlags as RF_PendingKill for performance + RootSet = 1 << 30, ///< Object will not be garbage collected, even if unreferenced. + PendingConstruction = 1 << 31 ///< Object didn't have its class constructor called yet (only the UObjectBase one to initialize its most basic members) + + /* GarbageCollectionKeepFlags = Native | Async | AsyncLoading | LoaderImport, + PRAGMA_DISABLE_DEPRECATION_WARNINGS + MirroredFlags = Garbage | PendingKill, /// Flags mirrored in EObjectFlags + + //~ Make sure this is up to date! + AllFlags = LoaderImport | Garbage | PersistentGarbage | ReachableInCluster | ClusterRoot | Native | Async | AsyncLoading | Unreachable | PendingKill | RootSet | PendingConstruction + PRAGMA_ENABLE_DEPRECATION_WARNINGS */ +}; + +ENUM_CLASS_FLAGS(EInternalObjectFlags) \ No newline at end of file diff --git a/Project Reboot 3.0/SoftObjectPtr.h b/Project Reboot 3.0/SoftObjectPtr.h index c76fbef..7f13da6 100644 --- a/Project Reboot 3.0/SoftObjectPtr.h +++ b/Project Reboot 3.0/SoftObjectPtr.h @@ -19,6 +19,19 @@ struct TSoftObjectPtr public: FSoftObjectPtr SoftObjectPtr; + bool IsValid() + { + if (Engine_Version <= 416) + { + auto& AssetPtr = *(TAssetPtr*)this; + return true; + } + else + { + return SoftObjectPtr.ObjectID.AssetPathName.ComparisonIndex.Value; + } + } + T* Get(UClass* ClassToLoad = nullptr, bool bTryToLoad = false) { if (Engine_Version <= 416) diff --git a/Project Reboot 3.0/UObjectArray.h b/Project Reboot 3.0/UObjectArray.h index 0c3cae9..5640625 100644 --- a/Project Reboot 3.0/UObjectArray.h +++ b/Project Reboot 3.0/UObjectArray.h @@ -3,6 +3,7 @@ #include "inc.h" #include "Object.h" +#include "ObjectMacros.h" struct FUObjectItem { @@ -10,6 +11,24 @@ struct FUObjectItem int32 Flags; int32 ClusterRootIndex; int32 SerialNumber; + + FORCEINLINE void SetFlag(EInternalObjectFlags FlagToSet) + { + // static_assert(sizeof(int32) == sizeof(Flags), "Flags must be 32-bit for atomics."); + int32 StartValue = int32(Flags); + + if ((StartValue & int32(FlagToSet)) == int32(FlagToSet)) + { + return; + } + + int32 NewValue = StartValue | int32(FlagToSet); + } + + FORCEINLINE void SetRootSet() + { + SetFlag(EInternalObjectFlags::RootSet); + } }; class FFixedUObjectArray @@ -28,6 +47,34 @@ public: return &Objects[Index]; } + bool IsValid(UObject* Object) + { + int32 Index = Object->InternalIndex; + if (Index == -1) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Object is not in global object array")); + return false; + } + if (!IsValidIndex(Index)) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Invalid object index %i"), Index); + return false; + } + + FUObjectItem* Slot = GetItemByIndex(Index); + if (!Slot || Slot->Object == nullptr) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Empty slot")); + return false; + } + if (Slot->Object != Object) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Other object in slot")); + return false; + } + return true; + } + FORCEINLINE UObject* GetObjectByIndex(int32 Index) { if (auto Item = GetItemByIndex(Index)) @@ -69,6 +116,34 @@ public: return Chunk + WithinChunkIndex; } + bool IsValid(UObject* Object) + { + int32 Index = Object->InternalIndex; + if (Index == -1) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Object is not in global object array")); + return false; + } + if (!IsValidIndex(Index)) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Invalid object index %i"), Index); + return false; + } + + FUObjectItem* Slot = GetItemByIndex(Index); + if (!Slot || Slot->Object == nullptr) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Empty slot")); + return false; + } + if (Slot->Object != Object) + { + // UE_LOG(LogUObjectArray, Warning, TEXT("Other object in slot")); + return false; + } + return true; + } + FORCEINLINE UObject* GetObjectByIndex(int32 Index) { if (auto Item = GetItemByIndex(Index)) @@ -84,4 +159,9 @@ extern inline FFixedUObjectArray* UnchunkedObjects = 0; FORCEINLINE UObject* GetObjectByIndex(int32 Index) { return ChunkedObjects ? ChunkedObjects->GetObjectByIndex(Index) : UnchunkedObjects->GetObjectByIndex(Index); +} + +FORCEINLINE FUObjectItem* GetItemByIndex(int32 Index) +{ + return ChunkedObjects ? ChunkedObjects->GetItemByIndex(Index) : UnchunkedObjects->GetItemByIndex(Index); } \ No newline at end of file diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 779e061..738de7d 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -393,12 +393,6 @@ std::vector Addresses::GetFunctionsToNull() toNull.push_back(Memcury::Scanner::FindPattern("40 57 41 56 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F1 74 3A 80 3D ? ? ? ? ? 0F 82").Get()); // collect garbage } - if (Engine_Version == 500) - { - // toNull.push_back(Memcury::Scanner::FindPattern("").Get()); // collectgarbage - // toNull.push_back(Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 48 8B FA 48 8B D9 48 85 D2 0F 84 ? ? ? ? 8B").Get()); // idk lmfao - } - if (Fortnite_Version == 12.61) { // toNull.push_back(Memcury::Scanner::FindPattern("48 89 4C 24 ? 55 56 57 41 56 48 81 EC ? ? ? ? 4C 8B B1 ? ? ? ? 33 F6 4C 89 B4 24 ? ? ? ? 48 8B").Get()); // fritter crash @@ -409,9 +403,9 @@ std::vector Addresses::GetFunctionsToNull() toNull.push_back(Memcury::Scanner::FindPattern("40 55 57 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F9 74 3B 80 3D ? ? ? ? ? 0F").Get()); } - if (Fortnite_Version == 17.30) + if (std::floor(Fortnite_Version) == 17) { - toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 70 08 48 89 78 10 55 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 ED").Get()); + // toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 70 08 48 89 78 10 55 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 ED").Get()); // collectgarbage } if (Fortnite_Version == 17.50) @@ -419,6 +413,12 @@ std::vector Addresses::GetFunctionsToNull() toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 48 89 70 10 48 89 78 18 4C 89 60 20 55 41 56 41 57 48 8B EC 48 83 EC 60 49 8B D9 45 8A").Get()); // no reservation in game } + if (Engine_Version == 500) + { + // toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 F6 0F 29 70 A8 44 38 35").Get()); // zone + // toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 55 56 57 41 54 41 55 41 56 41 57 48 8D 68 A8 48 81 EC ? ? ? ? 45 33 FF").Get()); // Garbage collection + } + toNull.push_back(Addresses::ChangeGameSessionId); return toNull; diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index ce8117f..bf6a19e 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -75,14 +75,4 @@ namespace Offsets void FindAll(); void Print(); -} - -#define ENUM_CLASS_FLAGS(Enum) \ - inline Enum& operator|=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \ - inline Enum& operator&=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \ - inline Enum& operator^=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \ - inline constexpr Enum operator| (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \ - inline constexpr Enum operator& (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \ - inline constexpr Enum operator^ (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \ - inline constexpr bool operator! (Enum E) { return !(__underlying_type(Enum))E; } \ - inline constexpr Enum operator~ (Enum E) { return (Enum)~(__underlying_type(Enum))E; } \ No newline at end of file +} \ No newline at end of file diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 96ac25c..1409c24 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -99,14 +99,17 @@ DWORD WINAPI Main(LPVOID) static auto FortPlayerStateAthenaDefault = FindObject(L"/Script/FortniteGame.Default__FortPlayerStateAthena"); static auto FortKismetLibraryDefault = FindObject(L"/Script/FortniteGame.Default__FortKismetLibrary"); static auto AthenaMarkerComponentDefault = FindObject(L"/Script/FortniteGame.Default__AthenaMarkerComponent"); + static auto FortWeaponDefault = FindObject(L"/Script/FortniteGame.Default__FortWeapon"); + UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogBuilding VeryVerbose", nullptr); + // UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortUIDirector NoLogging", nullptr); UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogAbilitySystem VeryVerbose", nullptr); UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFort VeryVerbose", nullptr); UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogGameMode VeryVerbose", nullptr); if (Globals::bNoMCP) { - if (Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr)) + if (Fortnite_Version > 2.5 ? Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr) : true) { Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr); } @@ -263,6 +266,9 @@ DWORD WINAPI Main(LPVOID) nullptr, false); } + Hooking::MinHook::Hook(FortWeaponDefault, FindObject(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"), + AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true); + Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerDropAllItems"), AFortPlayerController::ServerDropAllItemsHook, nullptr, false); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerAttemptInventoryDrop"), @@ -325,6 +331,8 @@ DWORD WINAPI Main(LPVOID) // TODO Add RemoveItemFromInventoryOwner + Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.SpawnToyInstance"), + AFortPlayerController::SpawnToyInstanceHook, (PVOID*)&AFortPlayerController::SpawnToyInstanceOriginal, false, true); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.DropSpecificItem"), AFortPlayerController::DropSpecificItemHook, (PVOID*)&AFortPlayerController::DropSpecificItemOriginal, false, true); @@ -438,32 +446,35 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal); Hooking::MinHook::Hook((PVOID)Addresses::CanActivateAbility, ReturnTrueHook); // ahhh wtf - auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)FindFunctionCall(L"ServerRemoveInventoryItem", - Fortnite_Version >= 16 ? std::vector{ 0x48, 0x8B, 0xC4 } : std::vector{ 0x48, 0x89, 0x5C }), 0, true); - - LOG_INFO(LogDev, "ServerRemoveInventoryItemFunctionCallRef: 0x{:x}", ServerRemoveInventoryItemFunctionCallRef.Get() - __int64(GetModuleHandleW(0))); - - uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0; - - for (int i = 0; i < 400; i++) + if (Fortnite_Version >= 2.5) { - if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0x5C) + auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)FindFunctionCall(L"ServerRemoveInventoryItem", + Fortnite_Version >= 16 ? std::vector{ 0x48, 0x8B, 0xC4 } : std::vector{ 0x48, 0x89, 0x5C }), 0, true); + + LOG_INFO(LogDev, "ServerRemoveInventoryItemFunctionCallRef: 0x{:x}", ServerRemoveInventoryItemFunctionCallRef.Get() - __int64(GetModuleHandleW(0))); + + uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0; + + for (int i = 0; i < 400; i++) { - ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i; - break; + if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0x5C) + { + ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i; + break; + } + + if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x83 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0xEC) + { + ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i; + break; + } } - if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x83 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0xEC) - { - ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i; - break; - } + Hooking::MinHook::Hook( + Memcury::Scanner(ServerRemoveInventoryItemFunctionCallBeginFunctionAddr).GetAs(), + UFortInventoryInterface::RemoveInventoryItemHook + ); } - - Hooking::MinHook::Hook( - Memcury::Scanner(ServerRemoveInventoryItemFunctionCallBeginFunctionAddr).GetAs(), - UFortInventoryInterface::RemoveInventoryItemHook - ); if (Fortnite_Version >= 13) Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)SetZoneToIndexHook, (PVOID*)&SetZoneToIndexOriginal); @@ -513,7 +524,7 @@ DWORD WINAPI Main(LPVOID) MemberOffsets::DeathReport::KillerPlayerState = FindOffsetStruct("/Script/FortniteGame.FortPlayerDeathReport", "KillerPlayerState"); MemberOffsets::DeathReport::DamageCauser = FindOffsetStruct("/Script/FortniteGame.FortPlayerDeathReport", "DamageCauser"); } - + srand(time(0)); LOG_INFO(LogHook, "Finished!"); diff --git a/Project Reboot 3.0/inc.h b/Project Reboot 3.0/inc.h index 8090458..b6ea0b2 100644 --- a/Project Reboot 3.0/inc.h +++ b/Project Reboot 3.0/inc.h @@ -16,4 +16,14 @@ extern inline int Engine_Version = 0; // For example, 420, 421, etc. // Prevent extern inline double Fortnite_Version = 0; // For example, 4.1, 6.21, etc. // Prevent using this when possible. #define MS_ALIGN(n) __declspec(align(n)) -#define FORCENOINLINE __declspec(noinline) \ No newline at end of file +#define FORCENOINLINE __declspec(noinline) + +#define ENUM_CLASS_FLAGS(Enum) \ + inline Enum& operator|=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \ + inline Enum& operator&=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \ + inline Enum& operator^=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \ + inline constexpr Enum operator| (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \ + inline constexpr Enum operator& (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \ + inline constexpr Enum operator^ (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \ + inline constexpr bool operator! (Enum E) { return !(__underlying_type(Enum))E; } \ + inline constexpr Enum operator~ (Enum E) { return (Enum)~(__underlying_type(Enum))E; } \ No newline at end of file