interacting

This commit is contained in:
Milxnor
2023-03-08 21:37:55 -05:00
parent 1fd8f0f93f
commit 59c338c401
26 changed files with 432 additions and 52 deletions

View File

@@ -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)
{

View File

@@ -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

View File

@@ -5,4 +5,9 @@
class ABuildingContainer : public ABuildingSMActor
{
public:
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.BuildingContainer");
return Class;
}
};

View File

@@ -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<TMap<FName, FName>>(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<float>("WarmupCountdownEndTime") = TimeSeconds + Duration;
GameMode->Get<float>("WarmupCountdownDuration") = Duration;
@@ -622,13 +656,13 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
PlayerStateAthena->ProcessEvent(OnRep_bHasStartedPlayingFn);
}
if (false)
if (Globals::bAbilitiesEnabled)
{
static auto GameplayAbilitySet = LoadObject<UObject>(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") ?
LoadObject<UObject>(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") :
LoadObject<UObject>(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<FUniqueNetIdReplExperimental>("UniqueId");
FUniqueNetIdReplExperimental bugha{};
auto& PlayerStateUniqueId = bugha; // PlayerStateAthena->Get<FUniqueNetIdReplExperimental>("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<TArray<__int64>>(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);
}

View File

@@ -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);
};

View File

@@ -15,19 +15,46 @@ void UFortKismetLibrary::ApplyCharacterCosmetics(UObject* WorldContextObject, co
{
static auto fn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.ApplyCharacterCosmetics");
if (fn)
{
struct
{
UObject* WorldContextObject; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
TArray<UObject*> 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 };
} UFortKismetLibrary_ApplyCharacterCosmetics_Params{ WorldContextObject, CharacterParts, PlayerState };
static auto DefaultClass = StaticClass();
DefaultClass->ProcessEvent(fn, &UFortKismetLibrary_ApplyCharacterCosmetics_Params);
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<UFunction>("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts");
PlayerState->ProcessEvent(OnRep_CharacterPartsFn);
}
else
{
// TODO Add character data support
}
}
UClass* UFortKismetLibrary::StaticClass()

View File

@@ -16,5 +16,13 @@ public:
return Get<AFortWeapon*>(CurrentWeaponOffset);
}
bool IsDBNO()
{
static auto bIsDBNOFieldMask = GetFieldMask(GetProperty("bIsDBNO"));
static auto bIsDBNOOffset = GetOffset("bIsDBNO");
return ReadBitfieldValue(bIsDBNOOffset, bIsDBNOFieldMask);
}
static UClass* StaticClass();
};

View File

@@ -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<UClass>("/Script/FortniteGame.FortControllerComponent_Interaction");
AFortPlayerControllerAthena* PlayerController = bIsUsingComponent ? Cast<AFortPlayerControllerAthena>(((UActorComponent*)Context)->GetOwner()) :
Cast<AFortPlayerControllerAthena>(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<ABuildingContainer>(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<void>(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<UFunction>("/Script/FortniteGame.BuildingContainer.OnRep_bAlreadySearched");
BuildingContainer->ProcessEvent(OnRep_bAlreadySearchedFn);
static auto SearchLootTierGroupOffset = BuildingContainer->GetOffset("SearchLootTierGroup");
auto RedirectedLootTier = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode(), false)->RedirectLootTier(BuildingContainer->Get<FName>(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<AFortPlayerPawn>(PlayerController->GetPawn());
if (!DeadPawn)
return;
static auto DeathInfoStruct = FindObject<UStruct>("/Script/FortniteGame.DeathInfo");
static auto DeathInfoStructSize = DeathInfoStruct->GetPropertiesSize();
auto DeathInfo = Alloc<void>(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<UFortWorldItemDefinition>(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())

View File

@@ -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<AFortPawn*>(MyFortPawnOffset);
}
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/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<UClass>("/Script/FortniteGame.FortPlayerController");
return Class;
}
};

View File

@@ -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<UAthenaEmojiItemDefinition>("/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())

View File

@@ -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);
};

View File

@@ -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<UClass>("/Script/FortniteGame.FortPlayerPawn");

View File

@@ -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();
};

View File

@@ -11,4 +11,10 @@ public:
static auto AbilitySystemComponentOffset = GetOffset("AbilitySystemComponent");
return this->Get<UAbilitySystemComponent*>(AbilitySystemComponentOffset);
}
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortPlayerState");
return Class;
}
};

View File

@@ -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<UClass>("/Script/FortniteGame.FortWorldItemDefinition");
return Class;
}
};

View File

@@ -23,6 +23,7 @@ struct FGameplayAbilitySpec : FFastArraySerializerItem
static auto GameplayAbilitySpecStruct = FindObject<UClass>("/Script/GameplayAbilities.GameplayAbilitySpec");
static auto StructSize = GameplayAbilitySpecStruct->GetPropertiesSize();
// *(int*)(__int64(GameplayAbilitySpecStruct) + Offsets::PropertiesSize);
LOG_INFO(LogAbility, "StructSize: {}", StructSize);
return StructSize;
}

View File

@@ -5,10 +5,8 @@
#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)
@@ -17,8 +15,41 @@ int UObject::GetOffset(const std::string& ChildName, bool bWarnIfNotFound)
NamePrivate = &((UField*)Property)->NamePrivate;
return NamePrivate;
};
};
void* UObject::GetProperty(int Offset, bool bWarnIfNotFound)
{
for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct))
{
void* Property = *(void**)(__int64(CurrentClass) + Offsets::Children);
if (Property)
{
if (*(int*)(__int64(Property) + Offsets::Offset_Internal) == Offset)
{
return Property;
}
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<PlaceholderBitfield>(Offset), FieldMask);
}
void UObject::SetBitfieldValue(int Offset, uint8_t FieldMask, bool NewValue)
{
SetBitfield(this->GetPtr<PlaceholderBitfield>(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<UClass>("/Script/CoreUObject.Object");
return Class;
}
} */

View File

@@ -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 <typename T = UObject*>
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 <typename T = UObject*>
T& GetCached(const std::string& ChildName)
{
@@ -81,5 +89,5 @@ public:
template <typename T = UObject*>
T* GetPtr(const std::string& ChildName) { return GetPtr<T>(GetOffset(ChildName)); }
static class UClass* StaticClass();
// static class UClass* StaticClass();
};

View File

@@ -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);

View File

@@ -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();

View File

@@ -154,6 +154,20 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook(GameModeDefault, FindObject<UFunction>(L"/Script/Engine.GameModeBase.HandleStartingNewPlayer"), AFortGameModeAthena::Athena_HandleStartingNewPlayerHook,
(PVOID*)&AFortGameModeAthena::Athena_HandleStartingNewPlayerOriginal, false);
static auto ControllerServerAttemptInteractFn = FindObject<UFunction>("/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<UFunction>("/Script/FortniteGame.FortControllerComponent_Interaction.ServerAttemptInteract"),
AFortPlayerController::ServerAttemptInteractHook, (PVOID*)&AFortPlayerController::ServerAttemptInteractOriginal, false, true);
}
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerExecuteInventoryItem"),
AFortPlayerController::ServerExecuteInventoryItemHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerPlayEmoteItem"),
@@ -168,13 +182,25 @@ DWORD WINAPI Main(LPVOID)
AFortPlayerController::ServerEndEditingBuildingActorHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/Engine.PlayerController.ServerAcknowledgePossession"),
AFortPlayerControllerAthena::ServerAcknowledgePossessionHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerAthena.ServerPlaySquadQuickChatMessage"),
AFortPlayerControllerAthena::ServerPlaySquadQuickChatMessage, nullptr, false);
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"),
AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false);
static auto ServerHandlePickupInfoFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerPawn.ServerHandlePickupInfo");
if (ServerHandlePickupInfoFn)
{
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, ServerHandlePickupInfoFn, AFortPlayerPawn::ServerHandlePickupInfoHook, nullptr, false);
}
else
{
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerHandlePickup"),
AFortPlayerPawn::ServerHandlePickupHook, nullptr, false);
}
if (false)
if (Globals::bAbilitiesEnabled)
{
Hooking::MinHook::Hook(FortAbilitySystemComponentAthenaDefault, FindObject<UFunction>(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));

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -218,6 +218,9 @@ namespace Hooking
if (bHookExec)
{
if (Original)
*Original = Exec;
Exec = Detour;
return true;
}

View File

@@ -70,6 +70,7 @@ inline void InitLogger()
MakeLogger("LogPlaylist");
MakeLogger("LogGame");
MakeLogger("LogAI");
MakeLogger("LogInteraction");
}
#define LOG_DEBUG(loggerName, ...) \

View File

@@ -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;
@@ -255,3 +272,11 @@ 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;
}
}