diff --git a/Project Reboot 3.0/Actor.cpp b/Project Reboot 3.0/Actor.cpp index 933a3b6..f62aa9e 100644 --- a/Project Reboot 3.0/Actor.cpp +++ b/Project Reboot 3.0/Actor.cpp @@ -100,6 +100,33 @@ bool AActor::TeleportTo(const FVector& DestLocation, const FRotator& DestRotatio return AActor_K2_TeleportTo_Params.ReturnValue; } +bool AActor::IsActorBeingDestroyed() +{ + static auto bActorIsBeingDestroyedOffset = GetOffset("bActorIsBeingDestroyed"); + static auto bActorIsBeingDestroyedFieldMask = GetFieldMask(GetProperty("bActorIsBeingDestroyed")); + return ReadBitfieldValue(bActorIsBeingDestroyedOffset, bActorIsBeingDestroyedFieldMask); +} + +bool AActor::IsNetStartup() +{ + static auto bNetStartupOffset = GetOffset("bNetStartup"); + static auto bNetStartupFieldMask = GetFieldMask(GetProperty("bNetStartup")); + return ReadBitfieldValue(bNetStartupOffset, bNetStartupFieldMask); +} + +void AActor::SetOwner(AActor* Owner) +{ + static auto SetOwnerFn = FindObject("/Script/Engine.Actor.SetOwner"); + this->ProcessEvent(SetOwnerFn, &Owner); +} + +bool AActor::IsAlwaysRelevant() +{ + static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant"); + static auto bAlwaysRelevantFieldMask = GetFieldMask(GetProperty("bAlwaysRelevant")); + return ReadBitfieldValue(bAlwaysRelevantOffset, bAlwaysRelevantFieldMask); +} + UClass* AActor::StaticClass() { static auto Class = FindObject(L"/Script/Engine.Actor"); diff --git a/Project Reboot 3.0/Actor.h b/Project Reboot 3.0/Actor.h index 47a62fb..794773e 100644 --- a/Project Reboot 3.0/Actor.h +++ b/Project Reboot 3.0/Actor.h @@ -16,6 +16,10 @@ public: struct FRotator GetActorRotation(); void FlushNetDormancy(); bool TeleportTo(const FVector& DestLocation, const FRotator& DestRotation); - + bool IsActorBeingDestroyed(); + bool IsNetStartup(); + bool IsAlwaysRelevant(); + void SetOwner(AActor* Owner); + static class UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/Controller.cpp b/Project Reboot 3.0/Controller.cpp new file mode 100644 index 0000000..2162ff6 --- /dev/null +++ b/Project Reboot 3.0/Controller.cpp @@ -0,0 +1,11 @@ +#include "Controller.h" + +#include "reboot.h" + +AActor* AController::GetViewTarget() +{ + static auto GetViewTargetFn = FindObject("/Script/Engine.Controller.GetViewTarget"); + AActor* ViewTarget = nullptr; + this->ProcessEvent(GetViewTargetFn, &ViewTarget); + return ViewTarget; +} \ No newline at end of file diff --git a/Project Reboot 3.0/Controller.h b/Project Reboot 3.0/Controller.h index c2676b9..8cab45b 100644 --- a/Project Reboot 3.0/Controller.h +++ b/Project Reboot 3.0/Controller.h @@ -5,4 +5,5 @@ class AController : public AActor { public: + AActor* GetViewTarget(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/CurveTable.h b/Project Reboot 3.0/CurveTable.h index e21150a..85a92d3 100644 --- a/Project Reboot 3.0/CurveTable.h +++ b/Project Reboot 3.0/CurveTable.h @@ -4,16 +4,13 @@ #include "NameTypes.h" #include "reboot.h" +#include "DataTable.h" -class UCurveTable : public UObject +enum class ECurveTableMode : unsigned char { -public: -}; - -struct FCurveTableRowHandle -{ - UCurveTable* CurveTable; - FName RowName; + Empty, + SimpleCurves, + RichCurves }; struct FSimpleCurveKey @@ -24,7 +21,7 @@ struct FSimpleCurveKey struct FIndexedCurve { - + }; struct FRealCurve : public FIndexedCurve @@ -38,4 +35,60 @@ struct FSimpleCurve : public FRealCurve static auto KeysOffset = FindOffsetStruct("/Script/Engine.SimpleCurve", "Keys"); return *(TArray*)(__int64(this) + KeysOffset); } +}; + +class UCurveTable : public UObject +{ +public: + static int GetCurveTableSize() + { + static auto CurveTableClass = FindObject("/Script/Engine.CurveTable"); + return CurveTableClass->GetPropertiesSize(); + } + + ECurveTableMode GetCurveTableMode() const + { + static auto CurveTableModeOffset = GetCurveTableSize() - 8; + return *(ECurveTableMode*)(__int64(this) + CurveTableModeOffset); + } + + void* GetKey(const FName& RowName, int Index) + { + auto CurveTableMode = GetCurveTableMode(); + + LOG_INFO(LogDev, "RowName {} CurveTableMode {} Size {}", RowName.ComparisonIndex.Value ? RowName.ToString() : "InvalidComparision", (int)CurveTableMode, GetCurveTableSize()); + + if (CurveTableMode == ECurveTableMode::SimpleCurves) + { + auto& RowMap = ((UDataTable*)this)->GetRowMap(); // its the same offset so + auto Curve = RowMap.Find(RowName); + auto& Keys = Curve->GetKeys(); + return Keys.Num() > Index ? &Curve->GetKeys().at(Index) : nullptr; + } + else if (CurveTableMode == ECurveTableMode::RichCurves) + { + + } + + return nullptr; + } + + float GetValueOfKey(void* Key) + { + if (!Key) + return 0.f; + + auto CurveTableMode = GetCurveTableMode(); + + if (CurveTableMode == ECurveTableMode::SimpleCurves) return ((FSimpleCurveKey*)Key)->Value; + else if (CurveTableMode == ECurveTableMode::RichCurves) return 0.f; + + return 0.f; + } +}; + +struct FCurveTableRowHandle +{ + UCurveTable* CurveTable; + FName RowName; }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 2e211af..46c6ea3 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -41,7 +41,10 @@ enum class EDynamicFoundationType : uint8_t void ShowFoundation(UObject* BuildingFoundation) { if (!BuildingFoundation) + { + LOG_WARN(LogGame, "Attempting to show invalid building foundation."); return; + } static auto bServerStreamedInLevelFieldMask = GetFieldMask(BuildingFoundation->GetProperty("bServerStreamedInLevel")); static auto bServerStreamedInLevelOffset = BuildingFoundation->GetOffset("bServerStreamedInLevel"); @@ -212,8 +215,17 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game GameMode->Get("WarmupRequiredPlayerCount") = 1; { - SetPlaylist(GetPlaylistToUse()); - LOG_INFO(LogDev, "Set playlist!"); + auto PlaylistToUse = GetPlaylistToUse(); + + if (!PlaylistToUse) + { + LOG_ERROR(LogPlaylist, "Failed to find playlist! Proceeding, but will probably not work as expected!"); + } + else + { + SetPlaylist(PlaylistToUse); + LOG_INFO(LogDev, "Set playlist!"); + } } // if (false) @@ -270,11 +282,8 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game ShowFoundation(PleasantParkGround); } - auto PolarPeak = FindObject(("/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.LF_Athena_POI_25x36")); - ShowFoundation(PolarPeak); - - auto tiltedtower = FindObject("/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.ShopsNew"); - ShowFoundation(tiltedtower); // 7.40 specific? + ShowFoundation(FindObject("/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.LF_Athena_POI_25x36")); // Polar Peak + ShowFoundation(FindObject("/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.ShopsNew")); // Tilted Tower Shops, is this 7.40 specific? } else if (Fortnite_Season == 8) @@ -298,9 +307,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game if (Fortnite_Version == 14.60 && Globals::bGoingToPlayEvent) { - auto aircraftcarrier = FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.Lobby_Foundation3"); - LOG_INFO(LogDev, "aircraftcarrier: {}", __int64(aircraftcarrier)); - ShowFoundation(aircraftcarrier); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.Lobby_Foundation3")); // Aircraft Carrier } if (Fortnite_Version == 17.50) { @@ -312,60 +319,48 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game } if (Fortnite_Version == 17.40) { - auto AbductedCoral = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.CoralPhase_02")); // Coral Castle Phases (CoralPhase_01, CoralPhase_02 and CoralPhase_03) - ShowFoundation(AbductedCoral); - - auto CoralFoundation_01 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation_0")); - ShowFoundation(CoralFoundation_01); - - auto CoralFoundation_05 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation6")); - ShowFoundation(CoralFoundation_05); - - auto CoralFoundation_07 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation3")); - ShowFoundation(CoralFoundation_07); - - auto CoralFoundation_10 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation2_1")); - ShowFoundation(CoralFoundation_10); - - auto CoralFoundation_13 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation4")); - ShowFoundation(CoralFoundation_13); - - auto CoralFoundation_17 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation5")); - ShowFoundation(CoralFoundation_17); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.CoralPhase_02")); // Coral Castle Phases (CoralPhase_01, CoralPhase_02 and CoralPhase_03) + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation_0")); // CoralFoundation_01 + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation6")); // CoralFoundation_05 + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation3")); // CoralFoundation_07 + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation2_1")); // CoralFoundation_10 + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation4")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.LF_Athena_16x16_Foundation5")); } if (Fortnite_Version == 17.30) { - auto AbductedSlurpy = FindObject(("LF_Athena_POI_50x50_C /Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.Slurpy_Phase03")); // Slurpy Swamp Phases (Slurpy_Phase01, Slurpy_Phase02 and Slurpy_Phase03) - ShowFoundation(AbductedSlurpy); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_Mother.Apollo_Mother.PersistentLevel.Slurpy_Phase03")); // There are 1, 2 and 3 } if (Fortnite_Season == 13) { - auto SpawnIsland = FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.Lobby_Foundation"); - ShowFoundation(SpawnIsland); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.Lobby_Foundation")); // SpawnIsland->RepData->Soemthing = FoundationSetup->LobbyLocation; } if (Fortnite_Version == 12.41) { - auto JS03 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_Athena_POI_19x19_2")); - ShowFoundation(JS03); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_Athena_POI_19x19_2")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head6_18")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head5_14")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head3_8")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head_2")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head4_11")); + } - auto JH00 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head6_18")); - ShowFoundation(JH00); + if (Fortnite_Version == 11.31) + { + // There are also christmas trees & stuff but we need to find a better way to stream that because there's a lot. - auto JH01 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head5_14")); - ShowFoundation(JH01); - - auto JH02 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head3_8")); - ShowFoundation(JH02); - - auto JH03 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head_2")); - ShowFoundation(JH03); - - auto JH04 = FindObject(("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.BP_Jerky_Head4_11")); - ShowFoundation(JH04); + if (false) // If the client loads this, it says the package doesnt exist... + { + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_5x5_Galileo_Ferry_1")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_5x5_Galileo_Ferry_2")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_5x5_Galileo_Ferry_3")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_5x5_Galileo_Ferry_4")); + ShowFoundation(FindObject("/Game/Athena/Apollo/Maps/Apollo_POI_Foundations.Apollo_POI_Foundations.PersistentLevel.LF_5x5_Galileo_Ferry_5")); + } } auto PlaylistToUse = GetPlaylistToUse(); @@ -505,20 +500,6 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game LOG_INFO(LogDev, "Initialized!"); } - if (Engine_Version >= 424) // returning true is stripped on c2+ - { - if (GameState->GetPlayersLeft() >= GameMode->Get("WarmupRequiredPlayerCount")) - { - if (MapInfo) - { - static auto FlightInfosOffset = MapInfo->GetOffset("FlightInfos"); - - if (MapInfo->Get>(FlightInfosOffset).ArrayNum <= 0) - return true; - } - } - } - static auto TeamsOffset = GameState->GetOffset("Teams"); auto& Teams = GameState->Get>(TeamsOffset); @@ -540,6 +521,20 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game // return false; } + if (Engine_Version >= 424) // returning true is stripped on c2+ + { + if (GameState->GetPlayersLeft() >= GameMode->Get("WarmupRequiredPlayerCount")) + { + if (MapInfo) + { + static auto FlightInfosOffset = MapInfo->GetOffset("FlightInfos"); + + if (MapInfo->Get>(FlightInfosOffset).ArrayNum <= 0) + return true; + } + } + } + return Athena_ReadyToStartMatchOriginal(GameMode); } @@ -658,13 +653,27 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena { bSpawnedVehicles = true; - SpawnVehicles(); + /* static auto GalileoSpawnerClass = FindObject("/Game/Athena/AI/Galileo/BP_Galileo_Spawner.BP_Galileo_Spawner_C"); + auto GalileoSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), GalileoSpawnerClass); + + LOG_INFO(LogDev, "GalileoSpawners.Num(): {}", GalileoSpawners.Num()); + + for (int i = 0; i < GalileoSpawners.Num(); i++) + { + auto GalileoSpawner = GalileoSpawners.at(i); + + auto NewPawn = SpawnAIFromCustomizationData(GalileoSpawner->GetActorLocation(), GalileoSpawner->Get("BotData")); + } */ + + // SpawnVehicles(); } auto NewPlayer = (AFortPlayerControllerAthena*)NewPlayerActor; auto PlayerStateAthena = NewPlayer->GetPlayerStateAthena(); + LOG_INFO(LogDev, "PlayerStateAthena: {}", __int64(PlayerStateAthena)); + if (!PlayerStateAthena) return Athena_HandleStartingNewPlayerOriginal(GameMode, NewPlayerActor); @@ -677,7 +686,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena { auto CharacterParts = PlayerStateAthena->GetPtr<__int64>("CharacterParts"); - static auto PartsOffset = FindOffsetStruct("/Script/FortniteGame.CustomCharacterParts", "Parts"); + static auto PartsOffset = FindOffsetStruct("/Script/FortniteGame.CustomCharacterParts", "Parts", false); auto Parts = (UObject**)(__int64(CharacterParts) + PartsOffset); // UCustomCharacterPart* Parts[0x6] static auto headPart = LoadObject("/Game/Characters/CharacterParts/Female/Medium/Heads/F_Med_Head1.F_Med_Head1"); @@ -695,24 +704,22 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena PlayerStateAthena->GetSquadId() = PlayerStateAthena->GetTeamIndex() - 2; - // if (false) - { - // idk if this is needed + // idk if this is needed - static auto bHasServerFinishedLoadingOffset = NewPlayer->GetOffset("bHasServerFinishedLoading"); - NewPlayer->Get(bHasServerFinishedLoadingOffset) = true; + static auto bHasServerFinishedLoadingOffset = NewPlayer->GetOffset("bHasServerFinishedLoading"); + NewPlayer->Get(bHasServerFinishedLoadingOffset) = true; - static auto OnRep_bHasServerFinishedLoadingFn = FindObject(L"/Script/FortniteGame.FortPlayerController.OnRep_bHasServerFinishedLoading"); - NewPlayer->ProcessEvent(OnRep_bHasServerFinishedLoadingFn); + static auto OnRep_bHasServerFinishedLoadingFn = FindObject(L"/Script/FortniteGame.FortPlayerController.OnRep_bHasServerFinishedLoading"); + NewPlayer->ProcessEvent(OnRep_bHasServerFinishedLoadingFn); - static auto bHasStartedPlayingOffset = PlayerStateAthena->GetOffset("bHasStartedPlaying"); - PlayerStateAthena->Get(bHasStartedPlayingOffset) = true; // this is a bitfield!!! + static auto bHasStartedPlayingOffset = PlayerStateAthena->GetOffset("bHasStartedPlaying"); + static auto bHasStartedPlayingFieldMask = GetFieldMask(PlayerStateAthena->GetProperty("bHasStartedPlaying")); + PlayerStateAthena->SetBitfieldValue(bHasStartedPlayingOffset, bHasStartedPlayingFieldMask, true); - static auto OnRep_bHasStartedPlayingFn = FindObject(L"/Script/FortniteGame.FortPlayerState.OnRep_bHasStartedPlaying"); - PlayerStateAthena->ProcessEvent(OnRep_bHasStartedPlayingFn); - } + static auto OnRep_bHasStartedPlayingFn = FindObject(L"/Script/FortniteGame.FortPlayerState.OnRep_bHasStartedPlaying"); + PlayerStateAthena->ProcessEvent(OnRep_bHasStartedPlayingFn); - // LOG_INFO(LogDev, "Old ID: {}", PlayerStateAthena->GetWorldPlayerId()); + LOG_INFO(LogDev, "Old ID: {}", PlayerStateAthena->GetWorldPlayerId()); // if (PlayerStateAthena->GetWorldPlayerId() == -1) { @@ -753,63 +760,65 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena } } } - - static auto GameMemberInfoArrayOffset = GameState->GetOffset("GameMemberInfoArray", false); struct FUniqueNetIdReplExperimental { unsigned char ahh[0x0028]; }; - FUniqueNetIdReplExperimental bugha{}; + FUniqueNetIdReplExperimental Bugha{}; auto& PlayerStateUniqueId = PlayerStateAthena->Get("UniqueId"); - // if (false) - // if (GameMemberInfoArrayOffset != 0) - if (Engine_Version >= 423) { - struct FGameMemberInfo : public FFastArraySerializerItem + static auto GameMemberInfoArrayOffset = GameState->GetOffset("GameMemberInfoArray", false); + + // if (false) + // if (GameMemberInfoArrayOffset != 0) + if (Engine_Version >= 423) { - unsigned char SquadId; // 0x000C(0x0001) (ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - unsigned char TeamIndex; // 0x000D(0x0001) (ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - unsigned char UnknownData00[0x2]; // 0x000E(0x0002) MISSED OFFSET - FUniqueNetIdReplExperimental MemberUniqueId; // 0x0010(0x0028) (HasGetValueTypeHash, NativeAccessSpecifierPublic) - }; + struct FGameMemberInfo : public FFastArraySerializerItem + { + unsigned char SquadId; // 0x000C(0x0001) (ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + unsigned char TeamIndex; // 0x000D(0x0001) (ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + unsigned char UnknownData00[0x2]; // 0x000E(0x0002) MISSED OFFSET + FUniqueNetIdReplExperimental MemberUniqueId; // 0x0010(0x0028) (HasGetValueTypeHash, NativeAccessSpecifierPublic) + }; - static auto GameMemberInfoStructSize = 0x38; - // LOG_INFO(LogDev, "Compare: 0x{:x} 0x{:x}", GameMemberInfoStructSize, sizeof(FGameMemberInfo)); + static auto GameMemberInfoStructSize = 0x38; + // LOG_INFO(LogDev, "Compare: 0x{:x} 0x{:x}", GameMemberInfoStructSize, sizeof(FGameMemberInfo)); - auto GameMemberInfo = Alloc(GameMemberInfoStructSize); + auto GameMemberInfo = Alloc(GameMemberInfoStructSize); - ((FFastArraySerializerItem*)GameMemberInfo)->MostRecentArrayReplicationKey = -1; - ((FFastArraySerializerItem*)GameMemberInfo)->ReplicationID = -1; - ((FFastArraySerializerItem*)GameMemberInfo)->ReplicationKey = -1; + ((FFastArraySerializerItem*)GameMemberInfo)->MostRecentArrayReplicationKey = -1; + ((FFastArraySerializerItem*)GameMemberInfo)->ReplicationID = -1; + ((FFastArraySerializerItem*)GameMemberInfo)->ReplicationKey = -1; - if (false) - { - static auto GameMemberInfo_SquadIdOffset = 0x000C; - static auto GameMemberInfo_TeamIndexOffset = 0x000D; - static auto GameMemberInfo_MemberUniqueIdOffset = 0x0010; - static auto UniqueIdSize = 0x0028; + if (false) + { + static auto GameMemberInfo_SquadIdOffset = 0x000C; + static auto GameMemberInfo_TeamIndexOffset = 0x000D; + static auto GameMemberInfo_MemberUniqueIdOffset = 0x0010; + static auto UniqueIdSize = 0x0028; - *(uint8*)(__int64(GameMemberInfo) + GameMemberInfo_SquadIdOffset) = PlayerStateAthena->GetSquadId(); - *(uint8*)(__int64(GameMemberInfo) + GameMemberInfo_TeamIndexOffset) = PlayerStateAthena->GetTeamIndex(); - CopyStruct((void*)(__int64(GameMemberInfo) + GameMemberInfo_MemberUniqueIdOffset), PlayerStateAthena->Get("UniqueId"), UniqueIdSize); + *(uint8*)(__int64(GameMemberInfo) + GameMemberInfo_SquadIdOffset) = PlayerStateAthena->GetSquadId(); + *(uint8*)(__int64(GameMemberInfo) + GameMemberInfo_TeamIndexOffset) = PlayerStateAthena->GetTeamIndex(); + CopyStruct((void*)(__int64(GameMemberInfo) + GameMemberInfo_MemberUniqueIdOffset), PlayerStateAthena->Get("UniqueId"), UniqueIdSize); + } + else + { + GameMemberInfo->SquadId = PlayerStateAthena->GetSquadId(); + GameMemberInfo->TeamIndex = PlayerStateAthena->GetTeamIndex(); + GameMemberInfo->MemberUniqueId = PlayerStateUniqueId; + } + + static auto GameMemberInfoArray_MembersOffset = FindOffsetStruct("/Script/FortniteGame.GameMemberInfoArray", "Members"); + + auto GameMemberInfoArray = GameState->GetPtr(GameMemberInfoArrayOffset); + + ((TArray*)(__int64(GameMemberInfoArray) + GameMemberInfoArray_MembersOffset))->Add(*GameMemberInfo, GameMemberInfoStructSize); + GameMemberInfoArray->MarkArrayDirty(); } - else - { - GameMemberInfo->SquadId = PlayerStateAthena->GetSquadId(); - GameMemberInfo->TeamIndex = PlayerStateAthena->GetTeamIndex(); - GameMemberInfo->MemberUniqueId = PlayerStateUniqueId; - } - - static auto GameMemberInfoArray_MembersOffset = FindOffsetStruct("/Script/FortniteGame.GameMemberInfoArray", "Members"); - - auto GameMemberInfoArray = GameState->GetPtr(GameMemberInfoArrayOffset); - - ((TArray*)(__int64(GameMemberInfoArray) + GameMemberInfoArray_MembersOffset))->Add(*GameMemberInfo, GameMemberInfoStructSize); - GameMemberInfoArray->MarkArrayDirty(); } if (Globals::bCreative) @@ -920,12 +929,18 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena } } - static auto SpawnActorDataListOffset = GameMode->GetOffset("SpawnActorDataList", false); + LOG_INFO(LogDev, "HandleStartingNewPlayer end"); - if (SpawnActorDataListOffset != 0) + if (Engine_Version < 420) { - auto& SpawnActorDataList = GameMode->Get>(SpawnActorDataListOffset); - LOG_INFO(LogDev, "SpawnActorDataList.Num(): {}", SpawnActorDataList.Num()); + static auto QuickBarsOffset = NewPlayer->GetOffset("QuickBars", false); + + if (QuickBarsOffset != 0) + { + static auto FortQuickBarsClass = FindObject("/Script/FortniteGame.FortQuickBars"); + NewPlayer->Get(QuickBarsOffset) = GetWorld()->SpawnActor(FortQuickBarsClass); + NewPlayer->Get(QuickBarsOffset)->SetOwner(NewPlayer); + } } return Athena_HandleStartingNewPlayerOriginal(GameMode, NewPlayerActor); diff --git a/Project Reboot 3.0/FortGameStateAthena.cpp b/Project Reboot 3.0/FortGameStateAthena.cpp index 58a32e2..d82ffc7 100644 --- a/Project Reboot 3.0/FortGameStateAthena.cpp +++ b/Project Reboot 3.0/FortGameStateAthena.cpp @@ -35,6 +35,8 @@ void AFortGameStateAthena::OnRep_CurrentPlaylistInfo() else { static auto OnRep_CurrentPlaylistInfo = FindObject("/Script/FortniteGame.FortGameStateAthena.OnRep_CurrentPlaylistInfo"); - this->ProcessEvent(OnRep_CurrentPlaylistInfo); + + if (OnRep_CurrentPlaylistInfo) + this->ProcessEvent(OnRep_CurrentPlaylistInfo); } } \ No newline at end of file diff --git a/Project Reboot 3.0/FortInventory.cpp b/Project Reboot 3.0/FortInventory.cpp index fff4fcd..d95a109 100644 --- a/Project Reboot 3.0/FortInventory.cpp +++ b/Project Reboot 3.0/FortInventory.cpp @@ -6,7 +6,7 @@ UFortItem* CreateItemInstance(AFortPlayerController* PlayerController, UFortItem { UFortItem* NewItemInstance = ItemDefinition->CreateTemporaryItemInstanceBP(Count); - if (NewItemInstance) + if (NewItemInstance && PlayerController) NewItemInstance->SetOwningControllerForTemporaryItem(PlayerController); return NewItemInstance; @@ -96,23 +96,24 @@ std::pair, std::vector> AFortInventory::AddI Count = OverStack > 0 ? OverStack : Count; - auto PlayerController = Cast(GetOwner()); + auto PlayerController = Cast(GetOwner()); if (!PlayerController) return std::make_pair(NewItemInstances, ModifiedItemInstances); if (OverStack > 0 && !bAllowMultipleStacks) { - auto Pawn = PlayerController->GetMyFortPawn(); + auto Pawn = PlayerController->GetPawn(); if (!Pawn) return std::make_pair(NewItemInstances, ModifiedItemInstances); - AFortPickup::SpawnPickup(ItemDefinition, Pawn->GetActorLocation(), Count, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, Pawn); + AFortPickup::SpawnPickup(ItemDefinition, Pawn->GetActorLocation(), Count, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, Cast(Pawn)); return std::make_pair(NewItemInstances, ModifiedItemInstances); } - UFortItem* NewItemInstance = CreateItemInstance(PlayerController, ItemDefinition, Count); + auto FortPlayerController = Cast(PlayerController); + UFortItem* NewItemInstance = CreateItemInstance(FortPlayerController, ItemDefinition, Count); if (NewItemInstance) { @@ -132,6 +133,36 @@ std::pair, std::vector> AFortInventory::AddI ItemInstances.Add(NewItemInstance); GetItemList().GetReplicatedEntries().Add(*NewItemInstance->GetItemEntry(), FortItemEntrySize); + if (FortPlayerController && Engine_Version < 420) + { + static auto QuickBarsOffset = FortPlayerController->GetOffset("QuickBars", false); + auto QuickBars = FortPlayerController->Get(QuickBarsOffset); + + enum class EFortQuickBars : uint8_t + { + Primary = 0, + Secondary = 1, + Max_None = 2, + EFortQuickBars_MAX = 3 + }; + + struct + { + FGuid Item; // (Parm, IsPlainOldData) + EFortQuickBars InQuickBar; // (Parm, ZeroConstructor, IsPlainOldData) + int Slot; // (Parm, ZeroConstructor, IsPlainOldData) + } + AFortQuickBars_ServerAddItemInternal_Params + { + NewItemInstance->GetItemEntry()->GetItemGuid(), + IsPrimaryQuickbar(ItemDefinition) ? EFortQuickBars ::Primary : EFortQuickBars::Secondary, + -1 + }; + + static auto ServerAddItemInternalFn = FindObject("/Script/FortniteGame.FortQuickBars.ServerAddItemInternal"); + QuickBars->ProcessEvent(ServerAddItemInternalFn, &AFortQuickBars_ServerAddItemInternal_Params); + } + if (bShouldUpdate) *bShouldUpdate = true; } diff --git a/Project Reboot 3.0/FortLootPackage.cpp b/Project Reboot 3.0/FortLootPackage.cpp index 13513db..50431a7 100644 --- a/Project Reboot 3.0/FortLootPackage.cpp +++ b/Project Reboot 3.0/FortLootPackage.cpp @@ -4,6 +4,77 @@ #include "KismetMathLibrary.h" #include "FortWeaponItemDefinition.h" + +static FFortLootTierData* GetLootTierData2(std::vector& LootTierData, bool bPrint) +{ + float TotalWeight = 0; + + for (auto Item : LootTierData) + { + TotalWeight += Item->GetWeight(); + } + + float RandomNumber = TotalWeight * (rand() * 0.000030518509); // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed? + + FFortLootTierData* SelectedItem = nullptr; + + if (bPrint) + { + std::cout << std::format("TotalWeight: {}\n", TotalWeight); + } + + for (auto Item : LootTierData) + { + if (bPrint) + { + std::cout << std::format("Rand: {} Weight: {}\n", RandomNumber, Item->GetWeight()); + } + + if (RandomNumber <= Item->GetWeight()) + { + SelectedItem = Item; + break; + } + + RandomNumber -= Item->GetWeight(); + } + + if (!SelectedItem) + return GetLootTierData2(LootTierData, bPrint); + + return SelectedItem; +} + +static FFortLootPackageData* GetLootPackage2(std::vector& LootPackages) +{ + float TotalWeight = 0; + + for (auto Item : LootPackages) + { + TotalWeight += Item->GetWeight(); + } + + float RandomNumber = TotalWeight * (rand() * 0.000030518509); // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed? + + FFortLootPackageData* SelectedItem = nullptr; + + for (auto Item : LootPackages) + { + if (RandomNumber <= Item->GetWeight()) + { + SelectedItem = Item; + break; + } + + RandomNumber -= Item->GetWeight(); + } + + if (!SelectedItem) + return GetLootPackage2(LootPackages); + + return SelectedItem; +} + static FFortLootTierData* GetLootTierData(std::vector& LootTierData, bool bPrint) { float TotalWeight = 0; @@ -280,6 +351,8 @@ std::vector PickLootDrops(FName TierGroupName, bool bPrint, int recurs LOG_INFO(LogLoot, "randomNumberFloat: {} randomNumberFloored: {}", randomNumberFloat, randomNumberFloored); TierGroupLP = TierGroupLPs.at(randomNumberFloored); */ + + TierGroupLP = TierGroupLPs.at(i - NumLootPackageDrops); // Once we fix chapter 2 loot package drops, we can use this } else { diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index 20bf73c..65fef4b 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -73,9 +73,61 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController if (!ItemDefinition) return; + if (Engine_Version < 420) // wtf + { + static auto CurrentWeaponListOffset = Pawn->GetOffset("CurrentWeaponList"); + auto& CurrentWeaponList = Pawn->Get>(CurrentWeaponListOffset); + + CurrentWeaponList.Data = nullptr; + CurrentWeaponList.ArrayNum = 0; + CurrentWeaponList.ArrayMax = 0; + } + if (auto Weapon = Pawn->EquipWeaponDefinition((UFortWeaponItemDefinition*)ItemDefinition, ItemInstance->GetItemEntry()->GetItemGuid())) { + if (Engine_Version < 420) + { + static auto FortWeap_BuildingToolClass = FindObject("/Script/FortniteGame.FortWeap_BuildingTool"); + if (!Weapon->IsA(FortWeap_BuildingToolClass)) + return; + + auto BuildingTool = Weapon; + + using UBuildingEditModeMetadata = UObject; + using UFortBuildingItemDefinition = UObject; + + static auto OnRep_DefaultMetadataFn = FindObject("/Script/FortniteGame.FortWeap_BuildingTool.OnRep_DefaultMetadata"); + static auto DefaultMetadataOffset = BuildingTool->GetOffset("DefaultMetadata"); + + static auto RoofPiece = FindObject("/Game/Items/Weapons/BuildingTools/BuildingItemData_RoofS.BuildingItemData_RoofS"); + static auto FloorPiece = FindObject("/Game/Items/Weapons/BuildingTools/BuildingItemData_Floor.BuildingItemData_Floor"); + static auto WallPiece = FindObject("/Game/Items/Weapons/BuildingTools/BuildingItemData_Wall.BuildingItemData_Wall"); + static auto StairPiece = FindObject("/Game/Items/Weapons/BuildingTools/BuildingItemData_Stair_W.BuildingItemData_Stair_W"); + + if (ItemDefinition == RoofPiece) + { + static auto RoofMetadata = FindObject("/Game/Building/EditModePatterns/Roof/EMP_Roof_RoofC.EMP_Roof_RoofC"); + BuildingTool->Get(DefaultMetadataOffset) = RoofMetadata; + } + else if (ItemDefinition == StairPiece) + { + static auto StairMetadata = FindObject("/Game/Building/EditModePatterns/Stair/EMP_Stair_StairW.EMP_Stair_StairW"); + BuildingTool->Get(DefaultMetadataOffset) = StairMetadata; + } + else if (ItemDefinition == WallPiece) + { + static auto WallMetadata = FindObject("/Game/Building/EditModePatterns/Wall/EMP_Wall_Solid.EMP_Wall_Solid"); + BuildingTool->Get(DefaultMetadataOffset) = WallMetadata; + } + else if (ItemDefinition == FloorPiece) + { + static auto FloorMetadata = FindObject("/Game/Building/EditModePatterns/Floor/EMP_Floor_Floor.EMP_Floor_Floor"); + BuildingTool->Get(DefaultMetadataOffset) = FloorMetadata; + } + + BuildingTool->ProcessEvent(OnRep_DefaultMetadataFn); + } } } @@ -523,7 +575,8 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo auto DeathInfo = (void*)(__int64(DeadPlayerState) + MemberOffsets::FortPlayerStateAthena::DeathInfo); // Alloc(DeathInfoStructSize); RtlSecureZeroMemory(DeathInfo, DeathInfoStructSize); - auto& Tags = DeadPawn->Get(MemberOffsets::FortPlayerPawn::CorrectTags); + auto/*&*/ Tags = MemberOffsets::FortPlayerPawn::CorrectTags == 0 ? FGameplayTagContainer() + : DeadPawn->Get(MemberOffsets::FortPlayerPawn::CorrectTags); // *(FGameplayTagContainer*)(__int64(DeathReport) + MemberOffsets::DeathReport::Tags); // LOG_INFO(LogDev, "Tags: {}", Tags.ToStringSimple(true)); @@ -535,7 +588,9 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo *(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bDBNO) = DeadPawn->IsDBNO(); *(uint8*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathCause) = DeathCause; *(AActor**)(__int64(DeathInfo) + MemberOffsets::DeathInfo::FinisherOrDowner) = KillerPlayerState ? KillerPlayerState : DeadPlayerState; - *(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) = DeathLocation; + + if (MemberOffsets::DeathInfo::DeathLocation != 0) + *(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) = DeathLocation; if (MemberOffsets::DeathInfo::DeathTags != 0) *(FGameplayTagContainer*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathTags) = Tags; @@ -545,14 +600,16 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo if (DeathCause == FallDamageEnumValue) { - *(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = DeadPawn->Get(MemberOffsets::FortPlayerPawnAthena::LastFallDistance); + if (MemberOffsets::FortPlayerPawnAthena::LastFallDistance != 0) + *(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = DeadPawn->Get(MemberOffsets::FortPlayerPawnAthena::LastFallDistance); } else { *(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = KillerPawn ? KillerPawn->GetDistanceTo(DeadPawn) : 0; } - DeadPlayerState->Get(MemberOffsets::FortPlayerState::PawnDeathLocation) = DeathLocation; + if (MemberOffsets::FortPlayerState::PawnDeathLocation != 0) + DeadPlayerState->Get(MemberOffsets::FortPlayerState::PawnDeathLocation) = DeathLocation; static auto OnRep_DeathInfoFn = FindObject("/Script/FortniteGame.FortPlayerStateAthena.OnRep_DeathInfo"); DeadPlayerState->ProcessEvent(OnRep_DeathInfoFn); diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.cpp b/Project Reboot 3.0/FortPlayerControllerAthena.cpp index b9e1830..7123230 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.cpp +++ b/Project Reboot 3.0/FortPlayerControllerAthena.cpp @@ -6,52 +6,6 @@ #include "globals.h" #include "GameplayStatics.h" -void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID) -{ - if (!CID) - return; - - static auto HeroDefinitionOffset = CID->GetOffset("HeroDefinition"); - auto HeroDefinition = CID->Get(HeroDefinitionOffset); - - using UFortHeroSpecialization = UObject; - - static auto SpecializationsOffset = HeroDefinition->GetOffset("Specializations"); - auto& Specializations = HeroDefinition->Get>>(SpecializationsOffset); - - auto PlayerState = Pawn->GetPlayerState(); - - for (int i = 0; i < Specializations.Num(); i++) - { - auto& SpecializationSoft = Specializations.at(i); - - auto Specialization = SpecializationSoft.Get(); - - if (Specialization) - { - static auto Specialization_CharacterPartsOffset = Specialization->GetOffset("CharacterParts"); - auto& CharacterParts = Specialization->Get>>(Specialization_CharacterPartsOffset); - - bool aa; - - TArray CharacterPartsaa; - - for (int z = 0; z < CharacterParts.Num(); z++) - { - auto& CharacterPartSoft = CharacterParts.at(z); - auto CharacterPart = CharacterPartSoft.Get(); - - CharacterPartsaa.Add(CharacterPart); - - continue; - } - - UFortKismetLibrary::ApplyCharacterCosmetics(GetWorld(), CharacterPartsaa, PlayerState, &aa); - CharacterPartsaa.Free(); - } - } -} - void AFortPlayerControllerAthena::ServerGiveCreativeItemHook(AFortPlayerControllerAthena* Controller, FFortItemEntry CreativeItem) { // Don't worry, the validate has a check if it is a creative enabled mode or not, but we need to add a volume check. diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.h b/Project Reboot 3.0/FortPlayerControllerAthena.h index 385dda2..4efc25c 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.h +++ b/Project Reboot 3.0/FortPlayerControllerAthena.h @@ -2,6 +2,55 @@ #include "FortPlayerController.h" #include "FortPlayerStateAthena.h" +#include "FortPlayerPawn.h" +#include "SoftObjectPtr.h" +#include "FortKismetLibrary.h" + +static void ApplyCID(AFortPlayerPawn* Pawn, UObject* CID) +{ + if (!CID) + return; + + static auto HeroDefinitionOffset = CID->GetOffset("HeroDefinition"); + auto HeroDefinition = CID->Get(HeroDefinitionOffset); + + using UFortHeroSpecialization = UObject; + + static auto SpecializationsOffset = HeroDefinition->GetOffset("Specializations"); + auto& Specializations = HeroDefinition->Get>>(SpecializationsOffset); + + auto PlayerState = Pawn->GetPlayerState(); + + for (int i = 0; i < Specializations.Num(); i++) + { + auto& SpecializationSoft = Specializations.at(i); + + auto Specialization = SpecializationSoft.Get(); + + if (Specialization) + { + static auto Specialization_CharacterPartsOffset = Specialization->GetOffset("CharacterParts"); + auto& CharacterParts = Specialization->Get>>(Specialization_CharacterPartsOffset); + + bool aa; + + TArray CharacterPartsaa; + + for (int z = 0; z < CharacterParts.Num(); z++) + { + auto& CharacterPartSoft = CharacterParts.at(z); + auto CharacterPart = CharacterPartSoft.Get(); + + CharacterPartsaa.Add(CharacterPart); + + continue; + } + + UFortKismetLibrary::ApplyCharacterCosmetics(GetWorld(), CharacterPartsaa, PlayerState, &aa); + CharacterPartsaa.Free(); + } + } +} class AFortPlayerControllerAthena : public AFortPlayerController { diff --git a/Project Reboot 3.0/FortPlayerPawn.cpp b/Project Reboot 3.0/FortPlayerPawn.cpp index 871f9a6..22372db 100644 --- a/Project Reboot 3.0/FortPlayerPawn.cpp +++ b/Project Reboot 3.0/FortPlayerPawn.cpp @@ -43,6 +43,8 @@ void AFortPlayerPawn::ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZipline if (!Addrr) Addrr = Memcury::Scanner::FindStringRef(L"ZIPLINES!! GetLocalRole()(%s) AFortPlayerPawn::OnRep_ZiplineState ZiplineState.bIsZiplining=%d").Get(); + // L"%s LocalRole[%s] ZiplineState.bIsZiplining[%d]" for 18.40??? + // std::cout << "Addrr: " << Addrr << '\n'; if (Addrr) diff --git a/Project Reboot 3.0/GameModeBase.cpp b/Project Reboot 3.0/GameModeBase.cpp index ea43271..535c3a7 100644 --- a/Project Reboot 3.0/GameModeBase.cpp +++ b/Project Reboot 3.0/GameModeBase.cpp @@ -3,13 +3,28 @@ #include "reboot.h" #include "FortPlayerControllerAthena.h" +UClass* AGameModeBase::GetDefaultPawnClassForController(AController* InController) +{ + static auto GetDefaultPawnClassForControllerFn = FindObject("/Script/Engine.GameModeBase.GetDefaultPawnClassForController"); + struct + { + AController* InController; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + UClass* ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + } AGameModeBase_GetDefaultPawnClassForController_Params{InController}; + + this->ProcessEvent(GetDefaultPawnClassForControllerFn, &AGameModeBase_GetDefaultPawnClassForController_Params); + + return AGameModeBase_GetDefaultPawnClassForController_Params.ReturnValue; +} + APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AController* NewPlayer, AActor* StartSpot) { LOG_INFO(LogDev, "SpawnDefaultPawnFor: 0x{:x}!", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0))); - static auto PawnClass = FindObject("/Game/Athena/PlayerPawn_Athena.PlayerPawn_Athena_C"); - GameMode->Get("DefaultPawnClass") = PawnClass; - + // static auto PawnClass = FindObject("/Game/Athena/PlayerPawn_Athena.PlayerPawn_Athena_C"); + // GameMode->Get("DefaultPawnClass") = PawnClass; + auto PawnClass = GameMode->GetDefaultPawnClassForController(NewPlayer); + static auto fn = FindObject(L"/Script/Engine.GameModeBase.SpawnDefaultPawnAtTransform"); struct { AController* NewPlayer; FTransform SpawnTransform; APawn* ReturnValue; } diff --git a/Project Reboot 3.0/GameModeBase.h b/Project Reboot 3.0/GameModeBase.h index dc23d87..dae256e 100644 --- a/Project Reboot 3.0/GameModeBase.h +++ b/Project Reboot 3.0/GameModeBase.h @@ -8,5 +8,7 @@ class AGameModeBase : public AActor // AInfo { public: + UClass* GetDefaultPawnClassForController(AController* InController); + static APawn* SpawnDefaultPawnForHook(AGameModeBase* GameMode, AController* NewPlayer, AActor* StartSpot); }; \ No newline at end of file diff --git a/Project Reboot 3.0/Map.h b/Project Reboot 3.0/Map.h index e719d33..5b94545 100644 --- a/Project Reboot 3.0/Map.h +++ b/Project Reboot 3.0/Map.h @@ -39,6 +39,17 @@ public: typedef TSet ElementSetType; ElementSetType Pairs; + + FORCEINLINE ValueType& Find(const KeyType& Key) + { + for (int j = 0; j < this->Pairs.Elements.Num(); j++) + { + ElementType& Pair = this->Pairs.Elements.operator[](j).ElementData.Value; + + if (Key == Pair.Key()) + return Pair.Value(); + } + } }; template //, typename SetAllocator, typename KeyFuncs> diff --git a/Project Reboot 3.0/NameTypes.h b/Project Reboot 3.0/NameTypes.h index aa71946..94fd757 100644 --- a/Project Reboot 3.0/NameTypes.h +++ b/Project Reboot 3.0/NameTypes.h @@ -12,6 +12,7 @@ struct FName FNameEntryId ComparisonIndex; uint32 Number; + std::string ToString() const; std::string ToString(); bool IsValid() { return ComparisonIndex.Value > 0; } diff --git a/Project Reboot 3.0/NetConnection.h b/Project Reboot 3.0/NetConnection.h new file mode 100644 index 0000000..0ce7905 --- /dev/null +++ b/Project Reboot 3.0/NetConnection.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Player.h" + +class UNetConnection : public UPlayer +{ +public: + AActor*& GetOwningActor() + { + static auto OwningActorOffset = GetOffset("OwningActor"); + return Get(OwningActorOffset); + } + + AActor*& GetViewTarget() + { + static auto ViewTargetOffset = GetOffset("ViewTarget"); + return Get(ViewTargetOffset); + } +}; \ No newline at end of file diff --git a/Project Reboot 3.0/NetDriver.cpp b/Project Reboot 3.0/NetDriver.cpp index e7aecc4..36bde19 100644 --- a/Project Reboot 3.0/NetDriver.cpp +++ b/Project Reboot 3.0/NetDriver.cpp @@ -1,6 +1,9 @@ #include "NetDriver.h" #include "reboot.h" +#include "Actor.h" +#include "NetConnection.h" +#include "GameplayStatics.h" void UNetDriver::TickFlushHook(UNetDriver* NetDriver) { @@ -19,7 +22,283 @@ void UNetDriver::TickFlushHook(UNetDriver* NetDriver) return TickFlushOriginal(NetDriver); } -void UNetDriver::ServerReplicateActors() +int32 ServerReplicateActors_PrepConnections(UNetDriver* NetDriver) { + auto& ClientConnections = NetDriver->GetClientConnections(); + int32 NumClientsToTick = ClientConnections.Num(); + + bool bFoundReadyConnection = false; + + for (int32 ConnIdx = 0; ConnIdx < ClientConnections.Num(); ConnIdx++) + { + UNetConnection* Connection = ClientConnections.at(ConnIdx); + // check(Connection); + // check(Connection->State == USOCK_Pending || Connection->State == USOCK_Open || Connection->State == USOCK_Closed); + // checkSlow(Connection->GetUChildConnection() == NULL); + + AActor* OwningActor = Connection->GetOwningActor(); + if (OwningActor != NULL) // && /* Connection->State == USOCK_Open && */ (Connection->Driver->Time - Connection->LastReceiveTime < 1.5f)) + { + // check(World == OwningActor->GetWorld()); + + bFoundReadyConnection = true; + + // the view target is what the player controller is looking at OR the owning actor itself when using beacons + Connection->GetViewTarget() = Connection->GetPlayerController() ? Connection->GetPlayerController()->GetViewTarget() : OwningActor; + } + else + { + Connection->GetViewTarget() = NULL; + } + } + + return bFoundReadyConnection ? NumClientsToTick : 0; +} + +enum class ENetRole : uint8_t +{ + ROLE_None = 0, + ROLE_SimulatedProxy = 1, + ROLE_AutonomousProxy = 2, + ROLE_Authority = 3, + ROLE_MAX = 4 +}; + +enum class ENetDormancy : uint8_t +{ + DORM_Never = 0, + DORM_Awake = 1, + DORM_DormantAll = 2, + DORM_DormantPartial = 3, + DORM_Initial = 4, + DORN_MAX = 5, + ENetDormancy_MAX = 6 +}; + +struct FNetworkObjectInfo +{ + AActor* Actor; + /* TWeakObjectPtr WeakActor; + double NextUpdateTime; + double LastNetReplicateTime; + float OptimalNetUpdateDelta; + float LastNetUpdateTime; + uint32 bPendingNetUpdate : 1; + uint32 bForceRelevantNextUpdate : 1; + TSet> DormantConnections; + TSet> RecentlyDormantConnections; */ +}; + +static void ServerReplicateActors_BuildConsiderList(UNetDriver* NetDriver, std::vector& OutConsiderList) +{ + TArray Actors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass()); + + /* auto& ActiveObjects = GetNetworkObjectList(NetDriver).ActiveNetworkObjects; + + for (int i = 0; i < ActiveObjects.Num(); i++) + { + auto ActorInfo = ActiveObjects.GetElements().GetData()[i].ElementData.Value.Get(); + auto Actor = ActorInfo->Actor; */ + + for (int i = 0; i < Actors.Num(); i++) + { + auto Actor = Actors.at(i); + + if (!Actor) + continue; + + // if (!Actor->bActorInitialized) continue; + + if (Actor->IsActorBeingDestroyed()) + { + continue; + } + + static auto RemoteRoleOffset = Actor->GetOffset("RemoteRole"); + + if (Actor->Get(RemoteRoleOffset) == ENetRole::ROLE_None) + { + continue; + } + + static auto NetDormancyOffset = Actor->GetOffset("NetDormancy"); + + if (Actor->Get(NetDormancyOffset) == ENetDormancy::DORM_Initial && Actor->IsNetStartup()) + { + continue; + } + + static void (*CallPreReplication)(AActor*, UNetDriver*) = decltype(CallPreReplication)(Addresses::CallPreReplication); + CallPreReplication(Actor, NetDriver); + + FNetworkObjectInfo* ActorInfo = new FNetworkObjectInfo; + ActorInfo->Actor = Actor; + OutConsiderList.push_back(ActorInfo); + } + + Actors.Free(); +} + +using UChannel = UObject; +using UActorChannel = UObject; + +static UActorChannel* FindChannel(AActor* Actor, UNetConnection* Connection) +{ + static auto OpenChannelsOffset = Connection->GetOffset("OpenChannels"); + auto& OpenChannels = Connection->Get>(OpenChannelsOffset); + + static auto ActorChannelClass = FindObject("/Script/Engine.ActorChannel"); + + // LOG_INFO(LogReplication, "OpenChannels.Num(): {}", OpenChannels.Num()); + + for (int i = 0; i < OpenChannels.Num(); i++) + { + auto Channel = OpenChannels.at(i); + + if (!Channel) + continue; + + // LOG_INFO(LogReplication, "[{}] Class {}", i, Channel->ClassPrivate ? Channel->ClassPrivate->GetFullName() : "InvalidObject"); + + if (!Channel->IsA(ActorChannelClass)) // (Channel->ClassPrivate == ActorChannelClass) + continue; + + static auto ActorOffset = Channel->GetOffset("Actor"); + auto ChannelActor = Channel->Get(ActorOffset); + + // LOG_INFO(LogReplication, "[{}] {}", i, ChannelActor->GetFullName()); + + if (ChannelActor != Actor) + continue; + + return (UActorChannel*)Channel; + } + + return NULL; +} + +int32 UNetDriver::ServerReplicateActors() +{ + int32 Updated = 0; + + ++*(int*)(this + Offsets::ReplicationFrame); + + const int32 NumClientsToTick = ServerReplicateActors_PrepConnections(this); + + if (NumClientsToTick == 0) + { + // No connections are ready this frame + return 0; + } + + // AFortWorldSettings* WorldSettings = GetFortWorldSettings(NetDriver->World); + + // bool bCPUSaturated = false; + float ServerTickTime = 30.f; // Globals::MaxTickRate; // GEngine->GetMaxTickRate(DeltaSeconds); + /* if (ServerTickTime == 0.f) + { + ServerTickTime = DeltaSeconds; + } + else */ + { + ServerTickTime = 1.f / ServerTickTime; + // bCPUSaturated = DeltaSeconds > 1.2f * ServerTickTime; + } + + std::vector ConsiderList; + // ConsiderList.reserve(GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num()); + + // std::cout << "ConsiderList.size(): " << GetNetworkObjectList(NetDriver).ActiveNetworkObjects.Num() << '\n'; + + ServerReplicateActors_BuildConsiderList(this, ConsiderList); + + for (int32 i = 0; i < this->GetClientConnections().Num(); i++) + { + UNetConnection* Connection = this->GetClientConnections().at(i); + + if (!Connection) + continue; + + if (i >= NumClientsToTick) + continue; + + if (!Connection->GetViewTarget()) + continue; + + if (Connection->GetPlayerController()) + { + static void (*SendClientAdjustment)(APlayerController*) = decltype(SendClientAdjustment)(Addresses::SendClientAdjustment); + SendClientAdjustment(Connection->GetPlayerController()); + } + + for (auto& ActorInfo : ConsiderList) + { + if (!ActorInfo || !ActorInfo->Actor) + continue; + + auto Actor = ActorInfo->Actor; + + auto Channel = FindChannel(Actor, Connection); + + /* std::vector ConnectionViewers; + ConnectionViewers.push_back(ConstructNetViewer(Connection)); + + if (!Actor->bAlwaysRelevant && !Actor->bNetUseOwnerRelevancy && !Actor->bOnlyRelevantToOwner) + { + if (Connection && Connection->ViewTarget) + { + auto Viewer = Connection->ViewTarget; + auto Loc = Viewer->K2_GetActorLocation(); + + if (!IsActorRelevantToConnection(Actor, ConnectionViewers)) + { + if (Channel) + CloseChannel(Channel); + + continue; + } + } + } */ + + static UChannel* (*CreateChannel)(UNetConnection*, int, bool, int32_t) = decltype(CreateChannel)(Addresses::CreateChannel); + static __int64 (*ReplicateActor)(UActorChannel*) = decltype(ReplicateActor)(Addresses::ReplicateActor); + static __int64 (*SetChannelActor)(UActorChannel*, AActor*) = decltype(SetChannelActor)(Addresses::SetChannelActor); + + if (!Channel) + { + if (Actor->IsA(APlayerController::StaticClass()) && Actor != Connection->GetPlayerController()) // isnetreelvantfor should handle this iirc + continue; + + Channel = (UActorChannel*)CreateChannel(Connection, 2, true, -1); + + if (Channel) { + SetChannelActor(Channel, Actor); + // Channel->Connection = Connection; + } + + } + + if (Channel) + ReplicateActor(Channel); + } + } + + // shuffle the list of connections if not all connections were ticked + /* + if (NumClientsToTick < NetDriver->ClientConnections.Num()) + { + int32 NumConnectionsToMove = NumClientsToTick; + while (NumConnectionsToMove > 0) + { + // move all the ticked connections to the end of the list so that the other connections are considered first for the next frame + UNetConnection* Connection = NetDriver->ClientConnections[0]; + NetDriver->ClientConnections.RemoveAt(0, 1); + NetDriver->ClientConnections.Add(Connection); + NumConnectionsToMove--; + } + } + */ + + return Updated; } \ No newline at end of file diff --git a/Project Reboot 3.0/NetDriver.h b/Project Reboot 3.0/NetDriver.h index d46467c..a81e9ae 100644 --- a/Project Reboot 3.0/NetDriver.h +++ b/Project Reboot 3.0/NetDriver.h @@ -4,6 +4,8 @@ #include "UnrealString.h" #include "World.h" +#include "NetConnection.h" +#include "Array.h" class UWorld; @@ -29,7 +31,13 @@ public: static void TickFlushHook(UNetDriver* NetDriver); + TArray& GetClientConnections() + { + static auto ClientConnectionsOffset = GetOffset("ClientConnections"); + return Get>(ClientConnectionsOffset); + } + bool InitListen(FNetworkNotify* InNotify, FURL& ListenURL, bool bReuseAddressAndPort, FString& Error) { return InitListenOriginal(this, InNotify, ListenURL, bReuseAddressAndPort, Error); } void SetWorld(UWorld* World) { return SetWorldOriginal(this, World); } - void ServerReplicateActors(); + int32 ServerReplicateActors(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/Player.h b/Project Reboot 3.0/Player.h new file mode 100644 index 0000000..eac0941 --- /dev/null +++ b/Project Reboot 3.0/Player.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Object.h" +#include "PlayerController.h" + +class UPlayer : public UObject +{ +public: + APlayerController*& GetPlayerController() + { + static auto PlayerControllerOffset = GetOffset("PlayerController"); + return Get(PlayerControllerOffset); + } +}; \ No newline at end of file diff --git a/Project Reboot 3.0/PlayerController.h b/Project Reboot 3.0/PlayerController.h index 5d98c84..c6937b5 100644 --- a/Project Reboot 3.0/PlayerController.h +++ b/Project Reboot 3.0/PlayerController.h @@ -1,11 +1,11 @@ #pragma once #include "Class.h" -#include "Actor.h" +#include "Controller.h" #include "Rotator.h" -class APlayerController : public AActor +class APlayerController : public AController { public: /* void Possess(APawn* Pawn) diff --git a/Project Reboot 3.0/Project Reboot 3.0.vcxproj b/Project Reboot 3.0/Project Reboot 3.0.vcxproj index 8700b6b..6f21a87 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj @@ -173,6 +173,7 @@ + @@ -205,6 +206,7 @@ + @@ -293,6 +295,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 3a472a9..1ce4220 100644 --- a/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters +++ b/Project Reboot 3.0/Project Reboot 3.0.vcxproj.filters @@ -110,9 +110,6 @@ Reboot\Private\Gameplay - - Reboot\Private\Gameplay - FortniteGame\Source\FortniteGame\Private\Player @@ -143,6 +140,15 @@ Engine\Source\Runtime\Engine\Private + + Reboot\Private + + + Engine\Source\Runtime\Engine\Classes\Engine + + + Engine\Source\Runtime\Engine\Private + @@ -395,9 +401,6 @@ FortniteGame\Source\FortniteGame\Public - - Reboot\Public - FortniteGame\Source\FortniteGame\Public\Creative @@ -434,6 +437,12 @@ Reboot\Public + + Reboot\Public\Gameplay + + + Engine\Source\Runtime\Engine\Classes\Engine + diff --git a/Project Reboot 3.0/UnrealNames.cpp b/Project Reboot 3.0/UnrealNames.cpp index 53f670a..1115363 100644 --- a/Project Reboot 3.0/UnrealNames.cpp +++ b/Project Reboot 3.0/UnrealNames.cpp @@ -5,7 +5,7 @@ #include "KismetStringLibrary.h" -std::string FName::ToString() +std::string FName::ToString() const { static auto KismetStringLibrary = FindObject(L"/Script/Engine.Default__KismetStringLibrary"); @@ -19,5 +19,22 @@ std::string FName::ToString() // Conv_NameToString_Params.OutStr.Free(); + return Str; +} + +std::string FName::ToString() +{ + static auto KismetStringLibrary = FindObject(L"/Script/Engine.Default__KismetStringLibrary"); + + static auto Conv_NameToString = FindObject(L"/Script/Engine.KismetStringLibrary.Conv_NameToString"); + + struct { FName InName; FString OutStr; } Conv_NameToString_Params{ *this }; + + KismetStringLibrary->ProcessEvent(Conv_NameToString, &Conv_NameToString_Params); + + auto Str = Conv_NameToString_Params.OutStr.ToString(); + + // Conv_NameToString_Params.OutStr.Free(); + return Str; } \ No newline at end of file diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 70037c9..0b3600e 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -114,95 +114,129 @@ void Addresses::FindAll() { auto Base = __int64(GetModuleHandleW(0)); - LOG_INFO(LogDev, "9241"); + LOG_INFO(LogDev, "Finding ProcessEvent"); Addresses::ProcessEvent = FindProcessEvent(); UObject::ProcessEventOriginal = decltype(UObject::ProcessEventOriginal)(ProcessEvent); - LOG_INFO(LogDev, "151"); + LOG_INFO(LogDev, "Finding StaticFindObject"); Addresses::StaticFindObject = FindStaticFindObject(); StaticFindObjectOriginal = decltype(StaticFindObjectOriginal)(StaticFindObject); LOG_INFO(LogDev, "StaticFindObject: 0x{:x}", StaticFindObject - Base); - LOG_INFO(LogDev, "2151"); + LOG_INFO(LogDev, "Finding GetPlayerViewpoint"); Addresses::GetPlayerViewpoint = FindGetPlayerViewpoint(); - LOG_INFO(LogDev, "1246"); + LOG_INFO(LogDev, "Finding CreateNetDriver"); Addresses::CreateNetDriver = FindCreateNetDriver(); - LOG_INFO(LogDev, "2561"); + LOG_INFO(LogDev, "Finding InitHost"); Addresses::InitHost = FindInitHost(); - LOG_INFO(LogDev, "1341"); + LOG_INFO(LogDev, "Finding PauseBeaconRequests"); Addresses::PauseBeaconRequests = FindPauseBeaconRequests(); - LOG_INFO(LogDev, "1351"); + LOG_INFO(LogDev, "Finding SpawnActor"); Addresses::SpawnActor = FindSpawnActor(); - LOG_INFO(LogDev, "1`231"); + LOG_INFO(LogDev, "Finding InitListen"); Addresses::InitListen = FindInitListen(); - LOG_INFO(LogDev, "52175"); + LOG_INFO(LogDev, "Finding SetWorld"); Addresses::SetWorld = FindSetWorld(); - LOG_INFO(LogDev, "5432"); + LOG_INFO(LogDev, "Finding Kickplayer"); Addresses::KickPlayer = FindKickPlayer(); - LOG_INFO(LogDev, "123"); + LOG_INFO(LogDev, "Finding TickFlush"); Addresses::TickFlush = FindTickFlush(); - LOG_INFO(LogDev, "1123"); + LOG_INFO(LogDev, "Finding GetNetMode"); Addresses::GetNetMode = FindGetNetMode(); - LOG_INFO(LogDev, "113"); + LOG_INFO(LogDev, "Finding Realloc"); Addresses::Realloc = FindRealloc(); - LOG_INFO(LogDev, "1231"); + LOG_INFO(LogDev, "Finding CollectGarbage"); Addresses::CollectGarbage = FindCollectGarbage(); - LOG_INFO(LogDev, "112113"); + LOG_INFO(LogDev, "Finding NoMCP"); Addresses::NoMCP = FindNoMCP(); - LOG_INFO(LogDev, "131"); + LOG_INFO(LogDev, "Finding PickTeam"); Addresses::PickTeam = FindPickTeam(); - LOG_INFO(LogDev, "132"); + LOG_INFO(LogDev, "Finding InternalTryActivateAbility"); Addresses::InternalTryActivateAbility = FindInternalTryActivateAbility(); - LOG_INFO(LogDev, "17"); + LOG_INFO(LogDev, "Finding GiveAbility"); Addresses::GiveAbility = FindGiveAbility(); - LOG_INFO(LogDev, "156"); + LOG_INFO(LogDev, "Finding CantBuild"); Addresses::CantBuild = FindCantBuild(); - LOG_INFO(LogDev, "16"); + LOG_INFO(LogDev, "Finding ReplaceBuildingActor"); Addresses::ReplaceBuildingActor = FindReplaceBuildingActor(); - LOG_INFO(LogDev, "15"); + LOG_INFO(LogDev, "Finding GiveAbilityAndActivateOnce"); Addresses::GiveAbilityAndActivateOnce = FindGiveAbilityAndActivateOnce(); - LOG_INFO(LogDev, "14"); + LOG_INFO(LogDev, "Finding OnDamageServer"); Addresses::OnDamageServer = FindOnDamageServer(); - LOG_INFO(LogDev, "13"); + LOG_INFO(LogDev, "Finding StaticLoadObject"); Addresses::StaticLoadObject = FindStaticLoadObject(); - LOG_INFO(LogDev, "12"); + LOG_INFO(LogDev, "Finding ActorGetNetMode"); Addresses::ActorGetNetMode = FindActorGetNetMode(); - LOG_INFO(LogDev, "11"); + LOG_INFO(LogDev, "Finding ChangeGameSessionId"); Addresses::ChangeGameSessionId = FindChangeGameSessionId(); - LOG_INFO(LogDev, "10"); + LOG_INFO(LogDev, "Finding DispatchRequest"); Addresses::DispatchRequest = FindDispatchRequest(); + LOG_INFO(LogDev, "Finding AddNavigationSystemToWorld"); + Addresses::AddNavigationSystemToWorld = FindAddNavigationSystemToWorld(); + LOG_INFO(LogDev, "Finding NavSystemCleanUp"); + Addresses::NavSystemCleanUp = FindNavSystemCleanUp(); + LOG_INFO(LogDev, "Finding LoadPlayset"); + Addresses::LoadPlayset = FindLoadPlayset(); + LOG_INFO(LogDev, "Finding SetZoneToIndex"); + Addresses::SetZoneToIndex = FindSetZoneToIndex(); + LOG_INFO(LogDev, "Finding CompletePickupAnimation"); + Addresses::CompletePickupAnimation = FindCompletePickupAnimation(); + LOG_INFO(LogDev, "Finding CanActivateAbility"); + Addresses::CanActivateAbility = FindCanActivateAbility(); + LOG_INFO(LogDev, "Finding SpecConstructor"); + Addresses::SpecConstructor = FindSpecConstructor(); + LOG_INFO(LogDev, "Finding FrameStep"); + Addresses::FrameStep = FindFrameStep(); + LOG_INFO(LogDev, "Finding ObjectArray"); + Addresses::ObjectArray = FindObjectArray(); + LOG_INFO(LogDev, "Finding ReplicateActor"); + + Addresses::ReplicateActor = FindReplicateActor(); + LOG_INFO(LogDev, "Finding SetChannelActor"); + + Addresses::SetChannelActor = FindSetChannelActor(); + LOG_INFO(LogDev, "Finding SendClientAdjustment"); + + Addresses::SendClientAdjustment = FindSendClientAdjustment(); + LOG_INFO(LogDev, "Finding CreateChannel"); + + Addresses::CreateChannel = FindCreateChannel(); + LOG_INFO(LogDev, "Finding CallPreReplication"); + + Addresses::CallPreReplication = FindCallPreReplication(); + LOG_INFO(LogDev, "Finished finding!"); } void Addresses::Print() @@ -245,6 +279,11 @@ void Addresses::Print() LOG_INFO(LogDev, "SpecConstructor: 0x{:x}", SpecConstructor - Base); LOG_INFO(LogDev, "FrameStep: 0x{:x}", FrameStep - Base); LOG_INFO(LogDev, "ObjectArray: 0x{:x}", ObjectArray - Base); + LOG_INFO(LogDev, "ReplicateActor: 0x{:x}", ReplicateActor - Base); + LOG_INFO(LogDev, "SetChannelActor: 0x{:x}", SetChannelActor - Base); + LOG_INFO(LogDev, "SendClientAdjustment: 0x{:x}", SendClientAdjustment - Base); + LOG_INFO(LogDev, "CreateChannel: 0x{:x}", CreateChannel - Base); + LOG_INFO(LogDev, "CallPreReplication: 0x{:x}", CallPreReplication - Base); } void Offsets::FindAll() @@ -254,7 +293,7 @@ void Offsets::FindAll() Offsets::Children = Engine_Version >= 425 ? 0x50 : Offsets::SuperStruct + 8; Offsets::PropertiesSize = Offsets::Children + 8; - if (Engine_Version == 420 || Engine_Version == 421) + if (Engine_Version >= 419 && Engine_Version <= 421) Offsets::Func = 0xB0; else if (Engine_Version >= 422 && Engine_Version <= 424) Offsets::Func = 0xC0; @@ -284,6 +323,9 @@ void Offsets::FindAll() Offsets::ServerReplicateActors = 0x66; else if (std::floor(Fortnite_Version) >= 21) Offsets::ServerReplicateActors = 0x67; // checked onb 22.30 + + if (Engine_Version == 419) + Offsets::ReplicationFrame = 0xB2; } void Offsets::Print() @@ -293,6 +335,8 @@ void Offsets::Print() LOG_INFO(LogDev, "Children: 0x{:x}", Children); LOG_INFO(LogDev, "PropertiesSize: 0x{:x}", PropertiesSize); LOG_INFO(LogDev, "Func: 0x{:x}", Func); + LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors); + LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame); } void Addresses::Init() diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index c17f201..2ad8638 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -44,6 +44,11 @@ namespace Addresses extern inline uint64 CompletePickupAnimation = 0; extern inline uint64 CanActivateAbility = 0; extern inline uint64 SpecConstructor = 0; + extern inline uint64 ReplicateActor = 0; + extern inline uint64 CallPreReplication = 0; + extern inline uint64 CreateChannel = 0; + extern inline uint64 SetChannelActor = 0; + extern inline uint64 SendClientAdjustment = 0; extern inline uint64 FrameStep = 0; void SetupVersion(); // Finds Engine Version @@ -62,7 +67,8 @@ namespace Offsets extern inline uint64 SuperStruct = 0; extern inline uint64 Offset_Internal = 0; extern inline uint64 ServerReplicateActors = 0; - + extern inline uint64 ReplicationFrame = 0; + void FindAll(); void Print(); } diff --git a/Project Reboot 3.0/ai.h b/Project Reboot 3.0/ai.h index 515a414..3b9d33a 100644 --- a/Project Reboot 3.0/ai.h +++ b/Project Reboot 3.0/ai.h @@ -5,6 +5,9 @@ #include "SoftObjectPath.h" #include "KismetStringLibrary.h" #include "GameplayStatics.h" +#include "FortPlayerPawn.h" +#include "FortPlayerController.h" +#include "FortPlayerControllerAthena.h" using UNavigationSystemV1 = UObject; using UNavigationSystemConfig = UObject; @@ -60,7 +63,7 @@ static void SetNavigationSystem(AAthenaNavSystemConfigOverride* NavSystemOverrid if (!NewNavSystemClass) return; - LOG_INFO(LogAI, "Setup navigation system.\n"); + LOG_INFO(LogAI, "Setup navigation system."); AddNavigationSystemToWorldOriginal(*GetWorld(), EFNavigationSystemRunMode::GameMode, NavSystemOverride->Get("NavigationSystemConfig"), true, false); } @@ -82,10 +85,69 @@ static void SetupNavConfig() AthenaNavConfig->Get("bAutoSpawnMissingNavData") = true; // BITFIELD AthenaNavConfig->Get("bSpawnNavDataInNavBoundsLevel") = true; // BITFIELD AthenaNavConfig->Get("bUseNavigationInvokers") = false; - AthenaNavConfig->Get("DefaultAgentName") = UKismetStringLibrary::Conv_StringToName(L"MANG"); + AthenaNavConfig->Get("DefaultAgentName") = UKismetStringLibrary::Conv_StringToName(L"Galileo"); // 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; } \ No newline at end of file diff --git a/Project Reboot 3.0/commands.h b/Project Reboot 3.0/commands.h index 472c20a..c297aa0 100644 --- a/Project Reboot 3.0/commands.h +++ b/Project Reboot 3.0/commands.h @@ -246,6 +246,25 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg) else if (Command == "spawnaidata") { + } + else if (Command == "sethealth") + { + auto Pawn = ReceivingController->GetMyFortPawn(); + + if (!Pawn) + { + SendMessageToConsole(PlayerController, L"No pawn!"); + return; + } + + float Health = 100.f; + + try { Health = std::stof(Arguments[1]); } + catch (...) {} + + static auto SetHealthFn = FindObject("/Script/FortniteGame.FortPawn.SetHealth"); + Pawn->ProcessEvent(SetHealthFn, &Health); + SendMessageToConsole(PlayerController, L"Set health!\n"); } else if (Command == "testspawn") { diff --git a/Project Reboot 3.0/die.h b/Project Reboot 3.0/die.h index 340e522..7672bc3 100644 --- a/Project Reboot 3.0/die.h +++ b/Project Reboot 3.0/die.h @@ -21,6 +21,7 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override static auto SafeZoneFinishShrinkTimeOffset = SafeZoneIndicator->GetOffset("SafeZoneFinishShrinkTime"); static auto SafeZoneStartShrinkTimeOffset = SafeZoneIndicator->GetOffset("SafeZoneStartShrinkTime"); + static auto RadiusOffset = SafeZoneIndicator->GetOffset("Radius"); static auto SafeZonePhaseOffset = GameModeAthena->GetOffset("SafeZonePhase"); @@ -30,7 +31,9 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override static auto SafeZoneDefinitionOffset = MapInfo->GetOffset("SafeZoneDefinition"); auto SafeZoneDefinition = MapInfo->GetPtr<__int64>(SafeZoneDefinitionOffset); - static auto ZoneDurationsOffset = 0x1F8; + LOG_INFO(LogDev, "SafeZoneDefinitionOffset: 0x{:x}", SafeZoneDefinitionOffset); + + static auto ZoneDurationsOffset = std::floor(Fortnite_Version) >= 18 ? 0x248 : 0x1F8; static auto ZoneHoldDurationsOffset = ZoneDurationsOffset - 0x10; auto& ZoneDurations = *(TArray*)(__int64(SafeZoneDefinition) + ZoneDurationsOffset); @@ -51,9 +54,17 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override if (!FortGameData) FortGameData = FindObject("/Game/Balance/AthenaGameData.AthenaGameData"); + LOG_INFO(LogDev, "FortGameData: {}", FortGameData ? FortGameData->GetFullName() : "InvalidObject"); + auto ShrinkTimeFName = UKismetStringLibrary::Conv_StringToName(L"Default.SafeZone.ShrinkTime"); + auto HoldTimeFName = UKismetStringLibrary::Conv_StringToName(L"Default.SafeZone.WaitTime"); FString ContextString; + /* for (int i = 0; i < 10; i++) + { + LOG_INFO(LogDev, "[{}] Value {}", i, FortGameData->GetValueOfKey(FortGameData->GetKey(ShrinkTimeFName, i))); + } */ + /* for (float i = 0; i < 1.1; i += 0.1) { float res; @@ -61,6 +72,26 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override LOG_INFO(LogZone, "[{}] {}", i, res); } */ + for (int i = 0; i < ZoneDurations.Num(); i++) + { + ZoneDurations.at(i) = FortGameData->GetValueOfKey(FortGameData->GetKey(ShrinkTimeFName, i)); + } + for (int i = 0; i < ZoneHoldDurations.Num(); i++) + { + ZoneHoldDurations.at(i) = FortGameData->GetValueOfKey(FortGameData->GetKey(HoldTimeFName, i)); + } + + for (int i = 0; i < ZoneDurations.Num(); i++) + { + LOG_INFO(LogZone, "Move [{}] {}", i, ZoneDurations.at(i)); + } + + for (int i = 0; i < ZoneHoldDurations.Num(); i++) + { + LOG_INFO(LogZone, "Hold [{}] {}", i, ZoneHoldDurations.at(i)); + } + + /* if (ZoneDurations.ArrayNum >= 1) ZoneDurations.at(0) = 0; if (ZoneDurations.ArrayNum >= 2) ZoneDurations.at(1) = 180; if (ZoneDurations.ArrayNum >= 3) ZoneDurations.at(2) = 120; @@ -84,22 +115,13 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override if (ZoneHoldDurations.ArrayNum >= 9) ZoneHoldDurations.at(8) = 0; if (ZoneHoldDurations.ArrayNum >= 10) ZoneHoldDurations.at(9) = 0; if (ZoneHoldDurations.ArrayNum >= 11) ZoneHoldDurations.at(10) = 0; + */ } LOG_INFO(LogZone, "SafeZonePhase: {}", GameModeAthena->Get(SafeZonePhaseOffset)); LOG_INFO(LogZone, "OverridePhaseMaybeIDFK: {}", OverridePhaseMaybeIDFK); LOG_INFO(LogZone, "TimeSeconds: {}", UGameplayStatics::GetTimeSeconds(GetWorld())); - for (int i = 0; i < ZoneDurations.Num(); i++) - { - LOG_INFO(LogZone, "Move [{}] {}", i, ZoneDurations.at(i)); - } - - for (int i = 0; i < ZoneHoldDurations.Num(); i++) - { - LOG_INFO(LogZone, "Hold [{}] {}", i, ZoneHoldDurations.at(i)); - } - SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); LOG_INFO(LogZone, "SafeZonePhase After: {}", GameModeAthena->Get(SafeZonePhaseOffset)); @@ -117,6 +139,7 @@ static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int Override ZoneDuration = ZoneDurations.at(GameModeAthena->Get(SafeZonePhaseOffset)); LOG_INFO(LogZone, "ZoneDuration: {}", ZoneDuration); + LOG_INFO(LogZone, "Duration: {}", SafeZoneIndicator->Get(RadiusOffset)); SafeZoneIndicator->Get(SafeZoneFinishShrinkTimeOffset) = SafeZoneIndicator->Get(SafeZoneStartShrinkTimeOffset) + ZoneDuration; } \ No newline at end of file diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index 1ff0e56..f9be511 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -256,11 +256,11 @@ DWORD WINAPI Main(LPVOID) AFortPlayerPawn::ServerHandlePickupHook, nullptr, false); } + static auto PredictionKeyStruct = FindObject("/Script/GameplayAbilities.PredictionKey"); + static auto PredictionKeySize = PredictionKeyStruct->GetPropertiesSize(); + if (Globals::bAbilitiesEnabled) { - static auto PredictionKeyStruct = FindObject("/Script/GameplayAbilities.PredictionKey"); - static auto PredictionKeySize = PredictionKeyStruct->GetPropertiesSize(); - if (PredictionKeySize == 0x10) { Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbility"), @@ -307,12 +307,23 @@ DWORD WINAPI Main(LPVOID) LOG_INFO(LogDev, "Test: 0x{:x}", FindFunctionCall(L"ClientOnPawnDied") - __int64(GetModuleHandleW(0))); Hooking::MinHook::Hook((PVOID)FindFunctionCall(L"ClientOnPawnDied"), AFortPlayerController::ClientOnPawnDiedHook, (PVOID*)&AFortPlayerController::ClientOnPawnDiedOriginal); - { - int increaseOffset = 0x18; // 0x10; - MemberOffsets::FortPlayerPawn::CorrectTags = FindOffsetStruct("/Script/FortniteGame.FortPlayerPawn", "MoveSoundStimulusBroadcastInterval") + increaseOffset; - MemberOffsets::FortPlayerState::PawnDeathLocation = FindOffsetStruct("/Script/FortniteGame.FortPlayerState", "PawnDeathLocation"); + LOG_INFO(LogDev, "PredictionKeySize: 0x{:x} {}", PredictionKeySize, PredictionKeySize); - MemberOffsets::FortPlayerPawnAthena::LastFallDistance = FindOffsetStruct("/Script/FortniteGame.FortPlayerPawnAthena", "LastFallDistance"); + static auto GameplayEventDataSize = FindObject("/Script/GameplayAbilities.GameplayEventData")->GetPropertiesSize(); + LOG_INFO(LogDev, "GameplayEventDataSize: 0x{:x} {}", GameplayEventDataSize, GameplayEventDataSize); + + { + int increaseOffset = 0x10; + + if (Engine_Version >= 424 && std::floor(Fortnite_Version) < 18) // checked on 11.31, 12.41, 14.60, 15.10, 16.40, 17.30 and 18.40 + increaseOffset += 0x8; + + auto MoveSoundStimulusBroadcastIntervalOffset = FindOffsetStruct("/Script/FortniteGame.FortPlayerPawn", "MoveSoundStimulusBroadcastInterval"); + MemberOffsets::FortPlayerPawn::CorrectTags = MoveSoundStimulusBroadcastIntervalOffset + increaseOffset; + LOG_INFO(LogDev, "CorrectTags: 0x{:x}", MemberOffsets::FortPlayerPawn::CorrectTags); + MemberOffsets::FortPlayerState::PawnDeathLocation = FindOffsetStruct("/Script/FortniteGame.FortPlayerState", "PawnDeathLocation", false); + + MemberOffsets::FortPlayerPawnAthena::LastFallDistance = FindOffsetStruct("/Script/FortniteGame.FortPlayerPawnAthena", "LastFallDistance", false); MemberOffsets::FortPlayerStateAthena::DeathInfo = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "DeathInfo"); MemberOffsets::FortPlayerStateAthena::KillScore = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "KillScore"); @@ -323,7 +334,7 @@ DWORD WINAPI Main(LPVOID) MemberOffsets::DeathInfo::bInitialized = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "bInitialized", false); MemberOffsets::DeathInfo::Distance = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "Distance"); MemberOffsets::DeathInfo::DeathTags = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathTags", false); - MemberOffsets::DeathInfo::DeathLocation = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathLocation"); + MemberOffsets::DeathInfo::DeathLocation = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathLocation", false); MemberOffsets::DeathReport::Tags = FindOffsetStruct("/Script/FortniteGame.FortPlayerDeathReport", "Tags"); MemberOffsets::DeathReport::KillerPawn = FindOffsetStruct("/Script/FortniteGame.FortPlayerDeathReport", "KillerPawn"); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 5d39f32..4d7da93 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -121,6 +121,9 @@ static inline uint64 FindCreateNetDriver() static inline uint64 FindKickPlayer() { + if (std::floor(Fortnite_Version) == 18) + return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 48 89 70 10 48 89 78 18 4C 89 60 20 55 41 56 41 57 48 8B EC 48 83 EC 60 48 83 65 ? ? 4C 8B F2 83 65 E8 00 4C 8B E1 83 65 EC").Get(); + if (Engine_Version >= 423 || Engine_Version <= 425) return Memcury::Scanner::FindPattern("48 89 5C 24 08 48 89 74 24 10 57 48 83 EC ? 49 8B F0 48 8B DA 48 85 D2").Get(); @@ -164,7 +167,14 @@ static inline uint64 FindKickPlayer() static inline uint64 FindInitHost() { if (Engine_Version == 427) // idk im dumb - return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 56 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B F1 4C 8D 05").Get(); + { + auto addr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 56 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B F1 4C 8D 05").Get(); + + if (!addr) // s18 + addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 48 8B F1 4C 8D 35 ? ? ? ? 4D").Get(); + + return addr; + } auto Addr = Memcury::Scanner::FindStringRef(L"BeaconPort="); return FindBytes(Addr, (Engine_Version == 427 ? std::vector{ 0x48, 0x8B, 0x5C } : std::vector{ 0x48, 0x8B, 0xC4 }), 1000, 0, true); @@ -178,12 +188,17 @@ static inline uint64 FindPauseBeaconRequests() if (Engine_Version == 427) return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 30 33 F6 48 8B F9 84 D2 74").Get(); + // todo try 40 53 48 83 EC 30 48 8B ? 84 D2 74 ? 80 3D for S1-S15 + if (Engine_Version == 426) return Memcury::Scanner::FindPattern("40 57 48 83 EC 30 48 8B F9 84 D2 74 62 80 3D").Get(); if (Engine_Version == 420) return Memcury::Scanner::FindPattern("40 53 48 83 EC 30 48 8B D9 84 D2 74 68 80 3D ? ? ? ? ? 72 2C 48 8B 05 ? ? ? ? 4C 8D 44").Get(); + if (Engine_Version == 419) + return Memcury::Scanner::FindPattern("40 53 48 83 EC 30 48 8B D9 84 D2 74 68 80 3D ? ? ? ? ? 72").Get(); // i supposed this is just because its getitng wrong string ref + auto Addr = Memcury::Scanner::FindStringRef(L"All Beacon Requests Resumed."); return FindBytes(Addr, { 0x40, 0x53 }, 1000, 0, true); } @@ -206,6 +221,10 @@ static inline uint64 FindSpawnActor() } auto Addr = Memcury::Scanner::FindStringRef(L"SpawnActor failed because no class was specified"); + + if (Engine_Version == 419) + return FindBytes(Addr, { 0x40, 0x55 }, 3000, 0, true); + return FindBytes(Addr, { 0x4C, 0x8B, 0xDC }, 3000, 0, true); } @@ -256,7 +275,15 @@ static inline uint64 FindOnDamageServer() static inline uint64 FindStaticLoadObject() { - auto Addr = Memcury::Scanner::FindStringRef(L"STAT_LoadObject").ScanFor({ 0x4C, 0x89, 0x4C }, false); + auto strRef = Memcury::Scanner::FindStringRef(L"STAT_LoadObject", false); + + if (!strRef.Get()) + { + auto StrRef2 = Memcury::Scanner::FindStringRef(L"Calling StaticLoadObject during PostLoad may result in hitches during streaming."); + return FindBytes(StrRef2, { 0x40, 0x55 }, 1000, 0, true); + } + + auto Addr = strRef.ScanFor({ 0x4C, 0x89, 0x4C }, false); return Addr.Get(); } @@ -324,12 +351,12 @@ static inline uint64 FindCompletePickupAnimation() static inline uint64 FindNoMCP() { - if (Fortnite_Version >= 17) // idk if needed + /* if (Fortnite_Version >= 17) // idk if needed { // todo make this relative // 19.10 return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC 20 65 48 8B 04 25 ? ? ? ? BA ? ? ? ? 48 8B 08 8B 04 0A 39 05 ? ? ? ? 7F 23 8A 05 ? ? ? ? 48 8B 5C 24 ? 48 8B 6C 24 ? 48 8B 74 24 ? 48 83 C4 20 41 5F 41 5E 41 5D 41 5C 5F C3 48 8D 0D ? ? ? ? E8 ? ? ? ? 83 3D ? ? ? ? ? 75 C8 E8 ? ? ? ? 45 33").Get(); - } + } */ if (std::floor(Fortnite_Version) == 3) return Memcury::Scanner::FindPattern("E8 ? ? ? ? 83 A7 ? ? ? ? ? 48 8D 4C 24 ?").Get(); @@ -373,10 +400,11 @@ static inline uint64 FindSetZoneToIndex() // actually StartNewSafeZonePhase // if (Fortnite_Version == 14.60) // return __int64(GetModuleHandleW(0)) + 0x207F9B0; - return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D 68 98 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 08 44 8B F2 89 54 24 48 48 8B F1 48 89 4C 24 ? E8 ? ? ? ? 45 33 E4 48 89 44 24 ? 4C 8B F8 48 85 C0 74 09").Get(); - return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D 68 88 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 10 44 8B F2 89 54 24 48 48 8B F1 48 89 4C 24 ? E8 ? ? ? ? 45 33 E4 48 89 45 80 4C 8B F8 48 85 C0 74 09 48 8B B8").Get(); - return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 44 0F 29 48 ? 44 0F 29 50 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B B1 ? ? ? ? 45 33 ED 89 54 24 70 44 8B FA 48 89 4C 24").Get(); - return Memcury::Scanner::FindPattern("40 55 53 56 41 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 18 48 8B").Get(); + return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 44 0F 29 48 ? 44 0F 29 50 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 44 8B F2 89 54 24 48 4C 8B F9 48 89 4D 90 E8 ? ? ? ? 45 33 ED 48 89 45 A0 48 8B F0").Get(); // 19.10 + // return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D 68 98 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 08 44 8B F2 89 54 24 48 48 8B F1 48 89 4C 24 ? E8 ? ? ? ? 45 33 E4 48 89 44 24 ? 4C 8B F8 48 85 C0 74 09").Get(); // 17.30 + // return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D 68 88 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 10 44 8B F2 89 54 24 48 48 8B F1 48 89 4C 24 ? E8 ? ? ? ? 45 33 E4 48 89 45 80 4C 8B F8 48 85 C0 74 09 48 8B B8").Get(); // 17.50 + return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 10 48 89 70 18 48 89 78 20 55 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 C8 0F 29 78 B8 44 0F 29 40 ? 44 0F 29 48 ? 44 0F 29 50 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B B1 ? ? ? ? 45 33 ED 89 54 24 70 44 8B FA 48 89 4C 24").Get(); // 18.40 + return Memcury::Scanner::FindPattern("40 55 53 56 41 55 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 18 48 8B").Get(); // 14.60 auto Addr = Memcury::Scanner::FindStringRef(L"FortGameModeAthena: No MegaStorm on SafeZone[%d]. GridCellThickness is less than 1.0."); return FindBytes(Addr, { 0x40, 0x55 }, 30000, 0, true); @@ -396,10 +424,17 @@ static inline uint64 FindActorGetNetMode() return Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 F6 41 08 10 48 8B D9 0F 85 ? ? ? ? 48 8B 41 20 48 85 C0 0F 84 ? ? ? ? F7 40").Get(); if (Engine_Version == 427) + { + // note this sig doesnt work on s18 return Memcury::Scanner::FindPattern("48 89 5C 24 ? 57 48 83 EC 20 48 8B D9 E8 ? ? ? ? 48 8B 93 ? ? ? ? 48 8B C8 48 8B F8 E8 ? ? ? ? 48 85 C0 75 29").Get(); + } - auto AActorGetNetmode = Memcury::Scanner::FindStringRef(L"STAT_ServerUpdateCamera"); - return Memcury::Scanner(FindBytes(AActorGetNetmode, { 0xE8 }, 255, 0, true)).RelativeOffset(1).Get(); + auto AActorGetNetmodeStrRef = Memcury::Scanner::FindStringRef(L"STAT_ServerUpdateCamera", false); + + if (!AActorGetNetmodeStrRef.Get()) + return 0; + + return Memcury::Scanner(FindBytes(AActorGetNetmodeStrRef, { 0xE8 }, 255, 0, true)).RelativeOffset(1).Get(); } static inline uint64 FindTickFlush() @@ -407,8 +442,20 @@ static inline uint64 FindTickFlush() // auto add = Memcury::Scanner::FindStringRef(L"UDemoNetDriver::TickFlush: ReplayStreamer ERROR: %s"); // return Memcury::Scanner(FindBytes(add, { 0xE8 }, 500, 0, true, 1)).RelativeOffset(1).Get(); + if (Engine_Version == 419) + { + return Memcury::Scanner::FindPattern("4C 8B DC 55 49 8D AB ? ? ? ? 48 81 EC ? ? ? ? 45 0F 29 43 ? 45 0F 29 4B ? 48 8B 05 ? ? ? ? 48").Get(); // 2.4.2 + } + if (Engine_Version == 427) - return Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 8A").Get(); + { + auto addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 8A").Get(); + + if (!addr) // s18 + addr = Memcury::Scanner::FindPattern("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 44 0F").Get(); + + return addr; + } auto Addr = Memcury::Scanner::FindStringRef(L"STAT_NetTickFlush"); return FindBytes(Addr, (Fortnite_Version < 18 ? std::vector{ 0x4C, 0x8B } : std::vector{ 0x48, 0x8B, 0xC4 }), 1000, 0, true); @@ -567,12 +614,15 @@ static inline uint64 FindChangeGameSessionId() static inline uint64 FindDispatchRequest() { - auto Addr = Memcury::Scanner::FindStringRef(L"MCP-Profile: Dispatching request to %s", true, 0, Fortnite_Version >= 18); // todo check s18 - return FindBytes(Addr, { 0x48, 0x89, 0x5C }, 300, 0, true); + auto Addr = Memcury::Scanner::FindStringRef(L"MCP-Profile: Dispatching request to %s", true, 0, Fortnite_Version >= 19); + return FindBytes(Addr, std::floor(Fortnite_Version) == 18 ? std::vector{0x48, 0x8B, 0xC4 } : std::vector{ 0x48, 0x89, 0x5C }, 300, 0, true); } static inline uint64 FindGIsClient() { + if (Fortnite_Version == 11.31) + return __int64(GetModuleHandleW(0)) + 0x6F41270; + if (Fortnite_Version == 14.60) return __int64(GetModuleHandleW(0)) + 0x939930D; @@ -661,6 +711,9 @@ static inline uint64 FindGetNetMode() .RelativeOffset(4) .Get(); // credit ender */ + if (std::floor(Fortnite_Version) == 18) + return Memcury::Scanner::FindPattern("48 83 EC 28 48 83 79 ? ? 75 20 48 8B 91 ? ? ? ? 48 85 D2 74 1E 48 8B 02 48 8B CA FF 90").Get(); + auto Addr = Memcury::Scanner::FindStringRef(L"PREPHYSBONES"); auto BeginningFunction = Memcury::Scanner(FindBytes(Addr, { 0x40, 0x55 }, 1000, 0, true)); auto CallToFunc = Memcury::Scanner(FindBytes(BeginningFunction, { 0xE8 })); @@ -692,6 +745,9 @@ static inline uint64 FindRealloc() static inline uint64 FindPickTeam() { + if (Engine_Version >= 427) // different start + return Memcury::Scanner::FindPattern("48 89 5C 24 ? 88 54 24 10 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 83 EC 70 4C 8B A1").Get(); + auto Addr = Memcury::Scanner::FindStringRef(L"PickTeam for [%s] used beacon value [%d]", false); if (!Addr.Get()) @@ -788,4 +844,44 @@ static inline uint64 FindReplaceBuildingActor() } return FindBytes(StringRef, (Engine_Version == 420 || Engine_Version == 421 ? std::vector{ 0x48, 0x8B, 0xC4 } : std::vector{ 0x4C, 0x8B }), 1000, 0, true); +} + +static inline uint64 FindSendClientAdjustment() +{ + if (Engine_Version == 419) + return Memcury::Scanner::FindPattern("40 53 48 83 EC 20 48 8B 99 ? ? ? ? 48 39 99 ? ? ? ? 74 0A 48 83 B9 ? ? ? ? ? 74").Get(); + + return 0; +} + +static inline uint64 FindReplicateActor() +{ + if (Engine_Version == 419) + return Memcury::Scanner::FindPattern("40 55 56 41 54 41 55 41 56 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 4C 8B E9 48 8B 49 68 48").Get(); + + return 0; +} + +static inline uint64 FindCreateChannel() +{ + if (Engine_Version == 419) + return Memcury::Scanner::FindPattern("40 56 57 41 54 41 55 41 57 48 83 EC 60 48 8B 01 41 8B F9 45 0F B6 E0").Get(); + + return 0; +} + +static inline uint64 FindSetChannelActor() +{ + if (Engine_Version == 419) + return Memcury::Scanner::FindPattern("48 8B C4 55 53 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 48 89 70 E8 48 8B D9").Get(); + + return 0; +} + +static inline uint64 FindCallPreReplication() +{ + if (Engine_Version == 419) + return Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 48 8B C4 55 57 41 54 48 8D 68 A1 48 81 EC ? ? ? ? 48 89 58 08 4C").Get(); + + return 0; } \ No newline at end of file diff --git a/Project Reboot 3.0/log.h b/Project Reboot 3.0/log.h index 5a88aff..53f60d6 100644 --- a/Project Reboot 3.0/log.h +++ b/Project Reboot 3.0/log.h @@ -72,6 +72,7 @@ inline void InitLogger() MakeLogger("LogInteraction"); MakeLogger("LogCreative"); MakeLogger("LogZone"); + MakeLogger("LogReplication"); } #define LOG_DEBUG(loggerName, ...) \ diff --git a/Project Reboot 3.0/reboot.h b/Project Reboot 3.0/reboot.h index b798d33..d307226 100644 --- a/Project Reboot 3.0/reboot.h +++ b/Project Reboot 3.0/reboot.h @@ -309,7 +309,7 @@ namespace MemberOffsets static UObject* GetPlaylistToUse() { auto Playlist = FindObject("/Game/Athena/Playlists/Playlist_DefaultSolo.Playlist_DefaultSolo"); - Playlist = FindObject("/BlueCheese/Playlists/Playlist_ShowdownAlt_BlueCheese_Trios.Playlist_ShowdownAlt_BlueCheese_Trios"); + // Playlist = FindObject("/BlueCheese/Playlists/Playlist_ShowdownAlt_BlueCheese_Trios.Playlist_ShowdownAlt_BlueCheese_Trios"); /* if (Globals::bCreative) diff --git a/Project Reboot 3.0/vehicles.h b/Project Reboot 3.0/vehicles.h index 05bad33..aaf0510 100644 --- a/Project Reboot 3.0/vehicles.h +++ b/Project Reboot 3.0/vehicles.h @@ -101,6 +101,40 @@ static inline void AddVehicleHook() } } +static inline AActor* SpawnVehicleFromSpawner(AActor* VehicleSpawner) +{ + FTransform SpawnTransform{}; + SpawnTransform.Translation = VehicleSpawner->GetActorLocation(); + SpawnTransform.Rotation = VehicleSpawner->GetActorRotation().Quaternion(); + SpawnTransform.Scale3D = { 1, 1, 1 }; + + static auto VehicleClassOffset = VehicleSpawner->GetOffset("VehicleClass", false); + + if (VehicleClassOffset != 0) // 10.40 and below? + { + auto VehicleClass = VehicleSpawner->Get(VehicleClassOffset); + + if (!VehicleClass) + return nullptr; + + return GetWorld()->SpawnActor(VehicleClass, SpawnTransform); + } +} + +static inline void SpawnVehicles2() +{ + static auto FortAthenaVehicleSpawnerClass = FindObject("/Script/FortniteGame.FortAthenaVehicleSpawner"); + TArray AllVehicleSpawners = UGameplayStatics::GetAllActorsOfClass(GetWorld(), FortAthenaVehicleSpawnerClass); + + for (int i = 0; i < AllVehicleSpawners.Num(); i++) + { + auto VehicleSpawner = AllVehicleSpawners.at(i); + auto Vehicle = SpawnVehicleFromSpawner(VehicleSpawner); + } + + AllVehicleSpawners.Free(); +} + static inline void SpawnVehicles() { static auto FortAthenaVehicleSpawnerClass = FindObject("/Script/FortniteGame.FortAthenaVehicleSpawner"); @@ -163,6 +197,11 @@ static inline void SpawnVehicles() if (aa) { static auto FortVehicleItemDefOffset = VehicleSpawner->GetOffset("FortVehicleItemDef"); + + if (FortVehicleItemDefOffset == 0) + { + + } auto FortVehicleItemDefSoft = VehicleSpawner->GetPtr>(FortVehicleItemDefOffset); diff --git a/vendor/memcury.h b/vendor/memcury.h index 5cf9e22..44d6b83 100644 --- a/vendor/memcury.h +++ b/vendor/memcury.h @@ -49,6 +49,8 @@ #include #include #pragma comment(lib, "Dbghelp.lib") +#include "../Project Reboot 3.0/log.h" + #define MemcuryAssert(cond) \ if (!(cond)) \ @@ -747,7 +749,10 @@ if (bWarnIfNotFound) { if (add == 0) - MessageBoxA(0, ("FindPattern " + std::string(signature) + " null").c_str(), "Memcury", MB_ICONERROR); + { + LOG_WARN(LogMemory, "Failed to find {}", signature); + // MessageBoxA(0, ("FindPattern " + std::string(signature) + " null").c_str(), "Memcury", MB_ICONERROR); + } } return Scanner(add); @@ -880,12 +885,16 @@ { if constexpr (bIsWide) { - auto aaa = (L"failed FindStringRef " + std::wstring(string)); - MessageBoxA(0, std::string(aaa.begin(), aaa.end()).c_str(), "Memcury", MB_ICONERROR); + std::wstring wstr = std::wstring(string); + LOG_WARN(LogMemory, "Failed to find String {}", std::string(wstr.begin(), wstr.end())); + + // auto aaa = (L"failed FindStringRef " + std::wstring(string)); + // MessageBoxA(0, std::string(aaa.begin(), aaa.end()).c_str(), "Memcury", MB_ICONERROR); } else { - MessageBoxA(0, ("failed FindStringRef " + std::string(string)).c_str(), "Memcury", MB_ICONERROR); + LOG_WARN(LogMemory, "Failed to find String {}", string); + // MessageBoxA(0, ("failed FindStringRef " + std::string(string)).c_str(), "Memcury", MB_ICONERROR); } } }