#pragma once #include "FortGameModePvPBase.h" #include "FortGameStateAthena.h" #include "KismetStringLibrary.h" #include "reboot.h" #include "BuildingSMActor.h" #include "FortSafeZoneIndicator.h" #include "GameplayStatics.h" #include "FortAbilitySet.h" #include "FortPlayerControllerAthena.h" #include "FortItemDefinition.h" struct FAircraftFlightInfo { float& GetTimeTillDropStart() { static auto TimeTillDropStartOffset = FindOffsetStruct("/Script/FortniteGame.AircraftFlightInfo", "TimeTillDropStart"); return *(float*)(__int64(this) + TimeTillDropStartOffset); } FVector& GetFlightStartLocation() { static auto FlightStartLocationOffset = FindOffsetStruct("/Script/FortniteGame.AircraftFlightInfo", "FlightStartLocation"); return *(FVector*)(__int64(this) + FlightStartLocationOffset); } float& GetFlightSpeed() { static auto FlightSpeedOffset = FindOffsetStruct("/Script/FortniteGame.AircraftFlightInfo", "FlightSpeed"); return *(float*)(__int64(this) + FlightSpeedOffset); } static UStruct* GetStruct() { static auto Struct = FindObject("/Script/FortniteGame.AircraftFlightInfo"); return Struct; } static int GetStructSize() { return GetStruct()->GetPropertiesSize(); } }; static void SetFoundationTransform(AActor* BuildingFoundation, const FTransform& Transform) { static auto DynamicFoundationRepDataOffset = BuildingFoundation->GetOffset("DynamicFoundationRepData", false); static auto Enabled = 1; static auto Disabled = 2; static auto DynamicFoundationTransformOffset = BuildingFoundation->GetOffset("DynamicFoundationTransform", false); if (DynamicFoundationTransformOffset != -1) // needed check? { auto DynamicFoundationTransform = BuildingFoundation->GetPtr(DynamicFoundationTransformOffset); *DynamicFoundationTransform = Transform; } if (DynamicFoundationRepDataOffset != -1) { auto DynamicFoundationRepData = BuildingFoundation->GetPtr(DynamicFoundationRepDataOffset); static auto RotationOffset = FindOffsetStruct("/Script/FortniteGame.DynamicBuildingFoundationRepData", "Rotation"); static auto TranslationOffset = FindOffsetStruct("/Script/FortniteGame.DynamicBuildingFoundationRepData", "Translation"); if (DynamicFoundationTransformOffset != -1) // needed check? { auto DynamicFoundationTransform = BuildingFoundation->GetPtr(DynamicFoundationTransformOffset); *(FRotator*)(__int64(DynamicFoundationRepData) + RotationOffset) = DynamicFoundationTransform->Rotation.Rotator(); *(FVector*)(__int64(DynamicFoundationRepData) + TranslationOffset) = DynamicFoundationTransform->Translation; } static auto OnRep_DynamicFoundationRepDataFn = FindObject("/Script/FortniteGame.BuildingFoundation.OnRep_DynamicFoundationRepData"); BuildingFoundation->ProcessEvent(OnRep_DynamicFoundationRepDataFn); } } 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())); return GameplayAbilitySet; } static void ShowFoundation(AActor* BuildingFoundation, bool bShow = true) { if (!BuildingFoundation) { LOG_WARN(LogGame, "Attempting to show invalid building foundation."); return; } LOG_INFO(LogDev, "{} {}", bShow ? "Showing" : "Hiding", BuildingFoundation->GetName()); bool bServerStreamedInLevelValue = bShow; // ?? static auto bServerStreamedInLevelFieldMask = GetFieldMask(BuildingFoundation->GetProperty("bServerStreamedInLevel")); static auto bServerStreamedInLevelOffset = BuildingFoundation->GetOffset("bServerStreamedInLevel"); BuildingFoundation->SetBitfieldValue(bServerStreamedInLevelOffset, bServerStreamedInLevelFieldMask, bServerStreamedInLevelValue); static auto bFoundationEnabledOffset = BuildingFoundation->GetOffset("bFoundationEnabled", false); if (bFoundationEnabledOffset != -1) { static auto bFoundationEnabledFieldMask = GetFieldMask(BuildingFoundation->GetProperty("bFoundationEnabled")); BuildingFoundation->SetBitfieldValue(bFoundationEnabledOffset, bFoundationEnabledFieldMask, bShow); // theres a onrep too } static auto StartDisabled = 3; static auto StartEnabled_Dynamic = 2; static auto Static = 0; static auto DynamicFoundationTypeOffset = BuildingFoundation->GetOffset("DynamicFoundationType", false); if (DynamicFoundationTypeOffset != -1) BuildingFoundation->Get(DynamicFoundationTypeOffset) = bShow ? Static : StartDisabled; /* static auto bShowHLODWhenDisabledOffset = BuildingFoundation->GetOffset("bShowHLODWhenDisabled", false); if (bShowHLODWhenDisabledOffset != -1) { static auto bShowHLODWhenDisabledFieldMask = GetFieldMask(BuildingFoundation->GetProperty("bShowHLODWhenDisabled")); BuildingFoundation->SetBitfieldValue(bShowHLODWhenDisabledOffset, bShowHLODWhenDisabledFieldMask, true); } */ static auto OnRep_ServerStreamedInLevelFn = FindObject("/Script/FortniteGame.BuildingFoundation.OnRep_ServerStreamedInLevel"); BuildingFoundation->ProcessEvent(OnRep_ServerStreamedInLevelFn); static auto DynamicFoundationRepDataOffset = BuildingFoundation->GetOffset("DynamicFoundationRepData", false); static auto Enabled = 1; static auto Disabled = 2; if (DynamicFoundationRepDataOffset != -1) { auto DynamicFoundationRepData = BuildingFoundation->GetPtr(DynamicFoundationRepDataOffset); static auto RotationOffset = FindOffsetStruct("/Script/FortniteGame.DynamicBuildingFoundationRepData", "Rotation"); static auto TranslationOffset = FindOffsetStruct("/Script/FortniteGame.DynamicBuildingFoundationRepData", "Translation"); static auto EnabledStateOffset = FindOffsetStruct("/Script/FortniteGame.DynamicBuildingFoundationRepData", "EnabledState"); *(uint8_t*)(__int64(DynamicFoundationRepData) + EnabledStateOffset) = bShow ? Enabled : Disabled; static auto OnRep_DynamicFoundationRepDataFn = FindObject("/Script/FortniteGame.BuildingFoundation.OnRep_DynamicFoundationRepData"); BuildingFoundation->ProcessEvent(OnRep_DynamicFoundationRepDataFn); } static auto FoundationEnabledStateOffset = BuildingFoundation->GetOffset("FoundationEnabledState", false); if (FoundationEnabledStateOffset != -1) BuildingFoundation->Get(FoundationEnabledStateOffset) = bShow ? Enabled : Disabled; // SetFoundationTransform(BuildingFoundation, BuildingFoundation->GetTransform()); // idk static auto LevelToStreamOffset = BuildingFoundation->GetOffset("LevelToStream"); auto& LevelToStream = BuildingFoundation->Get(LevelToStreamOffset); /* if (bShow) { UGameplayStatics::LoadStreamLevel(GetWorld(), LevelToStream, true, false, FLatentActionInfo()); } else { UGameplayStatics::UnloadStreamLevel(GetWorld(), LevelToStream, FLatentActionInfo(), false); } */ // real BuildingFoundation->FlushNetDormancy(); BuildingFoundation->ForceNetUpdate(); } static void StreamLevel(const std::string& LevelName, FVector Location = {}) { static auto BuildingFoundation3x3Class = FindObject("/Script/FortniteGame.BuildingFoundation3x3"); FTransform Transform{}; Transform.Scale3D = { 1, 1, 1 }; Transform.Translation = Location; auto BuildingFoundation = GetWorld()->SpawnActor(BuildingFoundation3x3Class, Transform); if (!BuildingFoundation) { LOG_ERROR(LogGame, "Failed to spawn BuildingFoundation for streaming!"); return; } static auto FoundationNameOffset = FindOffsetStruct("/Script/FortniteGame.BuildingFoundationStreamingData", "FoundationName"); static auto FoundationLocationOffset = FindOffsetStruct("/Script/FortniteGame.BuildingFoundationStreamingData", "FoundationLocation"); static auto StreamingDataOffset = BuildingFoundation->GetOffset("StreamingData"); static auto LevelToStreamOffset = BuildingFoundation->GetOffset("LevelToStream"); auto StreamingData = BuildingFoundation->GetPtr<__int64>(StreamingDataOffset); *(FName*)(__int64(StreamingData) + FoundationNameOffset) = UKismetStringLibrary::Conv_StringToName(std::wstring(LevelName.begin(), LevelName.end()).c_str()); *(FVector*)(__int64(StreamingData) + FoundationLocationOffset) = Location; *(FName*)(__int64(BuildingFoundation) + LevelToStreamOffset) = UKismetStringLibrary::Conv_StringToName(std::wstring(LevelName.begin(), LevelName.end()).c_str()); static auto OnRep_LevelToStreamFn = FindObject("/Script/FortniteGame.BuildingFoundation.OnRep_LevelToStream"); BuildingFoundation->ProcessEvent(OnRep_LevelToStreamFn); ShowFoundation(BuildingFoundation); } class AFortGameModeAthena : public AFortGameModePvPBase { public: static inline bool (*Athena_ReadyToStartMatchOriginal)(AFortGameModeAthena* GameMode); static inline void (*Athena_HandleStartingNewPlayerOriginal)(AFortGameModeAthena* GameMode, AActor* NewPlayer); static inline void (*SetZoneToIndexOriginal)(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK); AFortSafeZoneIndicator*& GetSafeZoneIndicator() { static auto SafeZoneIndicatorOffset = GetOffset("SafeZoneIndicator"); return Get(SafeZoneIndicatorOffset); } AFortGameStateAthena* GetGameStateAthena() { return (AFortGameStateAthena*)GetGameState(); } TArray& GetStartingItems() // really in zone { static auto StartingItemsOffset = GetOffset("StartingItems"); return Get>(StartingItemsOffset); } TArray& GetAlivePlayers() { static auto AlivePlayersOffset = GetOffset("AlivePlayers"); return Get>(AlivePlayersOffset); } FName RedirectLootTier(const FName& LootTier); UClass* GetVehicleClassOverride(UClass* DefaultClass); // Idk where to put these 3 functions. static void HandleSpawnRateForActorClass(UClass* ActorClass, float SpawnPercentage); static bool Athena_ReadyToStartMatchHook(AFortGameModeAthena* GameMode); static int Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller); static void Athena_HandleStartingNewPlayerHook(AFortGameModeAthena* GameMode, AActor* NewPlayerActor); static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK); };