diff --git a/Project Reboot 3.0/AbilitySystemComponent.h b/Project Reboot 3.0/AbilitySystemComponent.h index 9c96c10..318b961 100644 --- a/Project Reboot 3.0/AbilitySystemComponent.h +++ b/Project Reboot 3.0/AbilitySystemComponent.h @@ -32,6 +32,7 @@ public: this->ProcessEvent(fn, &UAbilitySystemComponent_ClientActivateAbilityFailed_Params); } + void RemoveActiveGameplayEffectBySourceEffect(UClass* GEClass, int StacksToRemove, UAbilitySystemComponent* Instigator); void ConsumeAllReplicatedData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey* AbilityOriginalPredictionKey); FGameplayAbilitySpecHandle GiveAbilityEasy(UClass* AbilityClass); FGameplayAbilitySpec* FindAbilitySpecFromHandle(FGameplayAbilitySpecHandle Handle); diff --git a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp index 238a434..90f2f29 100644 --- a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp +++ b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp @@ -25,6 +25,14 @@ void LoopSpecs(UAbilitySystemComponent* AbilitySystemComponent, std::function(L"/Script/GameplayAbilities.AbilitySystemComponent.RemoveActiveGameplayEffectBySourceEffect"); + struct { UClass* GameplayEffect; UObject* InstigatorAbilitySystemComponent; int StacksToRemove; } UAbilitySystemComponent_RemoveActiveGameplayEffectBySourceEffect_Params{ GEClass, Instigator, StacksToRemove }; + + this->ProcessEvent(RemoveActiveGameplayEffectBySourceEffectFn, &UAbilitySystemComponent_RemoveActiveGameplayEffectBySourceEffect_Params); +} + void UAbilitySystemComponent::ConsumeAllReplicatedData(FGameplayAbilitySpecHandle AbilityHandle, FPredictionKey* AbilityOriginalPredictionKey) { // static auto AbilityTargetDataMapOffset = ActivatableAbilitiesOffset + FGameplayAbilitySpecContainerSize ? diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 3fb70ab..155679c 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -638,7 +638,7 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint return Current++; } - static int NextTeamIndex = Playlist->Get("DefaultFirstTeam"); // + 1? + static int NextTeamIndex = 3; // Playlist->Get("DefaultFirstTeam"); // + 1? static int LastNum1 = 1; @@ -646,7 +646,7 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint { LastNum1 = AmountOfRestarts; - NextTeamIndex = Playlist->Get("DefaultFirstTeam"); + NextTeamIndex = 3; // Playlist->Get("DefaultFirstTeam"); // + 1? } // std::cout << "CurrentTeamMembers: " << CurrentTeamMembers << '\n'; diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index cd9eb85..8756521 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -3,7 +3,9 @@ #include "DataTable.h" #include "KismetMathLibrary.h" #include "FortWeaponItemDefinition.h" - +#include "UObjectArray.h" +#include "GameplayTagContainer.h" +#include "FortGameModeAthena.h" static FFortLootTierData* GetLootTierData2(std::vector& LootTierData, bool bPrint) { @@ -149,6 +151,15 @@ static FFortLootPackageData* GetLootPackage(std::vector& return SelectedItem; } +struct FFortGameFeatureLootTableData +{ +public: + TSoftObjectPtr LootTierData; // 0x0(0x28)(Edit, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic) + TSoftObjectPtr LootPackageData; // 0x28(0x28)(Edit, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic) +}; + + + std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recursive) { std::vector LootDrops; @@ -156,10 +167,23 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs if (recursive > 10) return LootDrops; + auto GameState = ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena(); + +// #define BELUGA + +#ifndef BELUGA /* static */ std::vector LTDTables; /* static */ std::vector LPTables; /* static */ bool bHasFoundTables = false; +#else + static std::vector LTDTables; + static std::vector LPTables; + + static bool bHasFoundTables = false; +#endif + + auto CurrentPlaylist = GameState->GetCurrentPlaylist(); if (!bHasFoundTables) { @@ -168,6 +192,154 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs LTDTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client")); LPTables.push_back(LoadObject(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client")); +#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) + { + for (int i = 0; i < ChunkedObjects->Num(); i++) + { + auto Object = ChunkedObjects->GetObjectByIndex(i); + + if (!Object) + continue; + + if (Object->IsA(FortGameFeatureDataClass)) + { + auto GameFeatureData = Object; + static auto DefaultLootTableDataOffset = GameFeatureData->GetOffset("DefaultLootTableData"); + + auto DefaultLootTableData = GameFeatureData->GetPtr(DefaultLootTableDataOffset); + + auto LootTierDataTableStr = DefaultLootTableData->LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + + auto LootTierDataTableIsComposite = LootTierDataTableStr.contains("Composite"); + auto LootPackageTableStr = DefaultLootTableData->LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + auto LootPackageTableIsComposite = LootPackageTableStr.contains("Composite"); + + auto LootTierDataPtr = DefaultLootTableData->LootTierData.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : DataTableClass, true); + auto LootPackagePtr = DefaultLootTableData->LootPackageData.Get(LootPackageTableIsComposite ? CompositeDataTableClass : DataTableClass, true); + + if (LootPackagePtr) + { + LPTables.push_back(LootPackagePtr); + } + + if (CurrentPlaylist) + { + static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData"); + auto PlaylistOverrideLootTableData = GameFeatureData->GetPtr>(PlaylistOverrideLootTableDataOffset); + + auto PlaylistOverrideLootTableData_Data = PlaylistOverrideLootTableData->Pairs.Elements.Data; + + static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer"); + auto GameplayTagContainer = CurrentPlaylist->GetPtr(GameplayTagContainerOffset); + + for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++) + { + auto& Tag = GameplayTagContainer->GameplayTags.At(i); + + for (int j = 0; j < PlaylistOverrideLootTableData_Data.Num(); j++) + { + auto Value = PlaylistOverrideLootTableData_Data.at(j).ElementData.Value; + auto CurrentOverrideTag = Value.First; + + if (Tag.TagName == CurrentOverrideTag.TagName) + { + auto OverrideLootPackageTableStr = Value.Second.LootPackageData.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + auto bOverrideIsComposite = OverrideLootPackageTableStr.contains("Composite"); + + auto ptr = Value.Second.LootPackageData.Get(bOverrideIsComposite ? CompositeDataTableClass : DataTableClass, true); + + if (ptr) + { + if (bOverrideIsComposite) + { + static auto ParentTablesOffset = ptr->GetOffset("ParentTables"); + + auto ParentTables = ptr->GetPtr>(ParentTablesOffset); + + for (int z = 0; z < ParentTables->size(); z++) + { + auto ParentTable = ParentTables->At(z); + + if (ParentTable) + { + LPTables.push_back(ParentTable); + } + } + } + + LPTables.push_back(ptr); + } + } + } + } + } + + if (LootTierDataPtr) + { + LTDTables.push_back(LootTierDataPtr); + } + + if (CurrentPlaylist) + { + static auto PlaylistOverrideLootTableDataOffset = GameFeatureData->GetOffset("PlaylistOverrideLootTableData"); + auto PlaylistOverrideLootTableData = GameFeatureData->GetPtr>(PlaylistOverrideLootTableDataOffset); + + auto PlaylistOverrideLootTableData_Data = PlaylistOverrideLootTableData->Pairs.Elements.Data; + + static auto GameplayTagContainerOffset = CurrentPlaylist->GetOffset("GameplayTagContainer"); + auto GameplayTagContainer = CurrentPlaylist->GetPtr(GameplayTagContainerOffset); + + for (int i = 0; i < GameplayTagContainer->GameplayTags.Num(); i++) + { + auto& Tag = GameplayTagContainer->GameplayTags.At(i); + + for (int j = 0; j < PlaylistOverrideLootTableData_Data.Num(); j++) + { + auto Value = PlaylistOverrideLootTableData_Data.at(j).ElementData.Value; + auto CurrentOverrideTag = Value.First; + + if (Tag.TagName == CurrentOverrideTag.TagName) + { + auto OverrideLootTierDataStr = Value.Second.LootTierData.SoftObjectPtr.ObjectID.AssetPathName.ToString(); + auto bOverrideIsComposite = OverrideLootTierDataStr.contains("Composite"); + + auto ptr = Value.Second.LootTierData.Get(bOverrideIsComposite ? CompositeDataTableClass : DataTableClass, true); + + if (ptr) + { + if (bOverrideIsComposite) + { + static auto ParentTablesOffset = ptr->GetOffset("ParentTables"); + + auto ParentTables = ptr->GetPtr>(ParentTablesOffset); + + for (int z = 0; z < ParentTables->size(); z++) + { + auto ParentTable = ParentTables->At(z); + + if (ParentTable) + { + LTDTables.push_back(ParentTable); + } + } + } + + LTDTables.push_back(ptr); + } + } + } + } + } + } + } + } +#endif + /* for (int i = 0; i < LTDTables.size(); i++) { LOG_INFO(LogDev, "[{}] LTD {}", i, LTDTables.at(i)->GetFullName()); @@ -240,7 +412,7 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs int MinimumLootDrops = 0; - static int AmountToAdd = Engine_Version >= 424 ? Engine_Version >= 500 ? 2 : 1 : 0; // fr + static int AmountToAdd = Engine_Version >= 424 ? Engine_Version >= 500 ? 1 : 1 : 0; // fr float NumLootPackageDrops = std::floor(ChosenRowLootTierData->GetNumLootPackageDrops() + AmountToAdd); diff --git a/Project Reboot 3.0/FortPickup.cpp b/Project Reboot 3.0/FortPickup.cpp index b717907..966a5b1 100644 --- a/Project Reboot 3.0/FortPickup.cpp +++ b/Project Reboot 3.0/FortPickup.cpp @@ -22,9 +22,13 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca static auto FortPickupClass = FindObject(L"/Script/FortniteGame.FortPickup"); auto PlayerState = Pawn ? Cast(Pawn->GetPlayerState()) : nullptr; - if (auto Pickup = GetWorld()->SpawnActor(OverrideClass ? OverrideClass : FortPickupClass, Location)) + FActorSpawnParameters SpawnParameters{}; + // SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; + + if (auto Pickup = GetWorld()->SpawnActor(OverrideClass ? OverrideClass : FortPickupClass, Location, FQuat(), FVector(1, 1, 1), SpawnParameters)) { static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup"); + Pickup->Get(PawnWhoDroppedPickupOffset) = Pawn; auto PrimaryPickupItemEntry = Pickup->GetPrimaryPickupItemEntry(); @@ -35,8 +39,6 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca // static auto OptionalOwnerIDOffset = Pickup->GetOffset("OptionalOwnerID"); // Pickup->Get(OptionalOwnerIDOffset) = PlayerState ? PlayerState->GetWorldPlayerId() : -1; - Pickup->Get(PawnWhoDroppedPickupOffset) = Pawn; - bool bToss = true; if (bToss) diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 1ce03e7..28d3d99 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -619,6 +619,9 @@ uint8 ToDeathCause(const FGameplayTagContainer& TagContainer, bool bWasDBNO = fa if (Engine_Version == 420) Addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 0F B6 FA 48 8B D9 E8 ? ? ? ? 33 F6 48 89 74 24").Get(); + if (Engine_Version == 421) // 5.1 + Addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 0F B6 FA 48 8B D9 E8 ? ? ? ? 33").Get(); + if (!Addr) { LOG_WARN(LogPlayer, "Failed to find ToDeathCause address!"); @@ -797,6 +800,17 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo // LOG_INFO(LogDev, "KillerWeaponDef: {}", KillerWeaponDef ? KillerWeaponDef->GetFullName() : "InvalidObject"); RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0); + + if (Fortnite_Version < 6) // Spectating + { + LOG_INFO(LogDev, "Starting Spectating!"); + + /* static auto PlayerToSpectateOnDeathOffset = PlayerController->GetOffset("PlayerToSpectateOnDeath"); + PlayerController->Get(PlayerToSpectateOnDeathOffset) = KillerPawn; + + static auto SpectateOnDeathFn = FindObject("/Script/FortniteGame.FortPlayerControllerZone.SpectateOnDeath") ? FindObject("/Script/FortniteGame.FortPlayerControllerZone.SpectateOnDeath") : FindObject("/Script/FortniteGame.FortPlayerControllerAthena.SpectateOnDeath"); + PlayerController->ProcessEvent(SpectateOnDeathFn); */ + } } } diff --git a/Project Reboot 3.0/GameModeBase.cpp b/Project Reboot 3.0/GameModeBase.cpp index 10f0a33..f6b97f9 100644 --- a/Project Reboot 3.0/GameModeBase.cpp +++ b/Project Reboot 3.0/GameModeBase.cpp @@ -60,6 +60,13 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll { auto NewPlayerAsAthena = Cast(NewPlayer); + /* if (Fortnite_Version >= 18) + { + static auto StormEffectClass = FindObject("/Game/Athena/SafeZone/GE_OutsideSafeZoneDamage.GE_OutsideSafeZoneDamage_C"); + auto PlayerState = NewPlayerAsAthena->GetPlayerStateAthena(); + PlayerState->GetAbilitySystemComponent()->RemoveActiveGameplayEffectBySourceEffect(StormEffectClass, 1, PlayerState->GetAbilitySystemComponent()); + } */ + if (NewPlayerAsAthena) { auto WorldInventory = NewPlayerAsAthena->GetWorldInventory(); diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 695ef85..96ac25c 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -429,7 +429,6 @@ 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); Hooking::MinHook::Hook((PVOID)Addresses::OnDamageServer, (PVOID)ABuildingActor::OnDamageServerHook, (PVOID*)&ABuildingActor::OnDamageServerOriginal); Hooking::MinHook::Hook((PVOID)Addresses::GetMaxTickRate, GetMaxTickRateHook); @@ -475,6 +474,7 @@ DWORD WINAPI Main(LPVOID) if (Fortnite_Version > 1.8) { + LOG_INFO(LogDev, "ahh!"); LOG_INFO(LogDev, "Test: 0x{:x}", FindFunctionCall(L"ClientOnPawnDied") - __int64(GetModuleHandleW(0))); Hooking::MinHook::Hook((PVOID)FindFunctionCall(L"ClientOnPawnDied"), AFortPlayerController::ClientOnPawnDiedHook, (PVOID*)&AFortPlayerController::ClientOnPawnDiedOriginal); } @@ -538,16 +538,14 @@ DWORD WINAPI Main(LPVOID) auto GameMode = (AFortGameMode*)GetWorld()->GetGameMode(); auto GameState = GameMode->GetGameState(); - /* GameState->Get("WarmupCountdownEndTime") = 0; GameMode->Get("WarmupCountdownDuration") = 0; GameState->Get("WarmupCountdownStartTime") = 0; GameMode->Get("WarmupEarlyCountdownDuration") = 0; - */ - FString cmd = L"startaircraft"; - UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), cmd, nullptr); + // FString cmd = L"startaircraft"; + // UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), cmd, nullptr); } else if (GetAsyncKeyState(VK_F9) & 1) diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index ad984ce..372afef 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -222,12 +222,13 @@ static inline uint64 FindOnRep_ZiplineState() if (Fortnite_Version < 7) return 0; - static auto Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! Role(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d", false).Get(); + auto Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! Role(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d", false).Get(); if (!Addrr) - Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! GetLocalRole()(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d").Get(); + Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! GetLocalRole()(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d", false).Get(); - // L"%s LocalRole[%s] ZiplineState.bIsZiplining[%d]" for 18.40??? + if (!Addrr) + Addrr = Memcury::Scanner::FindStringRef("AFortPlayerPawn::HandleZiplineStateChanged").Get(); // L"%s LocalRole[%s] ZiplineState.bIsZiplining[%d]" if (!Addrr) return 0; @@ -243,6 +244,11 @@ static inline uint64 FindOnRep_ZiplineState() { return Addrr - i; } + + if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x8B && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0xC4) + { + return Addrr - i; + } } return 0; @@ -261,6 +267,9 @@ static inline uint64 FindGetMaxTickRate() // Uengine::getmaxtickrate LOG_INFO(LogHook, "GetMaxTickRateIndex {}", GetMaxTickRateIndex); */ + if (Engine_Version == 500) + return Memcury::Scanner::FindPattern("40 53 48 83 EC 50 0F 29 74 24 ? 48 8B D9 0F 29 7C 24 ? 0F 28 F9 44 0F 29").Get(); // the string is in func + it's in function chunks. + auto Addrr = Memcury::Scanner::FindStringRef(L"Hitching by request!").Get(); if (!Addrr) @@ -478,7 +487,14 @@ static inline uint64 FindCompletePickupAnimation() return Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B D9 48 8B 89 ? ? ? ? 48 85 C9 74 20 48 8D 44 24").Get(); if (Engine_Version == 421) - return Memcury::Scanner::FindPattern("40 53 56 57 48 83 EC 30 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84").Get(); // 6.21 + { + auto adda = Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9").Get(); + + if (!adda) + adda = Memcury::Scanner::FindPattern("40 53 56 57 48 83 EC 30 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84").Get(); // 6.21 + + return adda; + } if (Engine_Version == 422) return Memcury::Scanner::FindPattern("40 53 56 57 48 83 EC 30 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED 0F 84").Get(); // 7.30