From 5bfe3a6179e54c019aa12e57429e82769207280b Mon Sep 17 00:00:00 2001 From: Gray <84999745+Milxnor@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:11:02 -0400 Subject: [PATCH] Give bot skins --- Project Reboot 3.0/AIController.h | 8 + Project Reboot 3.0/CurveTable.h | 2 +- .../FortAthenaAIBotController.h | 14 + Project Reboot 3.0/FortAthenaMutator.h | 2 +- Project Reboot 3.0/FortGameModeAthena.cpp | 63 ++- Project Reboot 3.0/FortGameModeAthena.h | 12 +- Project Reboot 3.0/FortPlayerController.cpp | 3 +- .../FortServerBotManagerAthena.h | 7 + Project Reboot 3.0/Pawn.h | 7 + Project Reboot 3.0/Project Reboot 3.0.vcxproj | 5 + .../Project Reboot 3.0.vcxproj.filters | 6 + Project Reboot 3.0/ai.h | 41 +- Project Reboot 3.0/bots.h | 380 +++++++++--------- Project Reboot 3.0/commands.cpp | 5 +- Project Reboot 3.0/dllmain.cpp | 26 +- Project Reboot 3.0/extra.cpp | 10 +- Project Reboot 3.0/finder.h | 7 +- Project Reboot 3.0/inc.h | 4 +- vendor/memcury.h | 13 +- 19 files changed, 388 insertions(+), 227 deletions(-) create mode 100644 Project Reboot 3.0/AIController.h create mode 100644 Project Reboot 3.0/FortAthenaAIBotController.h diff --git a/Project Reboot 3.0/AIController.h b/Project Reboot 3.0/AIController.h new file mode 100644 index 0000000..9d4ab28 --- /dev/null +++ b/Project Reboot 3.0/AIController.h @@ -0,0 +1,8 @@ +#pragma once + +#include "Controller.h" + +class AAIController : public AController +{ +public: +}; \ No newline at end of file diff --git a/Project Reboot 3.0/CurveTable.h b/Project Reboot 3.0/CurveTable.h index ecba384..35d578e 100644 --- a/Project Reboot 3.0/CurveTable.h +++ b/Project Reboot 3.0/CurveTable.h @@ -42,7 +42,7 @@ class UCurveTable : public UObject public: static int GetCurveTableSize() { - static auto CurveTableClass = FindObject("/Script/Engine.CurveTable"); + static auto CurveTableClass = FindObject(L"/Script/Engine.CurveTable"); return CurveTableClass->GetPropertiesSize(); } diff --git a/Project Reboot 3.0/FortAthenaAIBotController.h b/Project Reboot 3.0/FortAthenaAIBotController.h new file mode 100644 index 0000000..e5c2e75 --- /dev/null +++ b/Project Reboot 3.0/FortAthenaAIBotController.h @@ -0,0 +1,14 @@ +#pragma once + +#include "reboot.h" +#include "AIController.h" + +class AFortAthenaAIBotController : public AAIController +{ +public: + static UClass* StaticClass() + { + static auto Class = FindObject(L"/Script/FortniteGame.FortAthenaAIBotController"); + return Class; + } +}; \ No newline at end of file diff --git a/Project Reboot 3.0/FortAthenaMutator.h b/Project Reboot 3.0/FortAthenaMutator.h index 4edc366..0cfdd09 100644 --- a/Project Reboot 3.0/FortAthenaMutator.h +++ b/Project Reboot 3.0/FortAthenaMutator.h @@ -15,7 +15,7 @@ class AFortAthenaMutator : public AActor // AFortGameplayMutator public: static UClass* StaticClass() { - static auto Class = FindObject("/Script/FortniteGame.FortAthenaMutator"); + static auto Class = FindObject(L"/Script/FortniteGame.FortAthenaMutator"); return Class; } }; diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 0d314dd..cb165ae 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -241,11 +241,22 @@ void AFortGameModeAthena::OverrideSupplyDrop(AFortGameStateAthena* GameState, UC return; } - static auto SupplyDropInfoListOffset = MapInfo->GetOffset("SupplyDropInfoList"); - auto& SupplyDropInfoList = MapInfo->Get>(SupplyDropInfoListOffset); + static auto SupplyDropInfoListOffset = MapInfo->GetOffset("SupplyDropInfoList", false); - static auto SupplyDropClassOffset = SupplyDropInfoList.at(0)->GetOffset("SupplyDropClass"); - SupplyDropInfoList.at(0)->Get>(SupplyDropClassOffset) = OverrideSupplyDropBusClass; + if (SupplyDropInfoListOffset == -1) + return; + + auto& SupplyDropInfoList = MapInfo->Get>(SupplyDropInfoListOffset); + auto FirstSupplyDropInfo = SupplyDropInfoList.at(0); + + if (!FirstSupplyDropInfo) + { + LOG_WARN(LogGame, "No FirstSupplyDropInfo!"); + return; + } + + static auto SupplyDropClassOffset = FirstSupplyDropInfo->GetOffset("SupplyDropClass"); + FirstSupplyDropInfo->Get>(SupplyDropClassOffset) = OverrideSupplyDropBusClass; LOG_INFO(LogGame, "Overridden SupplyDropClass: {}", OverrideSupplyDropBusClass->GetFullName()); } @@ -283,6 +294,15 @@ void AFortGameModeAthena::OnAircraftEnteredDropZoneHook(AFortGameModeAthena* Gam } } +void SetupEverythingAI() // find better name lol +{ + PlayerBot::InitializeBotClasses(); + // SetupAIGoalManager(); + // SetupAIDirector(); + SetupServerBotManager(); + // SetupNavConfig(UKismetStringLibrary::Conv_StringToName(L"MANG")); +} + bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* GameMode) { Globals::bHitReadyToStartMatch = true; @@ -348,14 +368,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game LOG_INFO(LogDev, "Presetup!"); - if (false) - { - SetupAIGoalManager(); - SetupAIDirector(); - SetupServerBotManager(); - } - // SetupNavConfig(UKismetStringLibrary::Conv_StringToName(L"MANG")); - /* static auto WorldManagerOffset = GameState->GetOffset("WorldManager", false); @@ -402,12 +414,14 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game } else { - if (Fortnite_Version >= 4.1) // ???? + if (Fortnite_Version > 4.0) // bruh { SetPlaylist(PlaylistToUse, true); auto CurrentPlaylist = GameState->GetCurrentPlaylist(); LOG_INFO(LogDev, "Set playlist to {}!", CurrentPlaylist->IsValidLowLevel() ? CurrentPlaylist->GetFullName() : "Invalid"); + + SetupEverythingAI(); } } } @@ -674,7 +688,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game static int LastNum5 = 1; - if (AmountOfRestarts != LastNum5 && LastNum6 == AmountOfRestarts) // Make sure we loaded the event. + if (AmountOfRestarts != LastNum5 && LastNum6 == AmountOfRestarts) // Make sure we loaded the event successfully. { LastNum5 = AmountOfRestarts; @@ -706,7 +720,9 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game auto MapInfo = GameState->GetMapInfo(); - if (Engine_Version >= 421 && !MapInfo) + if (Engine_Version >= 421 && // todo recheck this version + !MapInfo + ) return false; static int LastNum = 1; @@ -717,8 +733,11 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game LOG_INFO(LogDev, "Initializing!"); - if (Fortnite_Version == 3) + if (Fortnite_Version >= 3.5 && Fortnite_Version <= 4) // todo check 3.4 + { SetPlaylist(GetPlaylistToUse(), true); + SetupEverythingAI(); + } LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode)); @@ -1531,6 +1550,18 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena if (PlayerAbilitySet && Fortnite_Version != 12.00) { PlayerAbilitySet->GiveToAbilitySystem(AbilitySystemComponent); + + if (Fortnite_Version >= 21) + { +#if 0 + static auto BGAClass = FindObject(L"/Script/Engine.BlueprintGeneratedClass"); + auto TacticalSprintClass = LoadObject("/TacticalSprint/Gameplay/GA_Athena_GrantTacticalSprint.GA_Athena_GrantTacticalSprint_C", BGAClass); + AbilitySystemComponent->GiveAbilityEasy(TacticalSprintClass); +#else + auto TacticalSprintAbilitySet = LoadObject("/TacticalSprint/Gameplay/AS_TacticalSprint.AS_TacticalSprint"); + // TacticalSprintAbilitySet->GiveToAbilitySystem(AbilitySystemComponent); +#endif + } } static auto PlayerCameraManagerOffset = NewPlayer->GetOffset("PlayerCameraManager"); diff --git a/Project Reboot 3.0/FortGameModeAthena.h b/Project Reboot 3.0/FortGameModeAthena.h index dd3303f..853a427 100644 --- a/Project Reboot 3.0/FortGameModeAthena.h +++ b/Project Reboot 3.0/FortGameModeAthena.h @@ -10,6 +10,7 @@ #include "FortAbilitySet.h" #include "FortPlayerControllerAthena.h" #include "FortItemDefinition.h" +#include "FortServerBotManagerAthena.h" struct FAircraftFlightInfo { @@ -82,9 +83,8 @@ static inline UFortAbilitySet* GetPlayerAbilitySet() { // There are some variables that contain this but it changes through versions soo.. - static auto GameplayAbilitySet = (UFortAbilitySet*)(Fortnite_Version >= 8.30 - ? LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer", UFortAbilitySet::StaticClass()) - : LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer", UFortAbilitySet::StaticClass())); + static auto GameplayAbilitySet = (Fortnite_Version >= 8.30 ? LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") + : LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer")); return GameplayAbilitySet; } @@ -251,6 +251,12 @@ public: return Get(SafeZoneIndicatorOffset); } + UFortServerBotManagerAthena*& GetServerBotManager() + { + static auto ServerBotManagerOffset = GetOffset("ServerBotManager"); + return Get(ServerBotManagerOffset); + } + AFortGameStateAthena* GetGameStateAthena() { return (AFortGameStateAthena*)GetGameState(); diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index c7c9b6f..e9d83f3 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -1817,7 +1817,8 @@ void AFortPlayerController::ServerEndEditingBuildingActorHook(AFortPlayerControl if (auto EditTool = Cast(Pawn->GetCurrentWeapon())) { EditTool->SetEditActor(nullptr); + // PlayerController->ClientForceCancelBuildingTool(); } - PlayerController->ClientForceCancelBuildingTool(); + // PlayerController->ClientForceCancelBuildingTool(); } diff --git a/Project Reboot 3.0/FortServerBotManagerAthena.h b/Project Reboot 3.0/FortServerBotManagerAthena.h index 67e409e..121595f 100644 --- a/Project Reboot 3.0/FortServerBotManagerAthena.h +++ b/Project Reboot 3.0/FortServerBotManagerAthena.h @@ -3,6 +3,7 @@ #include "Object.h" #include "FortPlayerPawnAthena.h" #include "FortAthenaAIBotCustomizationData.h" +#include "FortAthenaMutator_Bots.h" struct FFortAthenaAIBotRunTimeCustomizationData { @@ -16,5 +17,11 @@ class UFortServerBotManagerAthena : public UObject public: static inline AFortPlayerPawnAthena* (*SpawnBotOriginal)(UFortServerBotManagerAthena* BotManager, FVector InSpawnLocation, FRotator InSpawnRotation, UFortAthenaAIBotCustomizationData* InBotData, FFortAthenaAIBotRunTimeCustomizationData InRuntimeBotData); + AFortAthenaMutator_Bots*& GetCachedBotMutator() + { + static auto CachedBotMutatorOffset = GetOffset("CachedBotMutator"); + return Get(CachedBotMutatorOffset); + } + static AFortPlayerPawnAthena* SpawnBotHook(UFortServerBotManagerAthena* BotManager, FVector& InSpawnLocation, FRotator& InSpawnRotation, UFortAthenaAIBotCustomizationData* InBotData, FFortAthenaAIBotRunTimeCustomizationData* InRuntimeBotData); }; \ No newline at end of file diff --git a/Project Reboot 3.0/Pawn.h b/Project Reboot 3.0/Pawn.h index 40eadf2..0a10f6b 100644 --- a/Project Reboot 3.0/Pawn.h +++ b/Project Reboot 3.0/Pawn.h @@ -1,6 +1,7 @@ #pragma once #include "Actor.h" +#include "TSubClassOf.h" class APawn : public AActor { @@ -16,4 +17,10 @@ public: static auto ControllerOffset = GetOffset("Controller"); return Get(ControllerOffset); } + + TSubclassOf GetAIControllerClass() + { + static auto AIControllerClassOffset = GetOffset("AIControllerClass"); + return Get>(AIControllerClassOffset); + } }; \ 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 a3e5014..cf4b9fd 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -70,6 +70,9 @@ + + $(ProjectName) + Level3 @@ -274,6 +277,7 @@ + @@ -328,6 +332,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 c9c40ca..4eddaf0 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -978,6 +978,12 @@ FortniteGame\Source\FortniteGame\Public\AI + + FortniteGame\Source\FortniteGame\Public\AI + + + Engine\Source\Runtime\AIModule\Classes + diff --git a/Project Reboot 3.0/ai.h b/Project Reboot 3.0/ai.h index 2c9af18..5931cdf 100644 --- a/Project Reboot 3.0/ai.h +++ b/Project Reboot 3.0/ai.h @@ -105,6 +105,27 @@ static bool SetNavigationSystem(AAthenaNavSystemConfigOverride* NavSystemOverrid return true; } +static inline AFortAthenaMutator_Bots* SpawnBotMutator() //sets up all the classes for phoebe +{ + auto GameState = Cast(GetWorld()->GetGameState()); + auto GameMode = Cast(GetWorld()->GetGameMode()); + + static auto BGAClass = FindObject(L"/Script/Engine.BlueprintGeneratedClass"); + static auto PhoebeMutatorClass = LoadObject(L"/Game/Athena/AI/Phoebe/BP_Phoebe_Mutator.BP_Phoebe_Mutator_C", BGAClass); + + auto BotMutator = GetWorld()->SpawnActor(PhoebeMutatorClass); + + static auto CachedGameModeOffset = BotMutator->GetOffset("CachedGameMode"); + BotMutator->Get(CachedGameModeOffset) = GameMode; + + static auto CachedGameStateOffset = BotMutator->GetOffset("CachedGameState", false); + + if (CachedGameStateOffset != -1) + BotMutator->Get(CachedGameStateOffset) = GameState; + + return BotMutator; +} + static void SetupServerBotManager() { auto GameState = Cast(GetWorld()->GetGameState()); @@ -115,11 +136,10 @@ static void SetupServerBotManager() if (!FortServerBotManagerClass) return; - static auto ServerBotManagerOffset = GameMode->GetOffset("ServerBotManager"); - UObject*& ServerBotManager = GameMode->Get(ServerBotManagerOffset); + UFortServerBotManagerAthena*& ServerBotManager = GameMode->GetServerBotManager(); if (!ServerBotManager) - ServerBotManager = UGameplayStatics::SpawnObject(FortServerBotManagerClass, GetTransientPackage()); + ServerBotManager = (UFortServerBotManagerAthena*)UGameplayStatics::SpawnObject(FortServerBotManagerClass, GetTransientPackage()); if (ServerBotManager) { @@ -132,7 +152,20 @@ static void SetupServerBotManager() ServerBotManager->Get(CachedGameStateOffset) = GameState; static auto CachedBotMutatorOffset = ServerBotManager->GetOffset("CachedBotMutator"); - ServerBotManager->Get(CachedBotMutatorOffset) = FindFirstMutator(FindObject(L"/Script/FortniteGame.FortAthenaMutator_Bots")); + auto BotMutator = FindFirstMutator(FindObject(L"/Script/FortniteGame.FortAthenaMutator_Bots")); + + if (!BotMutator) + { + LOG_WARN(LogAI, "Failed to find Bot Mutator! Spawning it.."); + BotMutator = SpawnBotMutator(); + } + + if (!BotMutator) + { + LOG_ERROR(LogAI, "Failed to spawn or find Bot Mutator!"); + } + + ServerBotManager->Get(CachedBotMutatorOffset) = BotMutator; } } diff --git a/Project Reboot 3.0/bots.h b/Project Reboot 3.0/bots.h index fcf9e8a..a056835 100644 --- a/Project Reboot 3.0/bots.h +++ b/Project Reboot 3.0/bots.h @@ -2,6 +2,7 @@ #include "FortGameModeAthena.h" #include "OnlineReplStructs.h" +#include "FortAthenaAIBotController.h" #include "BuildingContainer.h" class BotPOI @@ -21,7 +22,13 @@ public: class PlayerBot { public: - AController* Controller = nullptr; + static inline UClass* PawnClass = nullptr; + static inline UClass* ControllerClass = nullptr; + + AController* Controller = nullptr; // This can be 1. AFortAthenaAIBotController OR AFortPlayerControllerAthena + bool bIsAthenaController = false; + AFortPlayerPawnAthena* Pawn = nullptr; + AFortPlayerStateAthena* PlayerState = nullptr; BotPOIEncounter currentBotEncounter; int TotalPlayersEncountered; std::vector POIsTraveled; @@ -38,64 +45,180 @@ public: } - void Initialize(const FTransform& SpawnTransform) + static bool ShouldUseAIBotController() { - auto GameState = Cast(GetWorld()->GetGameState()); - auto GameMode = Cast(GetWorld()->GetGameMode()); + return Fortnite_Version >= 11 && Engine_Version < 500; + } - static UClass* PawnClass = nullptr; - static UClass* ControllerClass = nullptr; + static void InitializeBotClasses() + { + static auto BlueprintGeneratedClassClass = FindObject(L"/Script/Engine.BlueprintGeneratedClass"); - bool bUsePhoebeClasses = false; - - if (!PawnClass) + if (!ShouldUseAIBotController()) { - if (!bUsePhoebeClasses) - PawnClass = FindObject(L"/Game/Athena/PlayerPawn_Athena.PlayerPawn_Athena_C"); - else - PawnClass = FindObject(L"/Game/Athena/AI/Phoebe/BP_PlayerPawn_Athena_Phoebe.BP_PlayerPawn_Athena_Phoebe_C"); + PawnClass = FindObject(L"/Game/Athena/PlayerPawn_Athena.PlayerPawn_Athena_C"); + ControllerClass = AFortPlayerControllerAthena::StaticClass(); + } + else + { + PawnClass = LoadObject(L"/Game/Athena/AI/Phoebe/BP_PlayerPawn_Athena_Phoebe.BP_PlayerPawn_Athena_Phoebe_C", BlueprintGeneratedClassClass); + + // ControllerClass = PawnClass->CreateDefaultObject()->GetAIControllerClass(); } - if (!ControllerClass) - { - if (!bUsePhoebeClasses) - ControllerClass = AFortPlayerControllerAthena::StaticClass(); - else - ControllerClass = FindObject(L"/Game/Athena/AI/Phoebe/BP_PhoebePlayerController.BP_PhoebePlayerController_C"); - } - - if (!ControllerClass || !PawnClass) + if (/* !ControllerClass + || */ !PawnClass + ) { LOG_ERROR(LogBots, "Failed to find a class for the bots!"); return; } + } - static auto FortAthenaAIBotControllerClass = FindObject(L"/Script/FortniteGame.FortAthenaAIBotController"); + static bool IsReadyToSpawnBot() + { + return PawnClass; + } - Controller = GetWorld()->SpawnActor(ControllerClass); - AFortPlayerPawnAthena* Pawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn)); - AFortPlayerStateAthena* PlayerState = Cast(Controller->GetPlayerState()); + void SetupInventory() + { + auto GameState = Cast(GetWorld()->GetGameState()); + auto GameMode = Cast(GetWorld()->GetGameMode()); - if (!Pawn || !PlayerState) - return; - - bool bUseOverrideName = false; - - FString NewName; - - if (bUseOverrideName) + if (!ShouldUseAIBotController()) // TODO REWRITE { - NewName = L"Override"; + AFortInventory** Inventory = nullptr; + + if (auto FortPlayerController = Cast(Controller)) + { + Inventory = &FortPlayerController->GetWorldInventory(); + } + else + { + if (auto FortAthenaAIBotController = Cast(Controller)) + { + static auto InventoryOffset = Controller->GetOffset("Inventory"); + Inventory = Controller->GetPtr(InventoryOffset); + } + } + + if (!Inventory) + { + LOG_ERROR(LogBots, "No inventory pointer!"); + + Pawn->K2_DestroyActor(); + Controller->K2_DestroyActor(); + return; + } + + static auto FortInventoryClass = FindObject(L"/Script/FortniteGame.FortInventory"); // AFortInventory::StaticClass() + *Inventory = GetWorld()->SpawnActor(FortInventoryClass, FTransform{}, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AlwaysSpawn, false, Controller)); + + if (!*Inventory) + { + LOG_ERROR(LogBots, "Failed to spawn Inventory!"); + + Pawn->K2_DestroyActor(); + Controller->K2_DestroyActor(); + return; + } + + (*Inventory)->GetInventoryType() = EFortInventoryType::World; + + if (auto FortPlayerController = Cast(Controller)) + { + static auto bHasInitializedWorldInventoryOffset = FortPlayerController->GetOffset("bHasInitializedWorldInventory"); + FortPlayerController->Get(bHasInitializedWorldInventoryOffset) = true; + } + + // if (false) + { + if (Inventory) + { + auto& StartingItems = GameMode->GetStartingItems(); + + for (int i = 0; i < StartingItems.Num(); ++i) + { + auto& StartingItem = StartingItems.at(i); + + (*Inventory)->AddItem(StartingItem.GetItem(), nullptr, StartingItem.GetCount()); + } + + if (auto FortPlayerController = Cast(Controller)) + { + UFortItem* PickaxeInstance = FortPlayerController->AddPickaxeToInventory(); + + if (PickaxeInstance) + { + FortPlayerController->ServerExecuteInventoryItemHook(FortPlayerController, PickaxeInstance->GetItemEntry()->GetItemGuid()); + } + } + + (*Inventory)->Update(); + } + } + } + } + + void Initialize(const FTransform& SpawnTransform, AActor* InSpawnLocator) + { + auto GameState = Cast(GetWorld()->GetGameState()); + auto GameMode = Cast(GetWorld()->GetGameMode()); + + if (!IsReadyToSpawnBot()) + { + LOG_ERROR(LogBots, "We are not prepared to spawn a bot!"); + return; + } + + if (!ShouldUseAIBotController()) + { + Controller = GetWorld()->SpawnActor(ControllerClass); + Pawn = GetWorld()->SpawnActor(PawnClass, SpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn)); + PlayerState = Cast(Controller->GetPlayerState()); } else { - static int CurrentBotNum = 1; - auto BotNumWStr = std::to_wstring(CurrentBotNum++); - NewName = (L"RebootBot" + BotNumWStr).c_str(); + Pawn = GameMode->GetServerBotManager()->GetCachedBotMutator()->SpawnBot(PawnClass, InSpawnLocator, SpawnTransform.Translation, SpawnTransform.Rotation.Rotator(), false); + + if (Fortnite_Version < 17) + Controller = Cast(Pawn->GetController()); + else + Controller = GetWorld()->SpawnActor(Pawn->GetAIControllerClass()); + + PlayerState = Cast(Controller->GetPlayerState()); } - if (auto PlayerController = Cast(Controller)) - PlayerController->ServerChangeName(NewName); + if (!Controller || !Pawn || !PlayerState) + { + LOG_ERROR(LogBots, "Failed to spawn controller, pawn or playerstate ({} {})!", bool(__int64(Controller)), bool(__int64(Pawn)), bool(__int64(Controller->GetPlayerState()))); + return; + } + + PlayerState->SetIsBot(true); + + if (Controller->GetPawn() != Pawn) + { + Controller->Possess(Pawn); + } + + static int CurrentBotNum = 1; + auto BotNumWStr = std::to_wstring(CurrentBotNum++); + FString NewName = (L"Jimmy" + BotNumWStr).c_str(); + + if (true || + Fortnite_Version < 9 + ) + { + if (auto PlayerController = Cast(Controller)) + { + PlayerController->ServerChangeName(NewName); + } + } + else + { + GameMode->ChangeName(Controller, NewName, true); + } PlayerState->OnRep_PlayerName(); @@ -108,111 +231,11 @@ public: GameState->AddPlayerStateToGameMemberInfo(PlayerState); - PlayerState->SetIsBot(true); - - /* - - static auto FortRegisteredPlayerInfoClass = FindObject("/Script/FortniteGame.FortRegisteredPlayerInfo"); - static auto MyPlayerInfoOffset = PlayerController->GetOffset("MyPlayerInfo"); - PlayerController->Get(MyPlayerInfoOffset) = UGameplayStatics::SpawnObject(FortRegisteredPlayerInfoClass, PlayerController); - - if (!PlayerController->Get(MyPlayerInfoOffset)) - { - LOG_ERROR(LogBots, "Failed to spawn PlayerInfo!"); - - Pawn->K2_DestroyActor(); - PlayerController->K2_DestroyActor(); - return nullptr; - } - - auto& PlayerInfo = PlayerController->Get(MyPlayerInfoOffset); - - static auto UniqueIdOffset = PlayerState->GetOffset("UniqueId"); - static auto PlayerInfo_PlayerNameOffset = PlayerInfo->GetOffset("PlayerName"); - static auto PlayerIDOffset = PlayerInfo->GetOffset("PlayerID"); - PlayerInfo->GetPtr(PlayerIDOffset)->CopyFromAnotherUniqueId(PlayerState->GetPtr(UniqueIdOffset)); - PlayerInfo->Get(PlayerInfo_PlayerNameOffset) = PlayerState->GetPlayerName(); - - */ - Controller->Possess(Pawn); Pawn->SetHealth(100); Pawn->SetMaxHealth(100); - AFortInventory** Inventory = nullptr; - - if (auto FortPlayerController = Cast(Controller)) - { - Inventory = &FortPlayerController->GetWorldInventory(); - } - else - { - if (Controller->IsA(FortAthenaAIBotControllerClass)) - { - static auto InventoryOffset = Controller->GetOffset("Inventory"); - Inventory = Controller->GetPtr(InventoryOffset); - } - } - - if (!Inventory) - { - LOG_ERROR(LogBots, "No inventory pointer!"); - - Pawn->K2_DestroyActor(); - Controller->K2_DestroyActor(); - return; - } - - FTransform InventorySpawnTransform{}; - - static auto FortInventoryClass = FindObject(L"/Script/FortniteGame.FortInventory"); // AFortInventory::StaticClass() - *Inventory = GetWorld()->SpawnActor(FortInventoryClass, InventorySpawnTransform, CreateSpawnParameters(ESpawnActorCollisionHandlingMethod::AlwaysSpawn, false, Controller)); - - if (!*Inventory) - { - LOG_ERROR(LogBots, "Failed to spawn Inventory!"); - - Pawn->K2_DestroyActor(); - Controller->K2_DestroyActor(); - return; - } - - (*Inventory)->GetInventoryType() = EFortInventoryType::World; - - if (auto FortPlayerController = Cast(Controller)) - { - static auto bHasInitializedWorldInventoryOffset = FortPlayerController->GetOffset("bHasInitializedWorldInventory"); - FortPlayerController->Get(bHasInitializedWorldInventoryOffset) = true; - } - - // if (false) - { - if (Inventory) - { - auto& StartingItems = GameMode->GetStartingItems(); - - for (int i = 0; i < StartingItems.Num(); ++i) - { - auto& StartingItem = StartingItems.at(i); - - (*Inventory)->AddItem(StartingItem.GetItem(), nullptr, StartingItem.GetCount()); - } - - if (auto FortPlayerController = Cast(Controller)) - { - UFortItem* PickaxeInstance = FortPlayerController->AddPickaxeToInventory(); - - if (PickaxeInstance) - { - FortPlayerController->ServerExecuteInventoryItemHook(FortPlayerController, PickaxeInstance->GetItemEntry()->GetItemGuid()); - } - } - - (*Inventory)->Update(); - } - } - auto PlayerAbilitySet = GetPlayerAbilitySet(); auto AbilitySystemComponent = PlayerState->GetAbilitySystemComponent(); @@ -221,13 +244,13 @@ public: PlayerAbilitySet->GiveToAbilitySystem(AbilitySystemComponent); } + SetupInventory(); + // PlayerController->GetCosmeticLoadout()->GetCharacter() = FindObject("/Game/Athena/Items/Cosmetics/Characters/CID_263_Athena_Commando_F_MadCommander.CID_263_Athena_Commando_F_MadCommander"); // Pawn->GetCosmeticLoadout()->GetCharacter() = PlayerController->GetCosmeticLoadout()->GetCharacter(); // PlayerController->ApplyCosmeticLoadout(); - /* - auto AllHeroTypes = GetAllObjectsOfClass(FindObject(L"/Script/FortniteGame.FortHeroType")); std::vector AthenaHeroTypes; @@ -249,38 +272,19 @@ public: static auto HeroTypeOffset = PlayerState->GetOffset("HeroType"); if (HeroTypeOffset != -1) + { PlayerState->Get(HeroTypeOffset) = HeroType; - - static auto OwningGameInstanceOffset = GetWorld()->GetOffset("OwningGameInstance"); - auto OwningGameInstance = GetWorld()->Get(OwningGameInstanceOffset); - - static auto RegisteredPlayersOffset = OwningGameInstance->GetOffset("RegisteredPlayers"); - auto& RegisteredPlayers = OwningGameInstance->Get>(RegisteredPlayersOffset); - - static auto FortRegisteredPlayerInfoClass = FindObject("/Script/FortniteGame.FortRegisteredPlayerInfo"); - - auto NewPlayerInfo = UGameplayStatics::SpawnObject(FortRegisteredPlayerInfoClass, Controller); - static auto PlayerIDOffset = NewPlayerInfo->GetOffset("PlayerID"); - - static auto UniqueIdOffset = PlayerState->GetOffset("UniqueId"); - auto PlayerStateUniqueId = PlayerState->GetPtr(UniqueIdOffset); - - NewPlayerInfo->GetPtr(PlayerIDOffset)->CopyFromAnotherUniqueId(PlayerStateUniqueId); - - static auto MyPlayerInfoOffset = Controller->GetOffset("MyPlayerInfo"); - Controller->Get(MyPlayerInfoOffset) = NewPlayerInfo; - - RegisteredPlayers.Add(NewPlayerInfo); + } ApplyHID(Pawn, HeroType, true); - */ - GameState->GetPlayersLeft()++; GameState->OnRep_PlayersLeft(); if (auto FortPlayerControllerAthena = Cast(Controller)) GameMode->GetAlivePlayers().Add(FortPlayerControllerAthena); + + LOG_INFO(LogDev, "Finished spawning bot!") } }; @@ -288,10 +292,10 @@ static inline std::vector AllPlayerBotsToTick; namespace Bots { - static AController* SpawnBot(FTransform SpawnTransform) + static AController* SpawnBot(FTransform SpawnTransform, AActor* InSpawnLocator) { auto playerBot = PlayerBot(); - playerBot.Initialize(SpawnTransform); + playerBot.Initialize(SpawnTransform, InSpawnLocator); AllPlayerBotsToTick.push_back(playerBot); return playerBot.Controller; } @@ -303,27 +307,36 @@ namespace Bots auto GameState = Cast(GetWorld()->GetGameState()); auto GameMode = Cast(GetWorld()->GetGameMode()); + static auto FortPlayerStartCreativeClass = FindObject(L"/Script/FortniteGame.FortPlayerStartCreative"); + static auto FortPlayerStartWarmupClass = FindObject(L"/Script/FortniteGame.FortPlayerStartWarmup"); + TArray PlayerStarts = UGameplayStatics::GetAllActorsOfClass(GetWorld(), Globals::bCreative ? FortPlayerStartCreativeClass : FortPlayerStartWarmupClass); + + int ActorsNum = PlayerStarts.Num(); + + // Actors.Free(); + + if (ActorsNum == 0) + { + // LOG_INFO(LogDev, "No Actors!"); + return; + } + + // Find playerstart (scuffed) + for (int i = 0; i < AmountOfBots; ++i) { - FTransform SpawnTransform{}; - SpawnTransform.Translation = FVector(1, 1, 10000); - SpawnTransform.Rotation = FQuat(); - SpawnTransform.Scale3D = FVector(1, 1, 1); - - auto NewBot = SpawnBot(SpawnTransform); - auto PlayerStart = GameMode->K2_FindPlayerStart(NewBot, NewBot->GetPlayerState()->GetPlayerName()); // i dont think this works + AActor* PlayerStart = PlayerStarts.at(std::rand() % (PlayerStarts.size() - 1)); if (!PlayerStart) { - LOG_ERROR(LogBots, "Failed to find PlayerStart for bot!"); - NewBot->GetPawn()->K2_DestroyActor(); - NewBot->K2_DestroyActor(); - continue; + return; } - NewBot->TeleportTo(PlayerStart->GetActorLocation(), FRotator()); + auto NewBot = SpawnBot(PlayerStart->GetTransform(), PlayerStart); NewBot->SetCanBeDamaged(Fortnite_Version < 7); // idk lol for spawn island } + + return; } static void Tick() @@ -346,9 +359,14 @@ namespace Bots auto CurrentPawn = CurrentPlayer->GetPawn(); + if (CurrentPawn->IsActorBeingDestroyed()) + continue; + auto CurrentPlayerState = Cast(CurrentPlayer->GetPlayerState()); - if (!CurrentPlayerState || !CurrentPlayerState->IsBot()) + if (!CurrentPlayerState + // || !CurrentPlayerState->IsBot() + ) continue; if (GameState->GetGamePhase() == EAthenaGamePhase::Warmup) @@ -362,7 +380,7 @@ namespace Bots } */ } - if (CurrentPlayerState->IsInAircraft() && !CurrentPlayerState->HasThankedBusDriver()) + if (PlayerBot.bIsAthenaController && CurrentPlayerState->IsInAircraft() && !CurrentPlayerState->HasThankedBusDriver()) { static auto ServerThankBusDriverFn = FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.ServerThankBusDriver"); CurrentPlayer->ProcessEvent(ServerThankBusDriverFn); diff --git a/Project Reboot 3.0/commands.cpp b/Project Reboot 3.0/commands.cpp index fc5209f..ff9ad9b 100644 --- a/Project Reboot 3.0/commands.cpp +++ b/Project Reboot 3.0/commands.cpp @@ -789,7 +789,7 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) Transform.Translation = Loc; Transform.Scale3D = FVector(1, 1, 1); - auto NewActor = Bots::SpawnBot(Transform); + auto NewActor = Bots::SpawnBot(Transform, Pawn); if (!NewActor) { @@ -801,7 +801,8 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) } } - SendMessageToConsole(PlayerController, L"Summoned!"); + if (AmountSpawned > 0) + SendMessageToConsole(PlayerController, L"Summoned!"); } else if (Command == "sethealth") { diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index edb2ae9..ebd1c34 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -1005,24 +1005,30 @@ DWORD WINAPI Main(LPVOID) if (std::floor(Fortnite_Version) == 4) { - auto RetrieveCharacterPartsAddr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 0F B6 FA 48 8B D9 FF 90 ? ? ? ? 48 8B C8 E8 ? ? ? ? 84 C0 74 0D 33 C0 48 8B 5C 24 ? 48 83 C4 20 5F").Get(); + auto RetrieveCharacterPartsAddr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B 01 0F B6 FA 48 8B D9 FF 90 ? ? ? ? 48 8B C8 E8 ? ? ? ? 84 C0 74 0D 33 C0 48 8B 5C 24 ? 48 83 C4 20 5F", false).Get(); + if (!RetrieveCharacterPartsAddr) + RetrieveCharacterPartsAddr = Memcury::Scanner::FindPattern("40 53 48 83 EC 20 48 8B 01 48 8B D9 FF 90 ? ? ? ? 48 8B C8 E8 ? ? ? ? 84 C0 74 08 33 C0 48 83 C4 20 5B C3 48 8B CB").Get(); // 4.0 + LOG_INFO(LogDev, "RetrieveCharacterPartsAddr: {}", RetrieveCharacterPartsAddr); - for (int i = 0; i < 400; i++) + if (RetrieveCharacterPartsAddr) { - if (*(uint8_t*)(RetrieveCharacterPartsAddr + i) == 0x74) // jz + for (int i = 0; i < 400; i++) { - DWORD dwProtection; - VirtualProtect((PVOID)(RetrieveCharacterPartsAddr + i), 1, PAGE_EXECUTE_READWRITE, &dwProtection); + if (*(uint8_t*)(RetrieveCharacterPartsAddr + i) == 0x74) // jz + { + DWORD dwProtection; + VirtualProtect((PVOID)(RetrieveCharacterPartsAddr + i), 1, PAGE_EXECUTE_READWRITE, &dwProtection); - *(uint8_t*)(RetrieveCharacterPartsAddr + i) = 0x75; // jnz + *(uint8_t*)(RetrieveCharacterPartsAddr + i) = 0x75; // jnz - DWORD dwTemp; - VirtualProtect((PVOID)(RetrieveCharacterPartsAddr + i), 1, dwProtection, &dwTemp); + DWORD dwTemp; + VirtualProtect((PVOID)(RetrieveCharacterPartsAddr + i), 1, dwProtection, &dwTemp); - LOG_INFO(LogDev, "Applied RetrieveCharacterParts patch!"); - break; + LOG_INFO(LogDev, "Applied RetrieveCharacterParts patch!"); + break; + } } } } diff --git a/Project Reboot 3.0/extra.cpp b/Project Reboot 3.0/extra.cpp index 38d3afc..606fc46 100644 --- a/Project Reboot 3.0/extra.cpp +++ b/Project Reboot 3.0/extra.cpp @@ -95,14 +95,18 @@ void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int OverridePhaseMa bFilledDurations = true; auto CurrentPlaylist = GameState->GetCurrentPlaylist(); - UCurveTable* FortGameData = nullptr; - static auto GameDataOffset = CurrentPlaylist->GetOffset("GameData"); - FortGameData = CurrentPlaylist ? CurrentPlaylist->Get>(GameDataOffset).Get() : nullptr; + UCurveTable* FortGameData = CurrentPlaylist ? CurrentPlaylist->Get>(GameDataOffset).Get() : nullptr; if (!FortGameData) FortGameData = FindObject(L"/Game/Balance/AthenaGameData.AthenaGameData"); + if (!FortGameData) + { + LOG_ERROR(LogZone, "Unable to get FortGameData."); + return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); + } + auto ShrinkTimeFName = UKismetStringLibrary::Conv_StringToName(L"Default.SafeZone.ShrinkTime"); auto HoldTimeFName = UKismetStringLibrary::Conv_StringToName(L"Default.SafeZone.WaitTime"); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index e6c787f..627a08e 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -585,8 +585,10 @@ static inline uint64 FindSetWorld() SetWorldIndex = 0x73; else if (Fortnite_Season >= 19 && Fortnite_Season < 21) SetWorldIndex = 0x7A; - if (Fortnite_Version == 20.40) + if (Fortnite_Season == 20) // 20.40 SetWorldIndex = 0x7B; + if (Fortnite_Season == 21) + SetWorldIndex = 0x7C; // 21.00 // static auto DefaultNetDriver = FindObject("/Script/Engine.Default__NetDriver"); return SetWorldIndex; @@ -606,6 +608,9 @@ static inline uint64 FindInitListen() static inline uint64 FindOnDamageServer() { + if (Fortnite_Version >= 20) // 8B 15 on name ref??? + return Memcury::Scanner::FindPattern("E8 ? ? ? ? 41 39 B4 24").RelativeOffset(1).Get(); // 20.40 (not 21.00) + auto Addr = FindFunctionCall(L"OnDamageServer", Engine_Version == 416 ? std::vector{ 0x4C, 0x89, 0x4C } : Engine_Version == 419 || Engine_Version >= 427 ? std::vector{ 0x48, 0x8B, 0xC4 } : std::vector{ 0x40, 0x55 } diff --git a/Project Reboot 3.0/inc.h b/Project Reboot 3.0/inc.h index 745b792..7ff98e1 100644 --- a/Project Reboot 3.0/inc.h +++ b/Project Reboot 3.0/inc.h @@ -21,9 +21,7 @@ extern inline double Fortnite_Version = 0; // For example, 4.1, 6.21, etc. // Pr extern inline int Fortnite_CL = 0; // #define PROD // this doesnt do anything besides remove processeventhook and some assert stuff -// DEPRACTERD ^^^ - - +// DEPRACTERD ^^^ (see Globals::bDeveloperMode) // #define ABOVE_S20 diff --git a/vendor/memcury.h b/vendor/memcury.h index f691aa1..2cc6fb3 100644 --- a/vendor/memcury.h +++ b/vendor/memcury.h @@ -960,6 +960,8 @@ { const auto scanBytes = _address.GetAs(); + bool bFound = false; + for (auto i = (forward ? 1 : -1); forward ? (i < 2048) : (i > -2048); forward ? i++ : i--) { bool found = true; @@ -971,7 +973,7 @@ if (currentOpcode == -1) continue; - // std::cout << std::format("[{} {}] 0x{:x}\n", i, k, currentOpcode); + // LOG_INFO(LogDev, "[{} 0x{:x}] 0x{:x}", i, __int64(&scanBytes[i]) - __int64(GetModuleHandleW(0)), currentOpcode); found = currentOpcode == scanBytes[i + k]; } @@ -984,10 +986,17 @@ return ScanFor(opcodesToFind, forward, toSkip - 1); } + bFound = true; + break; } } + if (!bFound) + { + LOG_ERROR(LogDev, "ScanFor failed!"); + } + return *this; } @@ -1439,6 +1448,8 @@ if (!NameRef) return 0; + LOG_INFO(LogDev, "FindFunctionCall NameRef: 0x{:x}", __int64(NameRef) - __int64(GetModuleHandleW(0))); + return Memcury::Scanner(NameRef).ScanFor(Bytes, false).Get(); }