From 59c338c40109300b5c0e3ca9bcc7c43911ec8fe5 Mon Sep 17 00:00:00 2001 From: Milxnor Date: Wed, 8 Mar 2023 21:37:55 -0500 Subject: [PATCH] interacting --- Project Reboot 3.0/AbilitySystemComponent.h | 7 +- .../AbilitySystemComponent_Abilities.cpp | 2 +- Project Reboot 3.0/BuildingContainer.h | 5 + Project Reboot 3.0/FortGameModeAthena.cpp | 65 +++++++++-- Project Reboot 3.0/FortGameModeAthena.h | 12 +- Project Reboot 3.0/FortKismetLibrary.cpp | 47 ++++++-- Project Reboot 3.0/FortPawn.h | 8 ++ Project Reboot 3.0/FortPlayerController.cpp | 109 ++++++++++++++++++ Project Reboot 3.0/FortPlayerController.h | 17 ++- .../FortPlayerControllerAthena.cpp | 9 +- .../FortPlayerControllerAthena.h | 1 + Project Reboot 3.0/FortPlayerPawn.cpp | 5 + Project Reboot 3.0/FortPlayerPawn.h | 1 + Project Reboot 3.0/FortPlayerState.h | 6 + Project Reboot 3.0/FortWorldItemDefinition.h | 19 +++ Project Reboot 3.0/GameplayAbilitySpec.h | 1 + Project Reboot 3.0/Object.cpp | 77 ++++++++++--- Project Reboot 3.0/Object.h | 10 +- Project Reboot 3.0/addresses.cpp | 4 + Project Reboot 3.0/addresses.h | 1 + Project Reboot 3.0/dllmain.cpp | 33 +++++- Project Reboot 3.0/finder.h | 13 ++- Project Reboot 3.0/globals.h | 3 +- Project Reboot 3.0/hooking.h | 3 + Project Reboot 3.0/log.h | 1 + Project Reboot 3.0/reboot.h | 25 ++++ 26 files changed, 432 insertions(+), 52 deletions(-) diff --git a/Project Reboot 3.0/AbilitySystemComponent.h b/Project Reboot 3.0/AbilitySystemComponent.h index 19fdc88..3b3a6ff 100644 --- a/Project Reboot 3.0/AbilitySystemComponent.h +++ b/Project Reboot 3.0/AbilitySystemComponent.h @@ -3,18 +3,19 @@ #include "Object.h" #include "GameplayAbilitySpec.h" +struct PadHex10 { char Pad[0x10]; }; struct PadHex18 { char Pad[0x18]; }; struct PadHexA8 { char Pad[0xA8]; }; struct PadHexB0 { char Pad[0xB0]; }; -using FPredictionKey = __int64; // PadHex18; -using FGameplayEventData = __int64; // PadHexB0; +using FPredictionKey = PadHex18; +using FGameplayEventData = PadHexA8; class UAbilitySystemComponent : public UObject { public: static inline FGameplayAbilitySpecHandle* (*GiveAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle*, __int64 inSpec); - static inline bool (*InternalTryActivateAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle Handle, __int64 InPredictionKey, UObject** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData); + static inline bool (*InternalTryActivateAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle Handle, FPredictionKey InPredictionKey, UObject** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData); void ClientActivateAbilityFailed(FGameplayAbilitySpecHandle AbilityToActivate, int16_t PredictionKey) { diff --git a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp index 1e90e82..2012311 100644 --- a/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp +++ b/Project Reboot 3.0/AbilitySystemComponent_Abilities.cpp @@ -46,7 +46,7 @@ void InternalServerTryActivateAbility(UAbilitySystemComponent* AbilitySystemComp UGameplayAbility* InstancedAbility = nullptr; SetBitfield(Spec, 1, true); // InputPressed = true - if (!AbilitySystemComponent->InternalTryActivateAbilityOriginal(AbilitySystemComponent, Handle, __int64(PredictionKey), &InstancedAbility, nullptr, TriggerEventData)) + if (!AbilitySystemComponent->InternalTryActivateAbilityOriginal(AbilitySystemComponent, Handle, *(FPredictionKey*)PredictionKey, &InstancedAbility, nullptr, TriggerEventData)) { AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset)); SetBitfield(Spec, 1, false); // InputPressed = false diff --git a/Project Reboot 3.0/BuildingContainer.h b/Project Reboot 3.0/BuildingContainer.h index 135acb7..e954274 100644 --- a/Project Reboot 3.0/BuildingContainer.h +++ b/Project Reboot 3.0/BuildingContainer.h @@ -5,4 +5,9 @@ class ABuildingContainer : public ABuildingSMActor { public: + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.BuildingContainer"); + return Class; + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameModeAthena.cpp b/Project Reboot 3.0/FortGameModeAthena.cpp index 817c3a2..26bacc5 100644 --- a/Project Reboot 3.0/FortGameModeAthena.cpp +++ b/Project Reboot 3.0/FortGameModeAthena.cpp @@ -18,8 +18,7 @@ #include "events.h" #include "reboot.h" #include "ai.h" - -static bool bFirstPlayerJoined = false; +#include "Map.h" enum class EDynamicFoundationEnabledState : uint8_t { @@ -29,8 +28,6 @@ enum class EDynamicFoundationEnabledState : uint8_t EDynamicFoundationEnabledState_MAX = 3 }; - -// Enum FortniteGame.EDynamicFoundationType enum class EDynamicFoundationType : uint8_t { Static = 0, @@ -123,6 +120,42 @@ UObject* GetPlaylistToUse() return Playlist; } +FName AFortGameModeAthena::RedirectLootTier(const FName& LootTier) +{ + static auto RedirectAthenaLootTierGroupsOffset = this->GetOffset("RedirectAthenaLootTierGroups", false); + + if (RedirectAthenaLootTierGroupsOffset == 0) + { + static auto Loot_TreasureFName = UKismetStringLibrary::Conv_StringToName(L"Loot_Treasure"); + static auto Loot_AmmoFName = UKismetStringLibrary::Conv_StringToName(L"Loot_Ammo"); + + if (LootTier == Loot_TreasureFName) + return UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaTreasure"); + + if (LootTier == Loot_AmmoFName) + return UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaAmmoLarge"); + + return LootTier; + } + + auto& RedirectAthenaLootTierGroups = Get>(RedirectAthenaLootTierGroupsOffset); + + for (int i = 0; i < RedirectAthenaLootTierGroups.Pairs.Elements.Num(); i++) + { + auto& Pair = RedirectAthenaLootTierGroups.Pairs.Elements.Data.at(i).ElementData.Value; + + auto& Key = Pair.Key(); + auto& Value = Pair.Value(); + + LOG_INFO(LogDev, "[{}] {} {}", i, Key.ComparisonIndex.Value ? Key.ToString() : "NULL", Key.ComparisonIndex.Value ? Value.ToString() : "NULL"); + + if (Key == LootTier) + return Value; + } + + return LootTier; +} + bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* GameMode) { auto GameState = GameMode->GetGameStateAthena(); @@ -416,6 +449,7 @@ bool AFortGameModeAthena::Athena_ReadyToStartMatchHook(AFortGameModeAthena* Game float TimeSeconds = 35.f; // UGameplayStatics::GetTimeSeconds(GetWorld()); LOG_INFO(LogDev, "Initializing!"); + LOG_INFO(LogDev, "GameMode 0x{:x}", __int64(GameMode)); GameState->Get("WarmupCountdownEndTime") = TimeSeconds + Duration; GameMode->Get("WarmupCountdownDuration") = Duration; @@ -622,13 +656,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena PlayerStateAthena->ProcessEvent(OnRep_bHasStartedPlayingFn); } - if (false) + if (Globals::bAbilitiesEnabled) { static auto GameplayAbilitySet = LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") ? LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") : LoadObject(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer"); - // LOG_INFO(LogDev, "GameplayAbilitySet {}", __int64(GameplayAbilitySet)); + LOG_INFO(LogDev, "GameplayAbilitySet {}", __int64(GameplayAbilitySet)); if (GameplayAbilitySet) { @@ -661,11 +695,12 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena unsigned char ahh[0x0028]; }; - auto& PlayerStateUniqueId = PlayerStateAthena->Get("UniqueId"); + FUniqueNetIdReplExperimental bugha{}; + auto& PlayerStateUniqueId = bugha; // PlayerStateAthena->Get("UniqueId"); // if (false) // if (GameMemberInfoArrayOffset != 0) - if (Engine_Version >= 423) + if (Engine_Version >= 423 && false) { struct FGameMemberInfo : public FFastArraySerializerItem { @@ -750,5 +785,19 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena UFortPlaysetItemDefinition::ShowPlayset(IslandPlayset, Portal->GetLinkedVolume()); } + static auto SpawnActorDataListOffset = GameMode->GetOffset("SpawnActorDataList"); + + if (SpawnActorDataListOffset != 0) + { + auto& SpawnActorDataList = GameMode->Get>(SpawnActorDataListOffset); + LOG_INFO(LogDev, "SpawnActorDataList.Num(): {}", SpawnActorDataList.Num()); + } + return Athena_HandleStartingNewPlayerOriginal(GameMode, NewPlayerActor); +} + +void AFortGameModeAthena::SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK) +{ + LOG_INFO(LogDev, "OverridePhaseMaybeIDFK: {}", OverridePhaseMaybeIDFK); + return SetZoneToIndexOriginal(GameModeAthena, OverridePhaseMaybeIDFK); } \ No newline at end of file diff --git a/Project Reboot 3.0/FortGameModeAthena.h b/Project Reboot 3.0/FortGameModeAthena.h index 570b763..2bbbb9d 100644 --- a/Project Reboot 3.0/FortGameModeAthena.h +++ b/Project Reboot 3.0/FortGameModeAthena.h @@ -9,13 +9,17 @@ class AFortGameModeAthena : public AFortGameModePvPBase public: static inline bool (*Athena_ReadyToStartMatchOriginal)(AFortGameModeAthena* GameMode); static inline void (*Athena_HandleStartingNewPlayerOriginal)(AFortGameModeAthena* GameMode, AActor* NewPlayer); - - static bool Athena_ReadyToStartMatchHook(AFortGameModeAthena* GameMode); - static int Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller); - static void Athena_HandleStartingNewPlayerHook(AFortGameModeAthena* GameMode, AActor* NewPlayerActor); + static inline void (*SetZoneToIndexOriginal)(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK); AFortGameStateAthena* GetGameStateAthena() { return (AFortGameStateAthena*)GetGameState(); } + + FName RedirectLootTier(const FName& LootTier); + + static bool Athena_ReadyToStartMatchHook(AFortGameModeAthena* GameMode); + static int Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller); + static void Athena_HandleStartingNewPlayerHook(AFortGameModeAthena* GameMode, AActor* NewPlayerActor); + static void SetZoneToIndexHook(AFortGameModeAthena* GameModeAthena, int OverridePhaseMaybeIDFK); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortKismetLibrary.cpp b/Project Reboot 3.0/FortKismetLibrary.cpp index f73602f..e50da21 100644 --- a/Project Reboot 3.0/FortKismetLibrary.cpp +++ b/Project Reboot 3.0/FortKismetLibrary.cpp @@ -15,19 +15,46 @@ void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, co { static auto fn = FindObject("/Script/FortniteGame.FortKismetLibrary.ApplyCharacterCosmetics"); - struct + if (fn) { - UObject* WorldContextObject; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - TArray CharacterParts; // (Parm, ZeroConstructor, NativeAccessSpecifierPublic) - UObject* PlayerState; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - bool bSuccess; // (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) - } UFortKismetLibrary_ApplyCharacterCosmetics_Params{WorldContextObject, CharacterParts, PlayerState }; + struct + { + UObject* WorldContextObject; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + TArray CharacterParts; // (Parm, ZeroConstructor, NativeAccessSpecifierPublic) + UObject* PlayerState; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + bool bSuccess; // (Parm, OutParm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic) + } UFortKismetLibrary_ApplyCharacterCosmetics_Params{ WorldContextObject, CharacterParts, PlayerState }; - static auto DefaultClass = StaticClass(); - DefaultClass->ProcessEvent(fn, &UFortKismetLibrary_ApplyCharacterCosmetics_Params); + static auto DefaultClass = StaticClass(); + DefaultClass->ProcessEvent(fn, &UFortKismetLibrary_ApplyCharacterCosmetics_Params); - if (bSuccess) - *bSuccess = UFortKismetLibrary_ApplyCharacterCosmetics_Params.bSuccess; + if (bSuccess) + *bSuccess = UFortKismetLibrary_ApplyCharacterCosmetics_Params.bSuccess; + + return; + } + + static auto CharacterPartsOffset = PlayerState->GetOffset("CharacterParts", false); + + if (CharacterPartsOffset != 0) + { + auto CharacterPartsPS = PlayerState->GetPtr<__int64>("CharacterParts"); + + static auto PartsOffset = FindOffsetStruct("/Script/FortniteGame.CustomCharacterParts", "Parts"); + auto Parts = (UObject**)(__int64(CharacterPartsPS) + PartsOffset); // UCustomCharacterPart* Parts[0x6] + + for (int i = 0; i < CharacterParts.Num(); i++) + { + Parts[i] = CharacterParts.at(i); + } + + static auto OnRep_CharacterPartsFn = FindObject("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts"); + PlayerState->ProcessEvent(OnRep_CharacterPartsFn); + } + else + { + // TODO Add character data support + } } UClass* UFortKismetLibrary::StaticClass() diff --git a/Project Reboot 3.0/FortPawn.h b/Project Reboot 3.0/FortPawn.h index 495f1ce..acf17a9 100644 --- a/Project Reboot 3.0/FortPawn.h +++ b/Project Reboot 3.0/FortPawn.h @@ -16,5 +16,13 @@ public: return Get(CurrentWeaponOffset); } + bool IsDBNO() + { + static auto bIsDBNOFieldMask = GetFieldMask(GetProperty("bIsDBNO")); + static auto bIsDBNOOffset = GetOffset("bIsDBNO"); + + return ReadBitfieldValue(bIsDBNOOffset, bIsDBNOFieldMask); + } + static UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerController.cpp b/Project Reboot 3.0/FortPlayerController.cpp index a5ef45c..57557a7 100644 --- a/Project Reboot 3.0/FortPlayerController.cpp +++ b/Project Reboot 3.0/FortPlayerController.cpp @@ -10,6 +10,11 @@ #include "ActorComponent.h" #include "FortPlayerStateAthena.h" #include "globals.h" +#include "FortPlayerControllerAthena.h" +#include "BuildingContainer.h" +#include "FortLootPackage.h" +#include "FortPickup.h" +#include "FortPlayerPawn.h" void AFortPlayerController::ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot) { @@ -56,6 +61,70 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController } } +void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame* Stack, void* Ret) +{ + LOG_INFO(LogInteraction, "ServerAttemptInteract!"); + + auto Params = Stack->Locals; + + static bool bIsUsingComponent = FindObject("/Script/FortniteGame.FortControllerComponent_Interaction"); + + AFortPlayerControllerAthena* PlayerController = bIsUsingComponent ? Cast(((UActorComponent*)Context)->GetOwner()) : + Cast(Context); + + if (!PlayerController) + return; + + std::string StructName = bIsUsingComponent ? "/Script/FortniteGame.FortControllerComponent_Interaction.ServerAttemptInteract" : "/Script/FortniteGame.FortPlayerController.ServerAttemptInteract"; + + static auto ReceivingActorOffset = FindOffsetStruct(StructName, "ReceivingActor"); + auto ReceivingActor = *(AActor**)(__int64(Params) + ReceivingActorOffset); + + // LOG_INFO(LogInteraction, "ReceivingActor: {}", __int64(ReceivingActor)); + + if (!ReceivingActor) + return; + + // LOG_INFO(LogInteraction, "ReceivingActor Name: {}", ReceivingActor->GetFullName()); + + if (auto BuildingContainer = Cast(ReceivingActor)) + { + static auto bAlreadySearchedOffset = BuildingContainer->GetOffset("bAlreadySearched"); + static auto SearchBounceDataOffset = BuildingContainer->GetOffset("SearchBounceData"); + static auto SearchAnimationCountOffset = FindOffsetStruct("/Script/FortniteGame.FortSearchBounceData", "SearchAnimationCount"); + static auto bAlreadySearchedFieldMask = GetFieldMask(BuildingContainer->GetProperty(bAlreadySearchedOffset)); + + auto SearchBounceData = BuildingContainer->GetPtr(SearchBounceDataOffset); + + if (BuildingContainer->ReadBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask)) + return; + + LOG_INFO(LogInteraction, "bAlreadySearchedFieldMask: {}", bAlreadySearchedFieldMask); + + BuildingContainer->SetBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask, true); + (*(int*)(__int64(SearchBounceData) + SearchAnimationCountOffset))++; + + static auto OnRep_bAlreadySearchedFn = FindObject("/Script/FortniteGame.BuildingContainer.OnRep_bAlreadySearched"); + BuildingContainer->ProcessEvent(OnRep_bAlreadySearchedFn); + + static auto SearchLootTierGroupOffset = BuildingContainer->GetOffset("SearchLootTierGroup"); + auto RedirectedLootTier = Cast(GetWorld()->GetGameMode(), false)->RedirectLootTier(BuildingContainer->Get(SearchLootTierGroupOffset)); + + auto LootDrops = PickLootDrops(RedirectedLootTier); + + FVector LocationToSpawnLoot = BuildingContainer->GetActorLocation(); + + for (int i = 0; i < LootDrops.size(); i++) + { + AFortPickup::SpawnPickup(LootDrops.at(i).first, LocationToSpawnLoot, LootDrops.at(i).second, EFortPickupSourceTypeFlag::Container, EFortPickupSpawnSource::Unset, -1 + // , (AFortPawn*)PlayerController->GetPawn() // should we put this here? + ); + } + } + + return ServerAttemptInteractOriginal(Context, Stack, Ret); +} + void AFortPlayerController::ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation) { if (Fortnite_Version == 17.30 && Globals::bGoingToPlayEvent) @@ -187,6 +256,46 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe GiveAbilityAndActivateOnce(PlayerState->GetAbilitySystemComponent(), &outHandle, __int64(Spec)); } +void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerController, __int64 DeathReport) +{ + auto DeadPawn = Cast(PlayerController->GetPawn()); + + if (!DeadPawn) + return; + + static auto DeathInfoStruct = FindObject("/Script/FortniteGame.DeathInfo"); + static auto DeathInfoStructSize = DeathInfoStruct->GetPropertiesSize(); + + auto DeathInfo = Alloc(DeathInfoStructSize); + + *(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bDBNO) = DeadPawn->IsDBNO(); + + auto DeathLocation = DeadPawn->GetActorLocation(); + auto WorldInventory = PlayerController->GetWorldInventory(); + + auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances(); + + for (int i = 0; i < ItemInstances.Num(); i++) + { + auto ItemInstance = ItemInstances.at(i); + + if (!ItemInstance) + continue; + + auto ItemEntry = ItemInstance->GetItemEntry(); + auto WorldItemDefinition = Cast(ItemEntry->GetItemDefinition()); + + if (!WorldItemDefinition) + continue; + + if (!WorldItemDefinition->ShouldDropOnDeath()) + continue; + + AFortPickup::SpawnPickup(WorldItemDefinition, DeathLocation, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::PlayerElimination, + ItemEntry->GetLoadedAmmo()); + } +} + void AFortPlayerController::ServerBeginEditingBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToEdit) { if (!BuildingActorToEdit || !BuildingActorToEdit->IsPlayerPlaced()) diff --git a/Project Reboot 3.0/FortPlayerController.h b/Project Reboot 3.0/FortPlayerController.h index 823756f..247a7c0 100644 --- a/Project Reboot 3.0/FortPlayerController.h +++ b/Project Reboot 3.0/FortPlayerController.h @@ -6,6 +6,7 @@ #include "Rotator.h" #include "BuildingSMActor.h" +#include "Stack.h" struct FCreateBuildingActorData { uint32_t BuildingClassHandle; FVector BuildLoc; FRotator BuildRot; bool bMirrored; }; @@ -27,6 +28,8 @@ struct FFortAthenaLoadout class AFortPlayerController : public APlayerController { public: + static inline void (*ServerAttemptInteractOriginal)(UObject* Context, FFrame* Stack, void* Ret); + void ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot); AFortInventory*& GetWorldInventory() @@ -41,12 +44,6 @@ public: return Get(MyFortPawnOffset); } - static UClass* StaticClass() - { - static auto Class = FindObject("/Script/FortniteGame.FortPlayerController"); - return Class; - } - FFortAthenaLoadout* GetCosmeticLoadout() { static auto CosmeticLoadoutPCOffset = this->GetOffset("CosmeticLoadoutPC", false); @@ -60,13 +57,21 @@ public: } static void ServerExecuteInventoryItemHook(AFortPlayerController* PlayerController, FGuid ItemGuid); + static void ServerAttemptInteractHook(UObject* Context, FFrame* Stack, void* Ret); static void ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation); static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData); static void ServerPlayEmoteItemHook(AFortPlayerController* PlayerController, UObject* EmoteAsset); + static void ClientOnPawnDiedHook(AFortPlayerController* PlayerController, __int64 DeathReport); static void ServerBeginEditingBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToEdit); static void ServerEditBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToEdit, UClass* NewBuildingClass, int RotationIterations, char bMirrored); static void ServerEndEditingBuildingActorHook(AFortPlayerController* PlayerController, ABuildingSMActor* BuildingActorToStopEditing); + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.FortPlayerController"); + return Class; + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.cpp b/Project Reboot 3.0/FortPlayerControllerAthena.cpp index c22046e..74b8697 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.cpp +++ b/Project Reboot 3.0/FortPlayerControllerAthena.cpp @@ -66,7 +66,6 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl if (!UpdatePlayerCustomCharacterPartsVisualizationFn) { - static auto CosmeticLoadoutPCOffset = Controller->GetOffset("CosmeticLoadoutPC"); auto CosmeticLoadout = ControllerAsFort->GetCosmeticLoadout(); ApplyCID(PawnAsFort, CosmeticLoadout->GetCharacter()); @@ -80,6 +79,14 @@ void AFortPlayerControllerAthena::ServerAcknowledgePossessionHook(APlayerControl UFortKismetLibrary::StaticClass()->ProcessEvent(UpdatePlayerCustomCharacterPartsVisualizationFn, &PlayerStateAsFort); } +void AFortPlayerControllerAthena::ServerPlaySquadQuickChatMessage(AFortPlayerControllerAthena* PlayerController, __int64 ChatEntry, __int64 SenderID) +{ + using UAthenaEmojiItemDefinition = UFortItemDefinition; + + static auto EmojiComm = FindObject("/Game/Athena/Items/Cosmetics/Dances/Emoji/Emoji_Comm.Emoji_Comm"); + PlayerController->ServerPlayEmoteItemHook(PlayerController, EmojiComm); +} + void AFortPlayerControllerAthena::GetPlayerViewPointHook(AFortPlayerControllerAthena* PlayerController, FVector& Location, FRotator& Rotation) { if (auto MyFortPawn = PlayerController->GetMyFortPawn()) diff --git a/Project Reboot 3.0/FortPlayerControllerAthena.h b/Project Reboot 3.0/FortPlayerControllerAthena.h index 5f7bdd5..e3f28dd 100644 --- a/Project Reboot 3.0/FortPlayerControllerAthena.h +++ b/Project Reboot 3.0/FortPlayerControllerAthena.h @@ -14,5 +14,6 @@ public: } static void ServerAcknowledgePossessionHook(APlayerController* Controller, APawn* Pawn); + static void ServerPlaySquadQuickChatMessage(AFortPlayerControllerAthena* PlayerController, __int64 ChatEntry, __int64 SenderID); static void GetPlayerViewPointHook(AFortPlayerControllerAthena* PlayerController, FVector& Location, FRotator& Rotation); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerPawn.cpp b/Project Reboot 3.0/FortPlayerPawn.cpp index 095ee5a..43c8f54 100644 --- a/Project Reboot 3.0/FortPlayerPawn.cpp +++ b/Project Reboot 3.0/FortPlayerPawn.cpp @@ -99,6 +99,11 @@ void AFortPlayerPawn::ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup->ProcessEvent(OnRep_bPickedUpFn); } +void AFortPlayerPawn::ServerHandlePickupInfoHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup, __int64 Params) +{ + return ServerHandlePickupHook(Pawn, Pickup, 0.40f, FVector(), false); +} + UClass* AFortPlayerPawn::StaticClass() { static auto Class = FindObject("/Script/FortniteGame.FortPlayerPawn"); diff --git a/Project Reboot 3.0/FortPlayerPawn.h b/Project Reboot 3.0/FortPlayerPawn.h index cf9adf9..0e34f8e 100644 --- a/Project Reboot 3.0/FortPlayerPawn.h +++ b/Project Reboot 3.0/FortPlayerPawn.h @@ -26,6 +26,7 @@ public: static void ServerSendZiplineStateHook(AFortPlayerPawn* Pawn, FZiplinePawnState InZiplineState); static void ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup, float InFlyTime, FVector InStartDirection, bool bPlayPickupSound); + static void ServerHandlePickupInfoHook(AFortPlayerPawn* Pawn, AFortPickup* Pickup, __int64 Params); static UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortPlayerState.h b/Project Reboot 3.0/FortPlayerState.h index bf49844..96766e3 100644 --- a/Project Reboot 3.0/FortPlayerState.h +++ b/Project Reboot 3.0/FortPlayerState.h @@ -11,4 +11,10 @@ public: static auto AbilitySystemComponentOffset = GetOffset("AbilitySystemComponent"); return this->Get(AbilitySystemComponentOffset); } + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.FortPlayerState"); + return Class; + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/FortWorldItemDefinition.h b/Project Reboot 3.0/FortWorldItemDefinition.h index ce4dff2..b672677 100644 --- a/Project Reboot 3.0/FortWorldItemDefinition.h +++ b/Project Reboot 3.0/FortWorldItemDefinition.h @@ -4,5 +4,24 @@ class UFortWorldItemDefinition : public UFortItemDefinition { +public: + bool CanBeDropped() + { + static auto bCanBeDroppedOffset = GetOffset("bCanBeDropped"); + static auto bCanBeDroppedFieldMask = GetFieldMask(GetProperty("bCanBeDropped")); + return ReadBitfieldValue(bCanBeDroppedOffset, bCanBeDroppedFieldMask); + } + bool ShouldDropOnDeath() + { + static auto bDropOnDeathOffset = GetOffset("bDropOnDeath"); + static auto bDropOnDeathFieldMask = GetFieldMask(GetProperty("bDropOnDeath")); + return ReadBitfieldValue(bDropOnDeathOffset, bDropOnDeathFieldMask); + } + + static UClass* StaticClass() + { + static auto Class = FindObject("/Script/FortniteGame.FortWorldItemDefinition"); + return Class; + } }; \ No newline at end of file diff --git a/Project Reboot 3.0/GameplayAbilitySpec.h b/Project Reboot 3.0/GameplayAbilitySpec.h index 7df04d5..68c7ee3 100644 --- a/Project Reboot 3.0/GameplayAbilitySpec.h +++ b/Project Reboot 3.0/GameplayAbilitySpec.h @@ -23,6 +23,7 @@ struct FGameplayAbilitySpec : FFastArraySerializerItem static auto GameplayAbilitySpecStruct = FindObject("/Script/GameplayAbilities.GameplayAbilitySpec"); static auto StructSize = GameplayAbilitySpecStruct->GetPropertiesSize(); // *(int*)(__int64(GameplayAbilitySpecStruct) + Offsets::PropertiesSize); + LOG_INFO(LogAbility, "StructSize: {}", StructSize); return StructSize; } diff --git a/Project Reboot 3.0/Object.cpp b/Project Reboot 3.0/Object.cpp index 43a982b..6063196 100644 --- a/Project Reboot 3.0/Object.cpp +++ b/Project Reboot 3.0/Object.cpp @@ -5,20 +5,51 @@ #include "Class.h" #include "KismetSystemLibrary.h" -int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) +FName* getFNameOfProp(void* Property) { - auto getFNameOfProp = [](void* Property) -> FName* + FName* NamePrivate = nullptr; + + if (Engine_Version >= 425) + NamePrivate = (FName*)(__int64(Property) + 0x28); + else + NamePrivate = &((UField*)Property)->NamePrivate; + + return NamePrivate; +}; + +void* UObject::GetProperty(int Offset, bool bWarnIfNotFound) +{ + for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct)) { - FName* NamePrivate = nullptr; + void* Property = *(void**)(__int64(CurrentClass) + Offsets::Children); - if (Engine_Version >= 425) - NamePrivate = (FName*)(__int64(Property) + 0x28); - else - NamePrivate = &((UField*)Property)->NamePrivate; + if (Property) + { + if (*(int*)(__int64(Property) + Offsets::Offset_Internal) == Offset) + { + return Property; + } - return NamePrivate; - }; + while (Property) + { + if (*(int*)(__int64(Property) + Offsets::Offset_Internal) == Offset) + { + return Property; + } + Property = Engine_Version >= 425 ? *(void**)(__int64(Property) + 0x20) : ((UField*)Property)->Next; + } + } + } + + if (bWarnIfNotFound) + LOG_WARN(LogFinder, "Unable to find2{}", Offset); + + return 0; +} + +void* UObject::GetProperty(const std::string& ChildName, bool bWarnIfNotFound) +{ for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct)) { void* Property = *(void**)(__int64(CurrentClass) + Offsets::Children); @@ -31,14 +62,14 @@ int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) if (PropName == ChildName) { - return *(int*)(__int64(Property) + Offsets::Offset_Internal); + return Property; } while (Property) { if (PropName == ChildName) { - return *(int*)(__int64(Property) + Offsets::Offset_Internal); + return Property; } Property = Engine_Version >= 425 ? *(void**)(__int64(Property) + 0x20) : ((UField*)Property)->Next; @@ -53,6 +84,26 @@ int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) return 0; } +int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound) +{ + auto Property = GetProperty(ChildName, bWarnIfNotFound); + + if (!Property) + return 0; + + return *(int*)(__int64(Property) + Offsets::Offset_Internal); +} + +bool UObject::ReadBitfieldValue(int Offset, uint8_t FieldMask) +{ + return ReadBitfield(this->GetPtr(Offset), FieldMask); +} + +void UObject::SetBitfieldValue(int Offset, uint8_t FieldMask, bool NewValue) +{ + SetBitfield(this->GetPtr(Offset), FieldMask, NewValue); +} + std::string UObject::GetFullName() { return ClassPrivate ? ClassPrivate->GetName() + " " + UKismetSystemLibrary::GetPathName(this).ToString() : "NoClassPrivate"; @@ -73,8 +124,8 @@ bool UObject::IsA(UClass* otherClass) return false; } -class UClass* UObject::StaticClass() +/* class UClass* UObject::StaticClass() { static auto Class = FindObject("/Script/CoreUObject.Object"); return Class; -} \ No newline at end of file +} */ \ No newline at end of file diff --git a/Project Reboot 3.0/Object.h b/Project Reboot 3.0/Object.h index a265b32..30562ab 100644 --- a/Project Reboot 3.0/Object.h +++ b/Project Reboot 3.0/Object.h @@ -44,11 +44,19 @@ public: bool IsA(UClass* Other); + void* GetProperty(int Offset, bool bWarnIfNotFound = true); + void* GetProperty(const std::string& ChildName, bool bWarnIfNotFound = true); int GetOffset(const std::string& ChildName, bool bWarnIfNotFound = true); template T& Get(int Offset) { return *(T*)(__int64(this) + Offset); } + bool ReadBitfieldValue(int Offset, uint8_t FieldMask); + bool ReadBitfieldValue(const std::string& ChildName, uint8_t FieldMask) { return ReadBitfieldValue(GetOffset(ChildName), FieldMask); } + + void SetBitfieldValue(int Offset, uint8_t FieldMask, bool NewValue); + void SetBitfieldValue(const std::string& ChildName, uint8_t FieldMask, bool NewValue) { return SetBitfieldValue(GetOffset(ChildName), FieldMask, NewValue); } + template T& GetCached(const std::string& ChildName) { @@ -81,5 +89,5 @@ public: template T* GetPtr(const std::string& ChildName) { return GetPtr(GetOffset(ChildName)); } - static class UClass* StaticClass(); + // static class UClass* StaticClass(); }; \ No newline at end of file diff --git a/Project Reboot 3.0/addresses.cpp b/Project Reboot 3.0/addresses.cpp index 6d4ceb4..20ab664 100644 --- a/Project Reboot 3.0/addresses.cpp +++ b/Project Reboot 3.0/addresses.cpp @@ -16,6 +16,7 @@ #include "ai.h" #include "BuildingActor.h" #include "FortPlaysetItemDefinition.h" +#include "FortGameModeAthena.h" void Addresses::SetupVersion() { @@ -192,6 +193,7 @@ void Addresses::FindAll() Addresses::AddNavigationSystemToWorld = FindAddNavigationSystemToWorld(); Addresses::NavSystemCleanUp = FindNavSystemCleanUp(); Addresses::LoadPlayset = FindLoadPlayset(); + Addresses::SetZoneToIndex = FindSetZoneToIndex(); } void Addresses::Print() @@ -228,6 +230,7 @@ void Addresses::Print() LOG_INFO(LogDev, "AddNavigationSystemToWorld: 0x{:x}", AddNavigationSystemToWorld - Base); LOG_INFO(LogDev, "NavSystemCleanUp: 0x{:x}", NavSystemCleanUp - Base); LOG_INFO(LogDev, "LoadPlayset: 0x{:x}", LoadPlayset - Base); + LOG_INFO(LogDev, "SetZoneToIndex: 0x{:x}", SetZoneToIndex - Base); } void Offsets::FindAll() @@ -299,6 +302,7 @@ void Addresses::Init() AddNavigationSystemToWorldOriginal = decltype(AddNavigationSystemToWorldOriginal)(AddNavigationSystemToWorld); NavSystemCleanUpOriginal = decltype(NavSystemCleanUpOriginal)(Addresses::NavSystemCleanUp); LoadPlaysetOriginal = decltype(LoadPlaysetOriginal)(Addresses::LoadPlayset); + AFortGameModeAthena::SetZoneToIndexOriginal = decltype(AFortGameModeAthena::SetZoneToIndexOriginal)(Addresses::SetZoneToIndex); // if (Engine_Version >= 421) ChunkedObjects = decltype(ChunkedObjects)(ObjectArray); // else UnchunkedObjects = decltype(UnchunkedObjects)(ObjectArray); diff --git a/Project Reboot 3.0/addresses.h b/Project Reboot 3.0/addresses.h index dc3fc56..8fb4119 100644 --- a/Project Reboot 3.0/addresses.h +++ b/Project Reboot 3.0/addresses.h @@ -40,6 +40,7 @@ namespace Addresses extern inline uint64 AddNavigationSystemToWorld = 0; extern inline uint64 NavSystemCleanUp = 0; extern inline uint64 LoadPlayset = 0; + extern inline uint64 SetZoneToIndex = 0; void SetupVersion(); // Finds Engine Version void FindAll(); diff --git a/Project Reboot 3.0/dllmain.cpp b/Project Reboot 3.0/dllmain.cpp index c186df7..65ba7b5 100644 --- a/Project Reboot 3.0/dllmain.cpp +++ b/Project Reboot 3.0/dllmain.cpp @@ -154,6 +154,20 @@ DWORD WINAPI Main(LPVOID) Hooking::MinHook::Hook(GameModeDefault, FindObject(L"/Script/Engine.GameModeBase.HandleStartingNewPlayer"), AFortGameModeAthena::Athena_HandleStartingNewPlayerHook, (PVOID*)&AFortGameModeAthena::Athena_HandleStartingNewPlayerOriginal, false); + static auto ControllerServerAttemptInteractFn = FindObject("/Script/FortniteGame.FortPlayerController.ServerAttemptInteract"); + + if (ControllerServerAttemptInteractFn) + { + Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, ControllerServerAttemptInteractFn, AFortPlayerController::ServerAttemptInteractHook, + (PVOID*)&AFortPlayerController::ServerAttemptInteractOriginal, false, true); + } + else + { + Hooking::MinHook::Hook(FindObject("/Script/FortniteGame.Default__FortControllerComponent_Interaction"), + FindObject("/Script/FortniteGame.FortControllerComponent_Interaction.ServerAttemptInteract"), + AFortPlayerController::ServerAttemptInteractHook, (PVOID*)&AFortPlayerController::ServerAttemptInteractOriginal, false, true); + } + Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerExecuteInventoryItem"), AFortPlayerController::ServerExecuteInventoryItemHook, nullptr, false); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerController.ServerPlayEmoteItem"), @@ -168,13 +182,25 @@ DWORD WINAPI Main(LPVOID) AFortPlayerController::ServerEndEditingBuildingActorHook, nullptr, false); Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/Engine.PlayerController.ServerAcknowledgePossession"), AFortPlayerControllerAthena::ServerAcknowledgePossessionHook, nullptr, false); + Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerControllerAthena.ServerPlaySquadQuickChatMessage"), + AFortPlayerControllerAthena::ServerPlaySquadQuickChatMessage, nullptr, false); Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"), AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false); - Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerHandlePickup"), - AFortPlayerPawn::ServerHandlePickupHook, nullptr, false); - if (false) + static auto ServerHandlePickupInfoFn = FindObject("/Script/FortniteGame.FortPlayerPawn.ServerHandlePickupInfo"); + + if (ServerHandlePickupInfoFn) + { + Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, ServerHandlePickupInfoFn, AFortPlayerPawn::ServerHandlePickupInfoHook, nullptr, false); + } + else + { + Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject(L"/Script/FortniteGame.FortPlayerPawn.ServerHandlePickup"), + AFortPlayerPawn::ServerHandlePickupHook, nullptr, false); + } + + if (Globals::bAbilitiesEnabled) { Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerTryActivateAbility"), UAbilitySystemComponent::ServerTryActivateAbilityHook, nullptr, false); @@ -197,6 +223,7 @@ DWORD WINAPI Main(LPVOID) // Hooking::MinHook::Hook((PVOID)Addresses::OnDamageServer, (PVOID)ABuildingActor::OnDamageServerHook, (PVOID*)&ABuildingActor::OnDamageServerOriginal); // Hooking::MinHook::Hook((PVOID)Addresses::CollectGarbage, (PVOID)CollectGarbageHook, nullptr); Hooking::MinHook::Hook((PVOID)Addresses::PickTeam, (PVOID)AFortGameModeAthena::Athena_PickTeamHook, nullptr); + Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)AFortGameModeAthena::SetZoneToIndexHook, (PVOID*)&AFortGameModeAthena::SetZoneToIndexOriginal); srand(time(0)); diff --git a/Project Reboot 3.0/finder.h b/Project Reboot 3.0/finder.h index 82d583c..dc65fea 100644 --- a/Project Reboot 3.0/finder.h +++ b/Project Reboot 3.0/finder.h @@ -265,9 +265,20 @@ static inline uint64 FindNoMCP() // return (uintptr_t)GetModuleHandleW(0) + 0x161d600; // 10.40 } +static inline uint64 FindSetZoneToIndex() +{ + if (Fortnite_Version == 14.60) + return __int64(GetModuleHandleW(0)) + 0x207F9B0; + + return 0; + + 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); +} + static inline uint64 FindCollectGarbage() { - return 0; + // return 0; auto Addr = Memcury::Scanner::FindStringRef(L"STAT_CollectGarbageInternal"); return FindBytes(Addr, { 0x48, 0x89, 0x5C }, 2000, 0, true, 1); diff --git a/Project Reboot 3.0/globals.h b/Project Reboot 3.0/globals.h index 8aeeddb..fc00458 100644 --- a/Project Reboot 3.0/globals.h +++ b/Project Reboot 3.0/globals.h @@ -2,8 +2,9 @@ namespace Globals { - extern inline bool bCreative = true; + extern inline bool bCreative = false; extern inline bool bGoingToPlayEvent = false; extern inline bool bNoMCP = false; extern inline bool bLateGame = false; + extern inline bool bAbilitiesEnabled = true; } \ No newline at end of file diff --git a/Project Reboot 3.0/hooking.h b/Project Reboot 3.0/hooking.h index b5722c1..d12e23b 100644 --- a/Project Reboot 3.0/hooking.h +++ b/Project Reboot 3.0/hooking.h @@ -218,6 +218,9 @@ namespace Hooking if (bHookExec) { + if (Original) + *Original = Exec; + Exec = Detour; return true; } diff --git a/Project Reboot 3.0/log.h b/Project Reboot 3.0/log.h index cdbb77a..3c4de9d 100644 --- a/Project Reboot 3.0/log.h +++ b/Project Reboot 3.0/log.h @@ -70,6 +70,7 @@ inline void InitLogger() MakeLogger("LogPlaylist"); MakeLogger("LogGame"); MakeLogger("LogAI"); + MakeLogger("LogInteraction"); } #define LOG_DEBUG(loggerName, ...) \ diff --git a/Project Reboot 3.0/reboot.h b/Project Reboot 3.0/reboot.h index b899aab..e7f45a5 100644 --- a/Project Reboot 3.0/reboot.h +++ b/Project Reboot 3.0/reboot.h @@ -134,6 +134,23 @@ struct PlaceholderBitfield uint8_t Eighth : 1; }; +inline uint8_t GetFieldMask(void* Property) +{ + if (!Property) + return -1; + + // 3 = sizeof(FieldSize) + sizeof(ByteOffset) + sizeof(ByteMask) + + if (Engine_Version <= 420) + return *(uint8_t*)(__int64(Property) + (112 + 3)); + else if (Engine_Version >= 421 && Engine_Version <= 424) + return *(uint8_t*)(__int64(Property) + (112 + 3)); + else if (Engine_Version >= 425) + return *(uint8_t*)(__int64(Property) + (120 + 3)); + + return -1; +} + inline bool ReadBitfield(void* Addr, uint8_t FieldMask) { auto Bitfield = (PlaceholderBitfield*)Addr; @@ -254,4 +271,12 @@ template static T* Alloc(size_t Size) { return (T*)VirtualAlloc(0, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); +} + +namespace MemberOffsets +{ + namespace DeathInfo + { + static inline int bDBNO, Downer, FinisherOrDowner, DeathCause, Distance, DeathLocation, bInitialized, DeathTags; + } } \ No newline at end of file