#pragma once #include "reboot.h" #include "Actor.h" #include "SoftObjectPath.h" #include "KismetStringLibrary.h" #include "GameplayStatics.h" #include "FortPlayerPawn.h" #include "FortAthenaMutator.h" #include "FortPlayerController.h" #include "FortGameModeAthena.h" #include "FortGameStateAthena.h" #include "FortPlayerControllerAthena.h" using UNavigationSystemV1 = UObject; using UNavigationSystemConfig = UObject; using AAthenaNavSystemConfigOverride = UObject; using UAthenaNavSystem = UObject; using UAthenaNavSystemConfig = UObject; enum class EFNavigationSystemRunMode : uint8_t { InvalidMode = 0, GameMode = 1, EditorMode = 2, SimulationMode = 3, PIEMode = 4, FNavigationSystemRunMode_MAX = 5 }; enum class ENavSystemOverridePolicy : uint8_t { Override = 0, Append = 1, Skip = 2, ENavSystemOverridePolicy_MAX = 3 }; extern inline void (*NavSystemCleanUpOriginal)(UNavigationSystemV1*, uint8) = nullptr; extern inline void (*AddNavigationSystemToWorldOriginal)(UWorld& WorldOwner, EFNavigationSystemRunMode RunMode, UNavigationSystemConfig* NavigationSystemConfig, char bInitializeForWorld, char bOverridePreviousNavSys) = nullptr; static void SetNavigationSystem(AAthenaNavSystemConfigOverride* NavSystemOverride) { auto WorldSettings = GetWorld()->K2_GetWorldSettings(); NavSystemOverride->Get("OverridePolicy") = ENavSystemOverridePolicy::Append; WorldSettings->Get("NavigationSystemConfigOverride") = NavSystemOverride->Get("NavigationSystemConfig"); WorldSettings->Get("NavigationSystemConfig")->Get("bIsOverriden") = true; auto NavSystem = (UAthenaNavSystem*)GetWorld()->Get("NavigationSystem"); NavSystemCleanUpOriginal(NavSystem, 0); GetWorld()->Get("NavigationSystem") = nullptr; if (!NavSystemOverride->Get("NavigationSystemConfig")) return; auto& ClassPath = NavSystemOverride->Get("NavigationSystemConfig")->Get("NavigationSystemClass"); auto NewNavSystemClass = FindObject(ClassPath.AssetPathName.ToString()); if (!NewNavSystemClass) return; LOG_INFO(LogAI, "Setup navigation system."); AddNavigationSystemToWorldOriginal(*GetWorld(), EFNavigationSystemRunMode::GameMode, NavSystemOverride->Get("NavigationSystemConfig"), true, false); } static void SetupServerBotManager() { auto GameState = Cast(GetWorld()->GetGameState()); auto GameMode = Cast(GetWorld()->GetGameMode()); static auto FortServerBotManagerClass = FindObject("/Script/FortniteGame.FortServerBotManagerAthena"); // Is there a BP for this? // GameMode->ServerBotManagerClass if (!FortServerBotManagerClass) return; static auto ServerBotManagerOffset = GameMode->GetOffset("ServerBotManager"); UObject*& ServerBotManager = GameMode->Get(ServerBotManagerOffset); if (!ServerBotManager) ServerBotManager = UGameplayStatics::SpawnObject(FortServerBotManagerClass, GetTransientPackage()); if (ServerBotManager) { static auto CachedGameModeOffset = ServerBotManager->GetOffset("CachedGameMode"); ServerBotManager->Get(CachedGameModeOffset) = GameMode; static auto CachedGameStateOffset = ServerBotManager->GetOffset("CachedGameState"); ServerBotManager->Get(CachedGameStateOffset) = GameState; static auto CachedBotMutatorOffset = ServerBotManager->GetOffset("CachedBotMutator"); ServerBotManager->Get(CachedBotMutatorOffset) = FindFirstMutator(FindObject("/Script/FortniteGame.FortAthenaMutator_Bots")); } } static void SetupAIDirector() { auto GameState = Cast(GetWorld()->GetGameState()); auto GameMode = Cast(GetWorld()->GetGameMode()); static auto AIDirectorClass = FindObject("/Script/FortniteGame.AthenaAIDirector"); // Probably wrong class if (!AIDirectorClass) return; static auto AIDirectorOffset = GameMode->GetOffset("AIDirector"); if (!GameMode->Get(AIDirectorOffset)) GameMode->Get(AIDirectorOffset) = GetWorld()->SpawnActor(AIDirectorClass); if (GameMode->Get(AIDirectorOffset)) { } } static void SetupNavConfig(const FName& AgentName) { static auto AthenaNavSystemConfigOverrideClass = FindObject("/Script/FortniteGame.AthenaNavSystemConfigOverride"); auto NavSystemOverride = GetWorld()->SpawnActor(AthenaNavSystemConfigOverrideClass); if (!NavSystemOverride) return; static auto AthenaNavSystemConfigClass = FindObject("/Script/FortniteGame.AthenaNavSystemConfig"); auto AthenaNavConfig = (UAthenaNavSystemConfig*)UGameplayStatics::SpawnObject(AthenaNavSystemConfigClass, NavSystemOverride); AthenaNavConfig->Get("bUseBuildingGridAsNavigableSpace") = false; AthenaNavConfig->Get("bUsesStreamedInNavLevel") = true; AthenaNavConfig->Get("bAllowAutoRebuild") = true; AthenaNavConfig->Get("bCreateOnClient") = true; // BITFIELD AthenaNavConfig->Get("bAutoSpawnMissingNavData") = true; // BITFIELD AthenaNavConfig->Get("bSpawnNavDataInNavBoundsLevel") = true; // BITFIELD AthenaNavConfig->Get("bUseNavigationInvokers") = false; AthenaNavConfig->Get("DefaultAgentName") = AgentName; // NavSystemOverride->Get("OverridePolicy") = ENavSystemOverridePolicy::Append; NavSystemOverride->Get("NavigationSystemConfig") = AthenaNavConfig; SetNavigationSystem(NavSystemOverride); } static AFortPlayerPawn* SpawnAIFromCustomizationData(const FVector& Location, UObject* CustomizationData) { static auto PawnClassOffset = CustomizationData->GetOffset("PawnClass"); auto PawnClass = CustomizationData->Get(PawnClassOffset); if (!PawnClass) { LOG_INFO(LogAI, "Invalid PawnClass for AI!"); return nullptr; } auto Pawn = GetWorld()->SpawnActor(PawnClass, Location); static auto CharacterCustomizationOffset = CustomizationData->GetOffset("CharacterCustomization"); auto CharacterCustomization = CustomizationData->Get(CharacterCustomizationOffset); auto CharacterCustomizationLoadoutOffset = CharacterCustomization->GetOffset("CustomizationLoadout"); auto CharacterCustomizationLoadout = CharacterCustomization->GetPtr(CharacterCustomizationLoadoutOffset); ApplyCID(Pawn, CharacterCustomizationLoadout->GetCharacter()); struct FItemAndCount { int Count; // 0x0000(0x0004) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) unsigned char UnknownData00[0x4]; // 0x0004(0x0004) MISSED OFFSET UFortItemDefinition* Item; // 0x0008(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) }; static auto StartupInventoryOffset = CustomizationData->GetOffset("StartupInventory"); auto StartupInventory = CustomizationData->Get(StartupInventoryOffset); static auto StartupInventoryItemsOffset = StartupInventory->GetOffset("Items"); auto& StartupInventoryItems = StartupInventory->Get>(StartupInventoryItemsOffset); auto Controller = Pawn->GetController(); LOG_INFO(LogDev, "Controller: {} StartupInventoryItems.Num: {}", Controller ? Controller->GetFullName() : "InvalidObject", StartupInventoryItems.Num()); if (Controller) { /* static auto InventoryOffset = Controller->GetOffset("Inventory"); auto Inventory = Controller->Get(InventoryOffset); for (int i = 0; i < StartupInventoryItems.Num(); i++) { auto pair = Inventory->AddItem(StartupInventoryItems.at(i).Item, nullptr, StartupInventoryItems.at(i).Count); LOG_INFO(LogDev, "pair.first.size(): {}", pair.first.size()); if (pair.first.size() > 0) { if (auto weaponDef = Cast(StartupInventoryItems.at(i).Item)) Pawn->EquipWeaponDefinition(weaponDef, pair.first.at(0)->GetItemEntry()->GetItemGuid()); } } */ // Inventory->Update(); // crashes idk why } return Pawn; }