diff --git a/Project Reboot 3.0/AbilitySystemComponent.h b/Project Reboot 3.0/AbilitySystemComponent.h index 2ec24cb..9c96c10 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 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 b30bd91..238a434 100644 --- a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp +++ b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp @@ -25,6 +25,13 @@ void LoopSpecs(UAbilitySystemComponent* AbilitySystemComponent, std::functionConsumeAllReplicatedData(Handle, (FPredictionKey*)PredictionKey); /* const */ UGameplayAbility * AbilityToActivate = Spec->GetAbility(); diff --git a/Project Reboot 3.0/BuildingActor.h b/Project Reboot 3.0/BuildingActor.h index 57e284d..e426d7d 100644 --- a/Project Reboot 3.0/BuildingActor.h +++ b/Project Reboot 3.0/BuildingActor.h @@ -22,6 +22,12 @@ public: this->ProcessEvent(fn, &IBAParams); } + void SilentDie() + { + static auto SilentDieFn = FindObject("/ScriptFortniteGame.BuildingActor.SilentDie"); + this->ProcessEvent(SilentDieFn); + } + float GetMaxHealth() { float MaxHealth = 0; diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index a9ac12e..3fb70ab 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -677,7 +677,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena LOG_INFO(LogPlayer, "HandleStartingNewPlayer!"); - if (Engine_Version < 427) + // if (Engine_Version < 427) { static int LastNum69 = 19451; @@ -689,7 +689,6 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena auto BRIsland_FloorLoot = FindObject("/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_01.Tiered_Athena_FloorLoot_01_C"); TArray SpawnIsland_FloorLoot_Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), SpawnIsland_FloorLoot); - TArray BRIsland_FloorLoot_Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), BRIsland_FloorLoot); auto SpawnIslandTierGroup = UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaFloorLoot_Warmup"); @@ -755,10 +754,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena CurrentActor->K2_DestroyActor(); } - } - } - LOG_INFO(LogDev, "Spawned loot!"); + // SpawnIsland_FloorLoot_Actors.Free(); + // BRIsland_FloorLoot_Actors.Free(); + } + + LOG_INFO(LogDev, "Spawned loot!"); + } if (Engine_Version >= 423 && Engine_Version < 426) // 423+ we need to spawn manually and vehicle sync doesn't work on >S13. { diff --git a/Project Reboot 3.0/FortInventoryInterface.cpp b/Project Reboot 3.0/FortInventoryInterface.cpp index 2dbb8ca..b96c31e 100644 --- a/Project Reboot 3.0/FortInventoryInterface.cpp +++ b/Project Reboot 3.0/FortInventoryInterface.cpp @@ -1,14 +1,37 @@ #include "FortInventoryInterface.h" #include "reboot.h" +#include "FortPlayerControllerAthena.h" char UFortInventoryInterface::RemoveInventoryItemHook(__int64 a1, FGuid a2, int Count, char bForceRemoveFromQuickBars, char bForceRemoval) { + // kms bruh + static auto FortPlayerControllerSuperSize = (*(UClass**)(__int64(FindObject("/Script/FortniteGame.FortPlayerController")) + Offsets::SuperStruct))->GetPropertiesSize(); - auto Controller = *(UObject**)(__int64(a1) - (FortPlayerControllerSuperSize + 8)); + int SuperAdditionalOffset = Engine_Version >= 427 ? 16 : 8; + auto ControllerObject = (UObject*)(__int64(a1) - (FortPlayerControllerSuperSize + SuperAdditionalOffset)); LOG_INFO(LogDev, "FortPlayerControllerSuperSize: {}", FortPlayerControllerSuperSize); - LOG_INFO(LogDev, "Controller: {}", Controller->GetFullName()); + LOG_INFO(LogDev, "ControllerObject: {}", ControllerObject->GetFullName()); + if (!ControllerObject) + return false; + auto PlayerController = Cast(ControllerObject); + + if (!PlayerController) + return false; + + auto WorldInventory = PlayerController->GetWorldInventory(); + + if (!WorldInventory) + return false; + + bool bShouldUpdate = false; + WorldInventory->RemoveItem(a2, &bShouldUpdate, Count); + + if (bShouldUpdate) + WorldInventory->Update(); + + return true; } \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 076f594..1ce03e7 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -28,6 +28,13 @@ void AFortPlayerController::ClientReportDamagedResourceBuilding(ABuildingSMActor this->ProcessEvent(fn, &AFortPlayerController_ClientReportDamagedResourceBuilding_Params); } +bool AFortPlayerController::DoesBuildFree() +{ + static auto bBuildFreeOffset = GetOffset("bBuildFree"); + static auto bBuildFreeFieldMask = GetFieldMask(GetProperty("bBuildFree")); + return ReadBitfieldValue(bBuildFreeOffset, bBuildFreeFieldMask); +} + void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController* PlayerController, FGuid ItemGuid) { auto ItemInstance = PlayerController->GetWorldInventory()->FindItemInstance(ItemGuid); @@ -454,12 +461,30 @@ void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFra if (!BuildingActor) return ServerCreateBuildingActorOriginal(Context, Stack, Ret); - // static auto OwnerPersistentIDOffset = BuildingActor->GetOffset("OwnerPersistentID"); - // BuildingActor->Get(OwnerPersistentIDOffset) = PlayerStateAthena->GetWorldPlayerId(); + auto MatDefinition = UFortKismetLibrary::K2_GetResourceItemDefinition(BuildingActor->GetResourceType()); + auto WorldInventory = PlayerController->GetWorldInventory(); + auto MatInstance = WorldInventory->FindItemInstance(MatDefinition); + + bool bShouldDestroy = MatInstance ? PlayerController->DoesBuildFree() ? false : MatInstance->GetItemEntry()->GetCount() < 10 : true; + + if (bShouldDestroy) + { + BuildingActor->SilentDie(); + return ServerCreateBuildingActorOriginal(Context, Stack, Ret); + } BuildingActor->SetPlayerPlaced(true); BuildingActor->InitializeBuildingActor(PlayerController, BuildingActor, true); - BuildingActor->SetTeam(PlayerStateAthena->GetTeamIndex()); + BuildingActor->SetTeam(PlayerStateAthena->GetTeamIndex()); // required? + + if (!PlayerController->DoesBuildFree()) + { + bool bShouldUpdate = false; + WorldInventory->RemoveItem(MatInstance->GetItemEntry()->GetItemGuid(), &bShouldUpdate, 10); + + if (bShouldUpdate) + WorldInventory->Update(); + } return ServerCreateBuildingActorOriginal(Context, Stack, Ret); } diff --git a/Project Reboot 3.0/FortPlayerController.h b/Project Reboot 3.0/FortPlayerController.h index a948196..28b157f 100644 --- a/Project Reboot 3.0/FortPlayerController.h +++ b/Project Reboot 3.0/FortPlayerController.h @@ -61,6 +61,8 @@ public: return CosmeticLoadout; } + bool DoesBuildFree(); + static void ServerExecuteInventoryItemHook(AFortPlayerController* PlayerController, FGuid ItemGuid); static void ServerAttemptInteractHook(UObject* Context, FFrame* Stack, void* Ret); diff --git a/Project Reboot 3.0/GameModeBase.cpp b/Project Reboot 3.0/GameModeBase.cpp index 0cd1a75..10f0a33 100644 --- a/Project Reboot 3.0/GameModeBase.cpp +++ b/Project Reboot 3.0/GameModeBase.cpp @@ -27,19 +27,29 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll static auto PawnClass = FindObject("/Game/Athena/PlayerPawn_Athena.PlayerPawn_Athena_C"); GameMode->Get("DefaultPawnClass") = PawnClass; + constexpr bool bUseSpawnActor = false; + static auto fn = FindObject(L"/Script/Engine.GameModeBase.SpawnDefaultPawnAtTransform"); FTransform SpawnTransform = StartSpot->GetTransform(); - - struct { AController* NewPlayer; FTransform SpawnTransform; APawn* ReturnValue; } - AGameModeBase_SpawnDefaultPawnAtTransform_Params{NewPlayer, SpawnTransform }; - - // GameMode->ProcessEvent(fn, &AGameModeBase_SpawnDefaultPawnAtTransform_Params); + APawn* NewPawn = nullptr; FActorSpawnParameters SpawnParameters{}; SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn; - auto NewPawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, SpawnParameters); // AGameModeBase_SpawnDefaultPawnAtTransform_Params.ReturnValue; + if constexpr (bUseSpawnActor) + { + NewPawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, SpawnParameters); + } + else + { + struct { AController* NewPlayer; FTransform SpawnTransform; APawn* ReturnValue; } + AGameModeBase_SpawnDefaultPawnAtTransform_Params{ NewPlayer, SpawnTransform }; + + GameMode->ProcessEvent(fn, &AGameModeBase_SpawnDefaultPawnAtTransform_Params); + + NewPawn = AGameModeBase_SpawnDefaultPawnAtTransform_Params.ReturnValue; + } if (!NewPawn) return nullptr; diff --git a/Project Reboot 3.0/GameplayAbilityTypes.h b/Project Reboot 3.0/GameplayAbilityTypes.h new file mode 100644 index 0000000..4c417e7 --- /dev/null +++ b/Project Reboot 3.0/GameplayAbilityTypes.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Array.h" +#include "Map.h" +#include "GameplayAbilitySpec.h" + +struct FGameplayAbilitySpecHandleAndPredictionKey +{ + FGameplayAbilitySpecHandle AbilityHandle; + int32 PredictionKeyAtCreation; +}; + +/*struct FGameplayAbilityReplicatedDataContainer +{ + typedef TPair> FKeyDataPair; + + TArray InUseData; + TArray> FreeData; +}; */ \ 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 edc47fb..f02d444 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -282,6 +282,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 b243f70..6a50e5c 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -476,6 +476,9 @@ FortniteGame\Source\FortniteGame\Public\Building\GameplayActors + + Engine\Plugins\Runtime\GameplayAbilities\Source\GameplayAbilities\Public + diff --git a/Project Reboot 3.0/die.h b/Project Reboot 3.0/die.h index aacb858..3c72d9e 100644 --- a/Project Reboot 3.0/die.h +++ b/Project Reboot 3.0/die.h @@ -33,7 +33,7 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override LOG_INFO(LogDev, "SafeZoneDefinitionOffset: 0x{:x}", SafeZoneDefinitionOffset); - static auto ZoneDurationsOffset = std::floor(Fortnite_Version) >= 18 ? 0x248 : 0x1F8; + static auto ZoneDurationsOffset = std::floor(Fortnite_Version) == 17 ? 0x258 : std::floor(Fortnite_Version) >= 18 ? 0x248 : 0x1F8; static auto ZoneHoldDurationsOffset = ZoneDurationsOffset - 0x10; auto& ZoneDurations = *(TArray*)(__int64(SafeZoneDefinition) + ZoneDurationsOffset); diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 4880370..695ef85 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -430,19 +430,41 @@ 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); - } + Hooking::MinHook::Hook((PVOID)Addresses::OnDamageServer, (PVOID)ABuildingActor::OnDamageServerHook, (PVOID*)&ABuildingActor::OnDamageServerOriginal); Hooking::MinHook::Hook((PVOID)Addresses::GetMaxTickRate, GetMaxTickRateHook); // Hooking::MinHook::Hook((PVOID)Addresses::CollectGarbage, (PVOID)CollectGarbageHook, nullptr); Hooking::MinHook::Hook((PVOID)Addresses::PickTeam, (PVOID)AFortGameModeAthena::Athena_PickTeamHook); // Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)AFortGameModeAthena::SetZoneToIndexHook, (PVOID*)&AFortGameModeAthena::SetZoneToIndexOriginal); Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal); - // Hooking::MinHook::Hook((PVOID)Addresses::CanActivateAbility, ReturnTrueHook); // ahhh wtf - // Hooking::MinHook::Hook((PVOID)FindFunctionCall(L"ServerRemoveInventoryItem"), UFortInventoryInterface::RemoveInventoryItemHook); + 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 (*(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; + } + } + + Hooking::MinHook::Hook( + Memcury::Scanner(ServerRemoveInventoryItemFunctionCallBeginFunctionAddr).GetAs(), + UFortInventoryInterface::RemoveInventoryItemHook + ); if (Fortnite_Version >= 13) Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)SetZoneToIndexHook, (PVOID*)&SetZoneToIndexOriginal); @@ -516,11 +538,16 @@ 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); } else if (GetAsyncKeyState(VK_F9) & 1) diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 0be0712..ad984ce 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -397,7 +397,7 @@ static inline uint64 FindInitListen() static inline uint64 FindOnDamageServer() { auto Addr = FindFunctionCall(L"OnDamageServer", - Engine_Version == 416 ? std::vector{ 0x4C, 0x89, 0x4C} : + Engine_Version == 416 ? std::vector{ 0x4C, 0x89, 0x4C } : Engine_Version == 419 || Engine_Version >= 427 ? std::vector{ 0x48, 0x8B, 0xC4 } : std::vector{ 0x40, 0x55 } ); @@ -621,7 +621,7 @@ static inline uint64 FindRemoveFromAlivePlayers() Addrr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena: Player [%s] removed from alive players list (Team [%d]). Player count is now [%d]. PlayerBots count is now [%d]. Team count is now [%d].", false).Get(); if (!Addrr) - Addrr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena::RemoveFromAlivePlayers: Player [%s] PC [%s] removed from alive players list (Team [%d]). Player count is now [%d]. PlayerBots count is now [%d]. Team count is now [%d].", true, 0, Fortnite_Version >= 18).Get(); // todo check version + Addrr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena::RemoveFromAlivePlayers: Player [%s] PC [%s] removed from alive players list (Team [%d]). Player count is now [%d]. PlayerBots count is now [%d]. Team count is now [%d].", true, 0, Fortnite_Version >= 16).Get(); // checked on 16.40 for (int i = 0; i < 2000; i++) { diff --git a/Project Reboot 3.0/globals.h b/Project Reboot 3.0/globals.h index d8245cb..711aec5 100644 --- a/Project Reboot 3.0/globals.h +++ b/Project Reboot 3.0/globals.h @@ -4,7 +4,7 @@ namespace Globals { extern inline bool bCreative = false; extern inline bool bGoingToPlayEvent = false; - extern inline bool bNoMCP = false; + extern inline bool bNoMCP = true; extern inline bool bLateGame = false; extern inline bool bAbilitiesEnabled = true; extern inline bool bLogProcessEvent = false; diff --git a/vendor/memcury.h b/vendor/memcury.h index 9c2420b..b54286d 100644 --- a/vendor/memcury.h +++ b/vendor/memcury.h @@ -758,7 +758,7 @@ return Scanner(add); } - static auto FindPointerRef(void* Pointer) -> Scanner // credit me and ender + static auto FindPointerRef(void* Pointer, int useRefNum = 0, bool bUseFirstResult = false) -> Scanner // credit me and ender { PE::Address add{ nullptr }; @@ -766,6 +766,8 @@ const auto scanBytes = reinterpret_cast(textSection.GetSectionStart().Get()); + int aa = 0; + // scan only text section for (DWORD i = 0x0; i < textSection.GetSectionSize(); i++) { @@ -774,6 +776,12 @@ if (PE::Address(&scanBytes[i]).RelativeOffset(3).GetAs() == Pointer) { add = PE::Address(&scanBytes[i]); + + if (bUseFirstResult) + return Scanner(add); + + /* if (++aa > useRefNum) + break; */ } } @@ -782,6 +790,12 @@ if (PE::Address(&scanBytes[i]).RelativeOffset(1).GetAs() == Pointer) { add = PE::Address(&scanBytes[i]); + + if (bUseFirstResult) + return Scanner(add); + + /* if (++aa > useRefNum) + break; */ } } } @@ -1394,5 +1408,14 @@ { auto FunctionPtr = Memcury::Scanner::FindStringRef(Name, true, skip).ScanFor({ 0x48, 0x8D, 0x0D }).RelativeOffset(3).GetAs(); - return Memcury::Scanner::FindPointerRef(FunctionPtr).ScanFor(Bytes, false).Get(); + auto PtrRef = Memcury::Scanner::FindPointerRef(FunctionPtr); + + /* if (!PtrRef.Get() || PtrRef.Get() == __int64(FunctionPtr)) + { + std::wstring NameWStr = std::wstring(Name); + LOG_WARN(LogMemory, "Failed to find pointer reference for {}", std::string(NameWStr.begin(), NameWStr.end())); + return 0; + } */ + + return PtrRef.ScanFor(Bytes, false).Get(); } \ No newline at end of file