interact + pickuo

This commit is contained in:
Milxnor
2023-03-11 09:24:00 -05:00
parent 59c338c401
commit 07950d84a2
33 changed files with 663 additions and 150 deletions

View File

@@ -8,14 +8,18 @@ struct PadHex18 { char Pad[0x18]; };
struct PadHexA8 { char Pad[0xA8]; }; struct PadHexA8 { char Pad[0xA8]; };
struct PadHexB0 { char Pad[0xB0]; }; struct PadHexB0 { char Pad[0xB0]; };
using FPredictionKey = PadHex18; // using FPredictionKey = PadHex18;
using FGameplayEventData = PadHexA8; // using FGameplayEventData = PadHexA8;
using FPredictionKey = __int64;
using FGameplayEventData = __int64;
class UAbilitySystemComponent : public UObject class UAbilitySystemComponent : public UObject
{ {
public: public:
static inline FGameplayAbilitySpecHandle* (*GiveAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle*, __int64 inSpec); static inline FGameplayAbilitySpecHandle* (*GiveAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle*, __int64 inSpec);
static inline bool (*InternalTryActivateAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle Handle, FPredictionKey InPredictionKey, UObject** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData); static inline bool (*InternalTryActivateAbilityOriginal)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle Handle, PadHex10 InPredictionKey, UObject** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData);
static inline bool (*InternalTryActivateAbilityOriginal2)(UAbilitySystemComponent*, FGameplayAbilitySpecHandle Handle, PadHex18 InPredictionKey, UObject** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, const FGameplayEventData* TriggerEventData);
void ClientActivateAbilityFailed(FGameplayAbilitySpecHandle AbilityToActivate, int16_t PredictionKey) void ClientActivateAbilityFailed(FGameplayAbilitySpecHandle AbilityToActivate, int16_t PredictionKey)
{ {

View File

@@ -28,36 +28,60 @@ void InternalServerTryActivateAbility(UAbilitySystemComponent* AbilitySystemComp
auto Spec = AbilitySystemComponent->FindAbilitySpecFromHandle(Handle); auto Spec = AbilitySystemComponent->FindAbilitySpecFromHandle(Handle);
static auto PredictionKeyStruct = FindObject<UStruct>("/Script/GameplayAbilities.PredictionKey");
static auto PredictionKeySize = PredictionKeyStruct->GetPropertiesSize();
static auto CurrentOffset = FindOffsetStruct("/Script/GameplayAbilities.PredictionKey", "Current"); static auto CurrentOffset = FindOffsetStruct("/Script/GameplayAbilities.PredictionKey", "Current");
if (!Spec) if (!Spec)
{ {
LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Rejecting ClientActivation of ability with invalid SpecHandle!");
AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset)); AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset));
return; return;
} }
// ConsumeAllReplicatedData(Handle, PredictionKey); // ConsumeAllReplicatedData(Handle, PredictionKey);
const UGameplayAbility* AbilityToActivate = Spec->GetAbility(); /* const */ UGameplayAbility * AbilityToActivate = Spec->GetAbility();
if (!AbilityToActivate) if (!AbilityToActivate)
{
LOG_ERROR(LogAbilities, "InternalServerTryActiveAbility. Rejecting ClientActivation of unconfigured spec ability!");
AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset));
return; return;
}
UGameplayAbility* InstancedAbility = nullptr; UGameplayAbility* InstancedAbility = nullptr;
SetBitfield(Spec, 1, true); // InputPressed = true SetBitfield(Spec, 1, true); // InputPressed = true
bool res = false;
if (!AbilitySystemComponent->InternalTryActivateAbilityOriginal(AbilitySystemComponent, Handle, *(FPredictionKey*)PredictionKey, &InstancedAbility, nullptr, TriggerEventData)) if (PredictionKeySize == 0x10)
res = UAbilitySystemComponent::InternalTryActivateAbilityOriginal(AbilitySystemComponent, Handle, *(PadHex10*)PredictionKey, &InstancedAbility, nullptr, TriggerEventData);
else if (PredictionKeySize == 0x18)
res = UAbilitySystemComponent::InternalTryActivateAbilityOriginal2(AbilitySystemComponent, Handle, *(PadHex18*)PredictionKey, &InstancedAbility, nullptr, TriggerEventData);
else
LOG_ERROR(LogAbilities, "Prediction key size does not match with any of them!");
if (res)
{ {
LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Rejecting ClientActivation of {}. InternalTryActivateAbility failed: ", AbilityToActivate->GetName());
AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset)); AbilitySystemComponent->ClientActivateAbilityFailed(Handle, *(int16_t*)(__int64(PredictionKey) + CurrentOffset));
SetBitfield(Spec, 1, false); // InputPressed = false SetBitfield(Spec, 1, false); // InputPressed = false
static auto ActivatableAbilitiesOffset = AbilitySystemComponent->GetOffset("ActivatableAbilities"); static auto ActivatableAbilitiesOffset = AbilitySystemComponent->GetOffset("ActivatableAbilities");
AbilitySystemComponent->Get<FFastArraySerializer>(ActivatableAbilitiesOffset).MarkItemDirty(Spec); AbilitySystemComponent->Get<FFastArraySerializer>(ActivatableAbilitiesOffset).MarkItemDirty(Spec);
} }
else
{
LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Activated {}", AbilityToActivate->GetName());
}
} }
FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass) FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass)
{ {
// LOG_INFO(LogDev, "Making spec!");
auto NewSpec = MakeNewSpec(AbilityClass); auto NewSpec = MakeNewSpec(AbilityClass);
// LOG_INFO(LogDev, "Made spec!"); // LOG_INFO(LogDev, "Made spec!");
@@ -91,12 +115,14 @@ FGameplayAbilitySpec* UAbilitySystemComponent::FindAbilitySpecFromHandle(FGamepl
void UAbilitySystemComponent::ServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent, void UAbilitySystemComponent::ServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent,
FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey) FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey)
{ {
LOG_INFO(LogAbilities, "ServerTryActivateAbility");
InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ &PredictionKey, nullptr); InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ &PredictionKey, nullptr);
} }
void UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook(UAbilitySystemComponent* AbilitySystemComponent, void UAbilitySystemComponent::ServerTryActivateAbilityWithEventDataHook(UAbilitySystemComponent* AbilitySystemComponent,
FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey, FGameplayEventData TriggerEventData) FGameplayAbilitySpecHandle Handle, bool InputPressed, FPredictionKey PredictionKey, FGameplayEventData TriggerEventData)
{ {
LOG_INFO(LogAbilities, "ServerTryActivateAbilityWithEventData");
InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */ InternalServerTryActivateAbility(AbilitySystemComponent, Handle, /* InputPressed, */
&PredictionKey, &TriggerEventData); &PredictionKey, &TriggerEventData);
} }

View File

@@ -49,5 +49,14 @@ FVector AActor::GetActorLocation()
FVector ret; FVector ret;
this->ProcessEvent(K2_GetActorLocationFn, &ret); this->ProcessEvent(K2_GetActorLocationFn, &ret);
return ret;
}
FVector AActor::GetActorRightVector()
{
static auto GetActorRightVectorFn = FindObject<UFunction>("/Script/Engine.Actor.GetActorRightVector");
FVector ret;
this->ProcessEvent(GetActorRightVectorFn, &ret);
return ret; return ret;
} }

View File

@@ -9,6 +9,7 @@ public:
AActor* GetOwner(); AActor* GetOwner();
struct FVector GetActorLocation(); struct FVector GetActorLocation();
struct FVector GetActorRightVector();
void K2_DestroyActor(); void K2_DestroyActor();
class UActorComponent* GetComponentByClass(class UClass* ComponentClass); class UActorComponent* GetComponentByClass(class UClass* ComponentClass);
}; };

View File

@@ -23,9 +23,9 @@ public:
public: public:
inline InElementType& At(int i, int Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); } inline InElementType& At(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
inline InElementType& at(int i, int Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); } inline InElementType& at(int i, size_t Size = sizeof(InElementType)) const { return *(InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
inline InElementType* AtPtr(int i, int Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); } inline InElementType* AtPtr(int i, size_t Size = sizeof(InElementType)) const { return (InElementType*)(__int64(Data) + (static_cast<long long>(Size) * i)); }
inline int Num() const { return ArrayNum; } inline int Num() const { return ArrayNum; }
inline int size() const { return ArrayNum; } inline int size() const { return ArrayNum; }
@@ -35,14 +35,14 @@ public:
return ArrayMax - NumElements; return ArrayMax - NumElements;
} }
void Reserve(int Number, int Size = sizeof(InElementType)) void Reserve(int Number, size_t Size = sizeof(InElementType))
{ {
// LOG_INFO(LogDev, "ArrayNum {}", ArrayNum); // LOG_INFO(LogDev, "ArrayNum {}", ArrayNum);
// Data = (InElementType*)FMemory::Realloc(Data, (ArrayMax = ArrayNum + Number) * Size, 0); // Data = (InElementType*)FMemory::Realloc(Data, (ArrayMax = ArrayNum + Number) * Size, 0);
Data = /* (ArrayMax - ArrayNum) >= ArrayNum ? Data : */ (InElementType*)FMemory::Realloc(Data, (ArrayMax = Number + ArrayNum) * Size, 0); Data = /* (ArrayMax - ArrayNum) >= ArrayNum ? Data : */ (InElementType*)FMemory::Realloc(Data, (ArrayMax = Number + ArrayNum) * Size, 0);
} }
FORCENOINLINE void ResizeGrow(int32 OldNum, int Size = sizeof(InElementType)) FORCENOINLINE void ResizeGrow(int32 OldNum, size_t Size = sizeof(InElementType))
{ {
// LOG_INFO(LogMemory, "FMemory::Realloc: {}", __int64(FMemory::Realloc)); // LOG_INFO(LogMemory, "FMemory::Realloc: {}", __int64(FMemory::Realloc));
@@ -52,7 +52,7 @@ public:
Data = (InElementType*)FMemory::Realloc(Data, ArrayMax * Size, 0); Data = (InElementType*)FMemory::Realloc(Data, ArrayMax * Size, 0);
} }
FORCEINLINE int32 AddUninitialized(int32 Count = 1, int Size = sizeof(InElementType)) FORCEINLINE int32 AddUninitialized(int32 Count = 1, size_t Size = sizeof(InElementType))
{ {
// CheckInvariants(); // CheckInvariants();
@@ -69,7 +69,7 @@ public:
return OldNum; return OldNum;
} }
FORCEINLINE int32 Emplace(const InElementType& New, int Size = sizeof(InElementType)) FORCEINLINE int32 Emplace(const InElementType& New, size_t Size = sizeof(InElementType))
{ {
const int32 Index = AddUninitialized(1, Size); // resizes array const int32 Index = AddUninitialized(1, Size); // resizes array
memcpy_s((InElementType*)(__int64(Data) + (Index * Size)), Size, (void*)&New, Size); memcpy_s((InElementType*)(__int64(Data) + (Index * Size)), Size, (void*)&New, Size);
@@ -82,7 +82,7 @@ public:
return Emplace(New, Size); return Emplace(New, Size);
} */ } */
int Add(const InElementType& New, int Size = sizeof(InElementType)) int Add(const InElementType& New, size_t Size = sizeof(InElementType))
{ {
// LOG_INFO(LogDev, "ArrayMax: {}", ArrayMax); // LOG_INFO(LogDev, "ArrayMax: {}", ArrayMax);
@@ -113,14 +113,17 @@ public:
ArrayMax = 0; ArrayMax = 0;
} }
bool Remove(const int Index) bool Remove(const int Index, size_t Size = sizeof(InElementType))
{ {
// return false; // return false;
if (Index < ArrayNum) if (Index < ArrayNum)
{ {
if (Index != ArrayNum - 1) if (Index != ArrayNum - 1)
Data[Index] = Data[ArrayNum - 1]; {
memcpy_s(&at(Index, Size), Size, &at(ArrayNum - 1, Size), Size);
// Data[Index] = Data[ArrayNum - 1];
}
--ArrayNum; --ArrayNum;

View File

@@ -0,0 +1,9 @@
#pragma once
#include "ActorComponent.h"
class UAthenaMarkerComponent : public UActorComponent
{
public:
};

View File

@@ -5,6 +5,13 @@
class ABuildingContainer : public ABuildingSMActor class ABuildingContainer : public ABuildingSMActor
{ {
public: public:
bool ShouldDestroyOnSearch()
{
static auto bDestroyContainerOnSearchOffset = GetOffset("bDestroyContainerOnSearch");
static auto bDestroyContainerOnSearchFieldMask = GetFieldMask(GetProperty("bDestroyContainerOnSearch"));
return this->ReadBitfieldValue(bDestroyContainerOnSearchOffset, bDestroyContainerOnSearchFieldMask);
}
static UClass* StaticClass() static UClass* StaticClass()
{ {
static auto Class = FindObject<UClass>("/Script/FortniteGame.BuildingContainer"); static auto Class = FindObject<UClass>("/Script/FortniteGame.BuildingContainer");

View File

@@ -76,7 +76,7 @@ static void StreamLevel(std::string LevelName, FVector Location = {})
FTransform Transform{}; FTransform Transform{};
Transform.Scale3D = { 1, 1, 1 }; Transform.Scale3D = { 1, 1, 1 };
Transform.Translation = Location; Transform.Translation = Location;
auto BuildingFoundation = GetWorld()->SpawnActor<ABuildingSMActor>(BuildingFoundation3x3Class, Transform); auto BuildingFoundation = (GetWorld()->SpawnActor<ABuildingSMActor>(BuildingFoundation3x3Class, Transform));
if (!BuildingFoundation) if (!BuildingFoundation)
{ {
@@ -84,7 +84,7 @@ static void StreamLevel(std::string LevelName, FVector Location = {})
return; return;
} }
BuildingFoundation->InitializeBuildingActor(BuildingFoundation, nullptr, false); // BuildingFoundation->InitializeBuildingActor(BuildingFoundation, nullptr, false);
static auto FoundationNameOffset = FindOffsetStruct("/Script/FortniteGame.BuildingFoundationStreamingData", "FoundationName"); static auto FoundationNameOffset = FindOffsetStruct("/Script/FortniteGame.BuildingFoundationStreamingData", "FoundationName");
static auto FoundationLocationOffset = FindOffsetStruct("/Script/FortniteGame.BuildingFoundationStreamingData", "FoundationLocation"); static auto FoundationLocationOffset = FindOffsetStruct("/Script/FortniteGame.BuildingFoundationStreamingData", "FoundationLocation");
@@ -117,6 +117,9 @@ UObject* GetPlaylistToUse()
Playlist = GetEventPlaylist(); Playlist = GetEventPlaylist();
} }
// Playlist = FindObject("/MoleGame/Playlists/Playlist_MoleGame.Playlist_MoleGame");
// Playlist = FindObject("/Game/Athena/Playlists/DADBRO/Playlist_DADBRO_Squads_8.Playlist_DADBRO_Squads_8");
return Playlist; return Playlist;
} }
@@ -147,7 +150,7 @@ FName AFortGameModeAthena::RedirectLootTier(const FName& LootTier)
auto& Key = Pair.Key(); auto& Key = Pair.Key();
auto& Value = Pair.Value(); auto& Value = Pair.Value();
LOG_INFO(LogDev, "[{}] {} {}", i, Key.ComparisonIndex.Value ? Key.ToString() : "NULL", Key.ComparisonIndex.Value ? Value.ToString() : "NULL"); // LOG_INFO(LogDev, "[{}] {} {}", i, Key.ComparisonIndex.Value ? Key.ToString() : "NULL", Key.ComparisonIndex.Value ? Value.ToString() : "NULL");
if (Key == LootTier) if (Key == LootTier)
return Value; return Value;
@@ -658,7 +661,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
if (Globals::bAbilitiesEnabled) if (Globals::bAbilitiesEnabled)
{ {
static auto GameplayAbilitySet = LoadObject<UObject>(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_AthenaPlayer.GAS_AthenaPlayer") ? static auto GameplayAbilitySet = Fortnite_Version >= 8.30 ? // 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_AthenaPlayer.GAS_AthenaPlayer") :
LoadObject<UObject>(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer"); LoadObject<UObject>(L"/Game/Abilities/Player/Generic/Traits/DefaultPlayer/GAS_DefaultPlayer.GAS_DefaultPlayer");
@@ -666,6 +669,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
if (GameplayAbilitySet) if (GameplayAbilitySet)
{ {
LOG_INFO(LogDev, "GameplayAbilitySet Name {}", GameplayAbilitySet->GetName());
static auto GameplayAbilitiesOffset = GameplayAbilitySet->GetOffset("GameplayAbilities"); static auto GameplayAbilitiesOffset = GameplayAbilitySet->GetOffset("GameplayAbilities");
auto GameplayAbilities = GameplayAbilitySet->GetPtr<TArray<UClass*>>(GameplayAbilitiesOffset); auto GameplayAbilities = GameplayAbilitySet->GetPtr<TArray<UClass*>>(GameplayAbilitiesOffset);
@@ -751,38 +755,67 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
static auto CreativePortalManagerOffset = GameState->GetOffset("CreativePortalManager"); static auto CreativePortalManagerOffset = GameState->GetOffset("CreativePortalManager");
auto CreativePortalManager = GameState->Get(CreativePortalManagerOffset); auto CreativePortalManager = GameState->Get(CreativePortalManagerOffset);
static auto AvailablePortalsOffset = CreativePortalManager->GetOffset("AvailablePortals"); static auto AvailablePortalsOffset = CreativePortalManager->GetOffset("AvailablePortals", false);
auto& AvailablePortals = CreativePortalManager->Get<TArray<AActor*>>(AvailablePortalsOffset);
auto Portal = (AFortAthenaCreativePortal*)AvailablePortals.at(0);
AvailablePortals.Remove(0);
static auto UsedPortalsOffset = CreativePortalManager->GetOffset("UsedPortals"); AFortAthenaCreativePortal* Portal = nullptr;
auto& UsedPortals = CreativePortalManager->Get<TArray<AActor*>>(UsedPortalsOffset);
UsedPortals.Add(Portal);
// Portal->GetCreatorName() = PlayerStateAthena->GetPlayerName(); if (AvailablePortalsOffset != 0)
{
auto& AvailablePortals = CreativePortalManager->Get<TArray<AActor*>>(AvailablePortalsOffset);
Portal = (AFortAthenaCreativePortal*)AvailablePortals.at(0);
AvailablePortals.Remove(0);
*(FUniqueNetIdReplExperimental*)Portal->GetOwningPlayer() = PlayerStateUniqueId; static auto UsedPortalsOffset = CreativePortalManager->GetOffset("UsedPortals");
Portal->GetPortalOpen() = true; auto& UsedPortals = CreativePortalManager->Get<TArray<AActor*>>(UsedPortalsOffset);
UsedPortals.Add(Portal);
}
else
{
static auto AllPortalsOffset = CreativePortalManager->GetOffset("AllPortals");
auto& AllPortals = CreativePortalManager->Get<TArray<AFortAthenaCreativePortal*>>(AllPortalsOffset);
for (int i = 0; i < AllPortals.size(); i++)
{
auto CurrentPortal = AllPortals.at(i);
static auto PlayersReadyOffset = Portal->GetOffset("PlayersReady"); if (CurrentPortal->GetUserInitiatedLoad())
auto& PlayersReady = Portal->Get<TArray<FUniqueNetIdReplExperimental>>(PlayersReadyOffset); continue;
PlayersReady.Add(PlayerStateUniqueId);
Portal->GetUserInitiatedLoad() = true; Portal = CurrentPortal;
Portal->GetInErrorState() = false; break;
}
}
static auto OwnedPortalOffset = NewPlayer->GetOffset("OwnedPortal"); if (Portal)
NewPlayer->Get<AFortAthenaCreativePortal*>(OwnedPortalOffset) = Portal; {
// Portal->GetCreatorName() = PlayerStateAthena->GetPlayerName();
static auto CreativePlotLinkedVolumeOffset = NewPlayer->GetOffset("CreativePlotLinkedVolume"); *(FUniqueNetIdReplExperimental*)Portal->GetOwningPlayer() = PlayerStateUniqueId;
NewPlayer->Get<AFortVolume*>(CreativePlotLinkedVolumeOffset) = Portal->GetLinkedVolume(); Portal->GetPortalOpen() = true;
Portal->GetLinkedVolume()->GetVolumeState() = EVolumeState::Ready; static auto PlayersReadyOffset = Portal->GetOffset("PlayersReady");
auto& PlayersReady = Portal->Get<TArray<FUniqueNetIdReplExperimental>>(PlayersReadyOffset);
PlayersReady.Add(PlayerStateUniqueId);
static auto IslandPlayset = FindObject<UFortPlaysetItemDefinition>("/Game/Playsets/PID_Playset_60x60_Composed.PID_Playset_60x60_Composed"); Portal->GetUserInitiatedLoad() = true;
Portal->GetInErrorState() = false;
UFortPlaysetItemDefinition::ShowPlayset(IslandPlayset, Portal->GetLinkedVolume()); static auto OwnedPortalOffset = NewPlayer->GetOffset("OwnedPortal");
NewPlayer->Get<AFortAthenaCreativePortal*>(OwnedPortalOffset) = Portal;
static auto CreativePlotLinkedVolumeOffset = NewPlayer->GetOffset("CreativePlotLinkedVolume");
NewPlayer->Get<AFortVolume*>(CreativePlotLinkedVolumeOffset) = Portal->GetLinkedVolume();
Portal->GetLinkedVolume()->GetVolumeState() = EVolumeState::Ready;
static auto IslandPlayset = FindObject<UFortPlaysetItemDefinition>("/Game/Playsets/PID_Playset_60x60_Composed.PID_Playset_60x60_Composed");
UFortPlaysetItemDefinition::ShowPlayset(IslandPlayset, Portal->GetLinkedVolume());
}
else
{
LOG_INFO(LogCreative, "Failed to find an open portal!");
}
} }
static auto SpawnActorDataListOffset = GameMode->GetOffset("SpawnActorDataList"); static auto SpawnActorDataListOffset = GameMode->GetOffset("SpawnActorDataList");

View File

@@ -11,7 +11,7 @@ UFortItem* CreateItemInstance(AFortPlayerController* PlayerController, UFortItem
return NewItemInstance; return NewItemInstance;
} }
std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddItem(UFortItemDefinition* ItemDefinition, bool* bShouldUpdate, int Count) std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddItem(UFortItemDefinition* ItemDefinition, bool* bShouldUpdate, int Count, int LoadedAmmo, bool bShouldAddToStateValues)
{ {
if (bShouldUpdate) if (bShouldUpdate)
*bShouldUpdate = false; *bShouldUpdate = false;
@@ -45,6 +45,95 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
return std::make_pair(NewItemInstances, ModifiedItemInstances); return std::make_pair(NewItemInstances, ModifiedItemInstances);
} }
bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count)
{
if (bShouldUpdate)
*bShouldUpdate = false;
auto ItemInstance = FindItemInstance(ItemGuid);
auto ReplicatedEntry = FindReplicatedEntry(ItemGuid);
if (!ItemInstance || !ReplicatedEntry)
return false;
auto ItemDefinition = Cast<UFortWorldItemDefinition>(ReplicatedEntry->GetItemDefinition());
if (!ItemDefinition)
return false;
auto NewCount = ReplicatedEntry->GetCount() - Count;
if (NewCount > 0)
{
ItemInstance->GetItemEntry()->GetCount() = NewCount;
ReplicatedEntry->GetCount() = NewCount;
GetItemList().MarkItemDirty(ItemInstance->GetItemEntry());
GetItemList().MarkItemDirty(ReplicatedEntry);
return true;
}
static auto FortItemEntryStruct = FindObject(L"/Script/FortniteGame.FortItemEntry");
static auto FortItemEntrySize = *(int*)(__int64(FortItemEntryStruct) + Offsets::PropertiesSize);
auto& ItemInstances = GetItemList().GetItemInstances();
auto& ReplicatedEntries = GetItemList().GetReplicatedEntries();
for (int i = 0; i < ItemInstances.Num(); i++)
{
if (ItemInstances.at(i)->GetItemEntry()->GetItemGuid() == ItemGuid)
{
ItemInstances.Remove(i);
break;
}
}
for (int i = 0; i < ReplicatedEntries.Num(); i++)
{
if (ReplicatedEntries.at(i).GetItemGuid() == ItemGuid)
{
ReplicatedEntries.Remove(i, FortItemEntrySize);
break;
}
}
// todo remove from weaponlist
if (bShouldUpdate)
*bShouldUpdate = true;
return true;
}
void AFortInventory::ModifyCount(UFortItem* ItemInstance, int New, bool bRemove, std::pair<FFortItemEntry*, FFortItemEntry*>* outEntries, bool bUpdate)
{
auto ReplicatedEntry = FindReplicatedEntry(ItemInstance->GetItemEntry()->GetItemGuid());
if (!ReplicatedEntry)
return;
if (!bRemove)
{
ItemInstance->GetItemEntry()->GetCount() += New;
ReplicatedEntry->GetCount() += New;
}
else
{
ItemInstance->GetItemEntry()->GetCount() -= New;
ReplicatedEntry->GetCount() -= New;
}
if (outEntries)
*outEntries = { ItemInstance->GetItemEntry(), ReplicatedEntry};
if (bUpdate || !outEntries)
{
GetItemList().MarkItemDirty(ItemInstance->GetItemEntry());
GetItemList().MarkItemDirty(ReplicatedEntry);
}
}
UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid) UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid)
{ {
auto& ItemInstances = GetItemList().GetItemInstances(); auto& ItemInstances = GetItemList().GetItemInstances();
@@ -57,5 +146,20 @@ UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid)
return ItemInstance; return ItemInstance;
} }
return nullptr;
}
FFortItemEntry* AFortInventory::FindReplicatedEntry(const FGuid& Guid)
{
auto& ReplicatedEntries = GetItemList().GetReplicatedEntries();
for (int i = 0; i < ReplicatedEntries.Num(); i++)
{
auto& ReplicatedEntry = ReplicatedEntries.At(i);
if (ReplicatedEntry.GetItemGuid() == Guid)
return &ReplicatedEntry;
}
return nullptr; return nullptr;
} }

View File

@@ -9,6 +9,34 @@
#include "reboot.h" #include "reboot.h"
static bool IsPrimaryQuickbar(UFortItemDefinition* ItemDefinition)
{
/* if (ItemDefinition->IsA(UFortDecoItemDefinition::StaticClass()))
{
if (ItemDefinition->IsA(UFortTrapItemDefinition::StaticClass()))
return false;
else
return true;
}
else if (ItemDefinition->IsA(UFortWeaponItemDefinition::StaticClass()))
return true; */
static auto FortWeaponMeleeItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortWeaponMeleeItemDefinition");
static auto FortEditToolItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortEditToolItemDefinition");
static auto FortBuildingItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortBuildingItemDefinition");
static auto FortAmmoItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortAmmoItemDefinition");
static auto FortResourceItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortResourceItemDefinition");
static auto FortTrapItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortTrapItemDefinition");
if (!ItemDefinition->IsA(FortWeaponMeleeItemDefinitionClass) && !ItemDefinition->IsA(FortEditToolItemDefinitionClass) &&
!ItemDefinition->IsA(FortBuildingItemDefinitionClass) && !ItemDefinition->IsA(FortAmmoItemDefinitionClass)
&& !ItemDefinition->IsA(FortResourceItemDefinitionClass) && !ItemDefinition->IsA(FortTrapItemDefinitionClass))
return true;
return false;
}
enum class EFortInventoryType : unsigned char enum class EFortInventoryType : unsigned char
{ {
World = 0, World = 0,
@@ -25,10 +53,10 @@ struct FFortItemList : public FFastArraySerializer
return *(TArray<UFortItem*>*)(__int64(this) + ItemInstancesOffset); return *(TArray<UFortItem*>*)(__int64(this) + ItemInstancesOffset);
} }
TArray<FFastArraySerializerItem>& GetReplicatedEntries() TArray<FFortItemEntry>& GetReplicatedEntries()
{ {
static auto ReplicatedEntriesOffset = FindOffsetStruct("/Script/FortniteGame.FortItemList", "ReplicatedEntries"); static auto ReplicatedEntriesOffset = FindOffsetStruct("/Script/FortniteGame.FortItemList", "ReplicatedEntries");
return *(TArray<FFastArraySerializerItem>*)(__int64(this) + ReplicatedEntriesOffset); return *(TArray<FFortItemEntry>*)(__int64(this) + ReplicatedEntriesOffset);
} }
}; };
@@ -63,7 +91,10 @@ public:
} }
} }
std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AddItem(UFortItemDefinition* ItemDefinition, bool* bShouldUpdate, int Count = 1); std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AddItem(UFortItemDefinition* ItemDefinition, bool* bShouldUpdate, int Count = 1, int LoadedAmmo = -1, bool bShouldAddToStateValues = false);
bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count);
void ModifyCount(UFortItem* ItemInstance, int New, bool bRemove = false, std::pair<FFortItemEntry*, FFortItemEntry*>* outEntries = nullptr, bool bUpdate = true);
UFortItem* FindItemInstance(const FGuid& Guid); UFortItem* FindItemInstance(const FGuid& Guid);
FFortItemEntry* FindReplicatedEntry(const FGuid& Guid);
}; };

View File

@@ -13,10 +13,10 @@ struct FFortItemEntry : FFastArraySerializerItem
return *(FGuid*)(__int64(this) + ItemGuidOffset); return *(FGuid*)(__int64(this) + ItemGuidOffset);
} }
UObject*& GetItemDefinition() class UFortItemDefinition*& GetItemDefinition()
{ {
static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ItemDefinition"); static auto ItemDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.FortItemEntry", "ItemDefinition");
return *(UObject**)(__int64(this) + ItemDefinitionOffset); return *(class UFortItemDefinition**)(__int64(this) + ItemDefinitionOffset);
} }
int& GetCount() int& GetCount()

View File

@@ -11,4 +11,11 @@ class UFortItemDefinition : public UObject
public: public:
UFortItem* CreateTemporaryItemInstanceBP(int Count, int Level = 1); UFortItem* CreateTemporaryItemInstanceBP(int Count, int Level = 1);
float GetMaxStackSize(); float GetMaxStackSize();
bool DoesAllowMultipleStacks()
{
static auto bAllowMultipleStacksOffset = GetOffset("bAllowMultipleStacks");
static auto bAllowMultipleStacksFieldMask = GetFieldMask(GetProperty("bAllowMultipleStacks"));
return ReadBitfieldValue(bAllowMultipleStacksOffset, bAllowMultipleStacksFieldMask);
}
}; };

View File

@@ -122,8 +122,7 @@ std::vector<std::pair<UFortItemDefinition*, int>> PickLootDrops(FName TierGroupN
if (TierGroupLTDs.size() == 0) if (TierGroupLTDs.size() == 0)
{ {
// std::cout << "Failed to find LTD!\n"; LOG_WARN(LogLoot, "Failed to find any LTD for: {}", TierGroupName.ToString());
std::cout << "Failed to find any LTD for: " << TierGroupName.ToString() << '\n';
return LootDrops; return LootDrops;
} }
@@ -253,7 +252,9 @@ std::vector<std::pair<UFortItemDefinition*, int>> PickLootDrops(FName TierGroupN
std::cout << "b: " << b << '\n'; */ std::cout << "b: " << b << '\n'; */
} }
LootDrops.reserve(NumLootPackageDrops); static int AmountToAdd = Engine_Version >= 424 ? 1 : 0; // fr
LootDrops.reserve(NumLootPackageDrops + AmountToAdd);
for (float i = 0; i < NumLootPackageDrops; i++) for (float i = 0; i < NumLootPackageDrops; i++)
{ {
@@ -261,7 +262,8 @@ std::vector<std::pair<UFortItemDefinition*, int>> PickLootDrops(FName TierGroupN
break; break;
auto TierGroupLP = TierGroupLPs.at(i); auto TierGroupLP = TierGroupLPs.at(i);
auto TierGroupLPStr = TierGroupLP->GetLootPackageCall().ToString(); auto& LootPackageCallFStr = TierGroupLP->GetLootPackageCall();
auto TierGroupLPStr = LootPackageCallFStr.IsValid() ? LootPackageCallFStr.ToString() : ".Empty";
if (TierGroupLPStr.contains(".Empty")) if (TierGroupLPStr.contains(".Empty"))
{ {

View File

@@ -3,6 +3,8 @@
#include "FortPawn.h" #include "FortPawn.h"
#include "FortItemDefinition.h" #include "FortItemDefinition.h"
#include "FortPlayerState.h" #include "FortPlayerState.h"
#include "FortPlayerPawn.h"
#include "FortPlayerController.h"
void AFortPickup::TossPickup(FVector FinalLocation, AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource) void AFortPickup::TossPickup(FVector FinalLocation, AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource)
{ {
@@ -23,9 +25,8 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca
if (auto Pickup = GetWorld()->SpawnActor<AFortPickup>(FortPickupClass, Location)) if (auto Pickup = GetWorld()->SpawnActor<AFortPickup>(FortPickupClass, Location))
{ {
static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup"); static auto PawnWhoDroppedPickupOffset = Pickup->GetOffset("PawnWhoDroppedPickup");
static auto PrimaryPickupItemEntryOffset = Pickup->GetOffset("PrimaryPickupItemEntry");
auto PrimaryPickupItemEntry = Pickup->GetPtr<FFortItemEntry>(PrimaryPickupItemEntryOffset); auto PrimaryPickupItemEntry = Pickup->GetPrimaryPickupItemEntry();
PrimaryPickupItemEntry->GetCount() = Count; PrimaryPickupItemEntry->GetCount() = Count;
PrimaryPickupItemEntry->GetItemDefinition() = ItemDef; PrimaryPickupItemEntry->GetItemDefinition() = ItemDef;
@@ -33,7 +34,6 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca
// Pickup->OptionalOwnerID = Pawn ? PlayerState->WorldPlayerId : -1; // Pickup->OptionalOwnerID = Pawn ? PlayerState->WorldPlayerId : -1;
Pickup->Get<AFortPawn*>(PawnWhoDroppedPickupOffset) = Pawn; Pickup->Get<AFortPawn*>(PawnWhoDroppedPickupOffset) = Pawn;
// Pickup->bCombinePickupsWhenTossCompletes = true;
bool bToss = true; bool bToss = true;
@@ -55,4 +55,156 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca
} }
return nullptr; return nullptr;
}
char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
{
auto Pawn = Cast<AFortPlayerPawn>(Pickup->GetPickupLocationData()->GetPickupTarget());
if (!Pawn)
return CompletePickupAnimationOriginal(Pickup);
auto PlayerController = Cast<AFortPlayerController>(Pawn->GetController());
if (!PlayerController)
return CompletePickupAnimationOriginal(Pickup);
auto WorldInventory = PlayerController->GetWorldInventory();
if (!WorldInventory)
return CompletePickupAnimationOriginal(Pickup);
auto PickupEntry = Pickup->GetPrimaryPickupItemEntry();
auto PickupItemDefinition = Cast<UFortWorldItemDefinition>(PickupEntry->GetItemDefinition());
auto IncomingCount = PickupEntry->GetCount();
if (!PickupItemDefinition)
return CompletePickupAnimationOriginal(Pickup);
auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances();
auto& CurrentItemGuid = Pickup->GetPickupLocationData()->GetPickupGuid(); // Pawn->CurrentWeapon->ItemEntryGuid;
auto ItemInstanceToSwap = WorldInventory->FindItemInstance(CurrentItemGuid);
auto ItemEntryToSwap = ItemInstanceToSwap->GetItemEntry();
auto ItemDefinitionToSwap = ItemEntryToSwap ? Cast<UFortWorldItemDefinition>(ItemEntryToSwap->GetItemDefinition()) : nullptr;
bool bHasSwapped = false;
int cpyCount = IncomingCount;
auto PawnLoc = Pawn->GetActorLocation();
auto ItemDefGoingInPrimary = IsPrimaryQuickbar(PickupItemDefinition);
std::vector<std::pair<FFortItemEntry*, FFortItemEntry*>> PairsToMarkDirty; // vector of sets or something so no duplicates??
bool bForceOverflow = false;
while (cpyCount > 0)
{
int PrimarySlotsFilled = 0;
bool bEverStacked = false;
bool bDoesStackExist = false;
bool bIsInventoryFull = false;
for (int i = 0; i < ItemInstances.Num(); i++)
{
auto ItemInstance = ItemInstances.at(i);
auto CurrentItemEntry = ItemInstance->GetItemEntry();
if (ItemDefGoingInPrimary && IsPrimaryQuickbar(CurrentItemEntry->GetItemDefinition()))
{
PrimarySlotsFilled++;
}
bIsInventoryFull = (PrimarySlotsFilled /* - 6 */) >= 5;
if (bIsInventoryFull) // probs shouldnt do in loop but alr
{
if (ItemInstanceToSwap && ItemDefinitionToSwap->CanBeDropped() && !bHasSwapped)
{
auto SwappedPickup = SpawnPickup(ItemDefinitionToSwap, PawnLoc, ItemEntryToSwap->GetCount(),
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, ItemEntryToSwap->GetLoadedAmmo(), Pawn);
WorldInventory->RemoveItem(CurrentItemGuid, nullptr, ItemEntryToSwap->GetCount());
bHasSwapped = true;
continue; // ???
}
}
if (CurrentItemEntry->GetItemDefinition() == PickupItemDefinition)
{
if (CurrentItemEntry->GetCount() < PickupItemDefinition->GetMaxStackSize())
{
int OverStack = CurrentItemEntry->GetCount() + cpyCount - PickupItemDefinition->GetMaxStackSize();
int AmountToStack = OverStack > 0 ? cpyCount - OverStack : cpyCount;
cpyCount -= AmountToStack;
std::pair<FFortItemEntry*, FFortItemEntry*> Pairs;
WorldInventory->ModifyCount(ItemInstance, AmountToStack, false, &Pairs, false);
PairsToMarkDirty.push_back(Pairs);
bEverStacked = true;
// if (cpyCount > 0)
// break;
}
bDoesStackExist = true;
}
if ((bIsInventoryFull || bForceOverflow) && cpyCount > 0) // overflow
{
UFortWorldItemDefinition* ItemDefinitionToSpawn = PickupItemDefinition;
int AmountToSpawn = cpyCount > PickupItemDefinition->GetMaxStackSize() ? PickupItemDefinition->GetMaxStackSize() : cpyCount;
SpawnPickup(ItemDefinitionToSpawn, PawnLoc, AmountToSpawn, EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, -1, Pawn);
cpyCount -= AmountToSpawn;
bForceOverflow = false;
}
if (cpyCount <= 0)
break;
}
if (cpyCount > 0 && !bIsInventoryFull)
{
if (bDoesStackExist ? PickupItemDefinition->DoesAllowMultipleStacks() : true)
{
auto NewItemCount = cpyCount > PickupItemDefinition->GetMaxStackSize() ? PickupItemDefinition->GetMaxStackSize() : cpyCount;
auto NewItem = WorldInventory->AddItem(PickupItemDefinition, nullptr,
NewItemCount, PickupEntry->GetLoadedAmmo(), true);
// if (NewItem)
cpyCount -= NewItemCount;
}
else
{
bForceOverflow = true;
}
}
}
// auto Item = GiveItem(PlayerController, ItemDef, cpyCount, CurrentPickup->PrimaryPickupItemEntry.LoadedAmmo, true);
/* for (int i = 0; i < Pawn->IncomingPickups.Num(); i++)
{
Pawn->IncomingPickups[i]->PickupLocationData.PickupGuid = Item->ItemEntry.ItemGuid;
} */
WorldInventory->Update(PairsToMarkDirty.size() == 0);
for (auto& [key, value] : PairsToMarkDirty)
{
WorldInventory->GetItemList().MarkItemDirty(key);
WorldInventory->GetItemList().MarkItemDirty(value);
}
return CompletePickupAnimationOriginal(Pickup);
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Actor.h" #include "Actor.h"
#include "FortPawn.h"
enum class EFortPickupSourceTypeFlag : uint8_t enum class EFortPickupSourceTypeFlag : uint8_t
{ {
@@ -28,12 +29,61 @@ enum class EFortPickupSpawnSource : uint8_t
ENUM_CLASS_FLAGS(EFortPickupSourceTypeFlag) ENUM_CLASS_FLAGS(EFortPickupSourceTypeFlag)
struct FFortPickupLocationData
{
AFortPawn*& GetPickupTarget()
{
static auto PickupTargetOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "PickupTarget");
return *(AFortPawn**)(__int64(this) + PickupTargetOffset);
}
float& GetFlyTime()
{
static auto FlyTimeOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "FlyTime");
return *(float*)(__int64(this) + FlyTimeOffset);
}
AFortPawn*& GetItemOwner()
{
static auto ItemOwnerOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "ItemOwner");
return *(AFortPawn**)(__int64(this) + ItemOwnerOffset);
}
FVector& GetStartDirection()
{
static auto StartDirectionOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "StartDirection");
return *(FVector*)(__int64(this) + StartDirectionOffset);
}
FGuid& GetPickupGuid()
{
static auto PickupGuidOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "PickupGuid");
return *(FGuid*)(__int64(this) + PickupGuidOffset);
}
};
class AFortPickup : public AActor class AFortPickup : public AActor
{ {
public: public:
static inline char (*CompletePickupAnimationOriginal)(AFortPickup* Pickup);
void TossPickup(FVector FinalLocation, class AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource); void TossPickup(FVector FinalLocation, class AFortPawn* ItemOwner, int OverrideMaxStackCount, bool bToss, EFortPickupSourceTypeFlag InPickupSourceTypeFlags, EFortPickupSpawnSource InPickupSpawnSource);
FFortPickupLocationData* GetPickupLocationData()
{
static auto PickupLocationDataOffset = this->GetOffset("PickupLocationData");
return this->GetPtr<FFortPickupLocationData>(PickupLocationDataOffset);
}
FFortItemEntry* GetPrimaryPickupItemEntry()
{
static auto PrimaryPickupItemEntryOffset = this->GetOffset("PrimaryPickupItemEntry");
return this->GetPtr<FFortItemEntry>(PrimaryPickupItemEntryOffset);
}
static AFortPickup* SpawnPickup(class UFortItemDefinition* ItemDef, FVector Location, int Count, static AFortPickup* SpawnPickup(class UFortItemDefinition* ItemDef, FVector Location, int Count,
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset, EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
int LoadedAmmo = -1, class AFortPawn* Pawn = nullptr); int LoadedAmmo = -1, class AFortPawn* Pawn = nullptr);
static char CompletePickupAnimationHook(AFortPickup* Pickup);
}; };

View File

@@ -91,15 +91,15 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
{ {
static auto bAlreadySearchedOffset = BuildingContainer->GetOffset("bAlreadySearched"); static auto bAlreadySearchedOffset = BuildingContainer->GetOffset("bAlreadySearched");
static auto SearchBounceDataOffset = BuildingContainer->GetOffset("SearchBounceData"); static auto SearchBounceDataOffset = BuildingContainer->GetOffset("SearchBounceData");
static auto bAlreadySearchedFieldMask = GetFieldMask(BuildingContainer->GetProperty("bAlreadySearched"));
static auto SearchAnimationCountOffset = FindOffsetStruct("/Script/FortniteGame.FortSearchBounceData", "SearchAnimationCount"); static auto SearchAnimationCountOffset = FindOffsetStruct("/Script/FortniteGame.FortSearchBounceData", "SearchAnimationCount");
static auto bAlreadySearchedFieldMask = GetFieldMask(BuildingContainer->GetProperty(bAlreadySearchedOffset));
auto SearchBounceData = BuildingContainer->GetPtr<void>(SearchBounceDataOffset); auto SearchBounceData = BuildingContainer->GetPtr<void>(SearchBounceDataOffset);
if (BuildingContainer->ReadBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask)) if (BuildingContainer->ReadBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask))
return; return;
LOG_INFO(LogInteraction, "bAlreadySearchedFieldMask: {}", bAlreadySearchedFieldMask); // LOG_INFO(LogInteraction, "bAlreadySearchedFieldMask: {}", bAlreadySearchedFieldMask);
BuildingContainer->SetBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask, true); BuildingContainer->SetBitfieldValue(bAlreadySearchedOffset, bAlreadySearchedFieldMask, true);
(*(int*)(__int64(SearchBounceData) + SearchAnimationCountOffset))++; (*(int*)(__int64(SearchBounceData) + SearchAnimationCountOffset))++;
@@ -112,7 +112,9 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
auto LootDrops = PickLootDrops(RedirectedLootTier); auto LootDrops = PickLootDrops(RedirectedLootTier);
FVector LocationToSpawnLoot = BuildingContainer->GetActorLocation(); LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
FVector LocationToSpawnLoot = BuildingContainer->GetActorLocation() + BuildingContainer->GetActorRightVector() * 70.f + FVector{0, 0, 50};
for (int i = 0; i < LootDrops.size(); i++) for (int i = 0; i < LootDrops.size(); i++)
{ {
@@ -120,6 +122,9 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
// , (AFortPawn*)PlayerController->GetPawn() // should we put this here? // , (AFortPawn*)PlayerController->GetPawn() // should we put this here?
); );
} }
// if (BuildingContainer->ShouldDestroyOnSearch())
// BuildingContainer->K2_DestroyActor();
} }
return ServerAttemptInteractOriginal(Context, Stack, Ret); return ServerAttemptInteractOriginal(Context, Stack, Ret);
@@ -224,6 +229,41 @@ void AFortPlayerController::ServerCreateBuildingActorHook(AFortPlayerController*
BuildingActor->InitializeBuildingActor(PlayerController, BuildingActor, true); BuildingActor->InitializeBuildingActor(PlayerController, BuildingActor, true);
} }
void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController* PlayerController, FGuid ItemGuid, int Count)
{
LOG_INFO(LogDev, "ServerAttemptInventoryDropHook!");
auto Pawn = PlayerController->GetMyFortPawn();
if (Count < 0 || !Pawn)
return;
auto WorldInventory = PlayerController->GetWorldInventory();
auto ReplicatedEntry = WorldInventory->FindReplicatedEntry(ItemGuid);
if (!ReplicatedEntry)
return;
auto ItemDefinition = Cast<UFortWorldItemDefinition>(ReplicatedEntry->GetItemDefinition());
if (!ItemDefinition)
return;
auto Pickup = AFortPickup::SpawnPickup(ItemDefinition, Pawn->GetActorLocation(), Count,
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, ReplicatedEntry->GetLoadedAmmo(), Pawn);
if (!Pickup)
return;
bool bShouldUpdate = false;
if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count))
return;
if (bShouldUpdate)
WorldInventory->Update();
}
void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* PlayerController, UObject* EmoteAsset) void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* PlayerController, UObject* EmoteAsset)
{ {
auto PlayerState = (AFortPlayerStateAthena*)PlayerController->GetPlayerState(); auto PlayerState = (AFortPlayerStateAthena*)PlayerController->GetPlayerState();

View File

@@ -62,6 +62,7 @@ public:
static void ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation); static void ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation);
static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData); static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData);
static void ServerAttemptInventoryDropHook(AFortPlayerController* PlayerController, FGuid ItemGuid, int Count);
static void ServerPlayEmoteItemHook(AFortPlayerController* PlayerController, UObject* EmoteAsset); static void ServerPlayEmoteItemHook(AFortPlayerController* PlayerController, UObject* EmoteAsset);
static void ClientOnPawnDiedHook(AFortPlayerController* PlayerController, __int64 DeathReport); static void ClientOnPawnDiedHook(AFortPlayerController* PlayerController, __int64 DeathReport);

View File

@@ -73,22 +73,15 @@ void AFortPlayerPawn::ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup*
return; return;
static auto IncomingPickupsOffset = Pawn->GetOffset("IncomingPickups"); static auto IncomingPickupsOffset = Pawn->GetOffset("IncomingPickups");
static auto PickupLocationDataOffset = Pickup->GetOffset("PickupLocationData");
auto PickupLocationData = Pickup->GetPtr<__int64>(PickupLocationDataOffset);
Pawn->Get<TArray<AFortPickup*>>(IncomingPickupsOffset).Add(Pickup); Pawn->Get<TArray<AFortPickup*>>(IncomingPickupsOffset).Add(Pickup);
static auto PickupTargetOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "PickupTarget"); auto PickupLocationData = Pickup->GetPickupLocationData();
static auto FlyTimeOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "FlyTime");
static auto ItemOwnerOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "ItemOwner");
static auto StartDirectionOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "StartDirection");
static auto PickupGuidOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "PickupGuid");
*(AFortPawn**)(__int64(PickupLocationData) + PickupTargetOffset) = Pawn; PickupLocationData->GetPickupTarget() = Pawn;
*(float*)(__int64(PickupLocationData) + FlyTimeOffset) = 0.40f; PickupLocationData->GetFlyTime() = 0.40f;
*(AFortPawn**)(__int64(PickupLocationData) + ItemOwnerOffset) = Pawn; PickupLocationData->GetItemOwner() = Pawn;
*(FVector*)(__int64(PickupLocationData) + StartDirectionOffset) = InStartDirection; PickupLocationData->GetStartDirection() = InStartDirection;
*(FGuid*)(__int64(PickupLocationData) + PickupGuidOffset) = Pawn->GetCurrentWeapon() ? Pawn->GetCurrentWeapon()->GetItemEntryGuid() : FGuid(); PickupLocationData->GetPickupGuid() = Pawn->GetCurrentWeapon() ? Pawn->GetCurrentWeapon()->GetItemEntryGuid() : FGuid();
static auto OnRep_PickupLocationDataFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPickup.OnRep_PickupLocationData"); static auto OnRep_PickupLocationDataFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPickup.OnRep_PickupLocationData");
Pickup->ProcessEvent(OnRep_PickupLocationDataFn); Pickup->ProcessEvent(OnRep_PickupLocationDataFn);

View File

@@ -17,37 +17,41 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
GameMode->ProcessEvent(fn, &AGameModeBase_SpawnDefaultPawnAtTransform_Params); GameMode->ProcessEvent(fn, &AGameModeBase_SpawnDefaultPawnAtTransform_Params);
auto NewPlayerAsAthena = Cast<AFortPlayerControllerAthena>(NewPlayer); bool bIsRespawning = false;
if (NewPlayerAsAthena) if (!bIsRespawning)
{ {
auto WorldInventory = NewPlayerAsAthena->GetWorldInventory(); auto NewPlayerAsAthena = Cast<AFortPlayerControllerAthena>(NewPlayer);
auto CosmeticLoadoutPickaxe = NewPlayerAsAthena->GetCosmeticLoadout()->GetPickaxe(); if (NewPlayerAsAthena)
static auto WeaponDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.AthenaPickaxeItemDefinition", "WeaponDefinition"); {
auto WorldInventory = NewPlayerAsAthena->GetWorldInventory();
auto Pickaxe = CosmeticLoadoutPickaxe ? CosmeticLoadoutPickaxe->Get<UFortItemDefinition*>(WeaponDefinitionOffset) auto CosmeticLoadoutPickaxe = NewPlayerAsAthena->GetCosmeticLoadout()->GetPickaxe();
: FindObject<UFortItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01"); static auto WeaponDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.AthenaPickaxeItemDefinition", "WeaponDefinition");
static UFortItemDefinition* EditToolItemDefinition = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/EditTool.EditTool"); auto Pickaxe = CosmeticLoadoutPickaxe ? CosmeticLoadoutPickaxe->Get<UFortItemDefinition*>(WeaponDefinitionOffset)
static UFortItemDefinition* PickaxeDefinition = Pickaxe; : FindObject<UFortItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01");
static UFortItemDefinition* BuildingItemData_Wall = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Wall.BuildingItemData_Wall");
static UFortItemDefinition* BuildingItemData_Floor = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Floor.BuildingItemData_Floor");
static UFortItemDefinition* BuildingItemData_Stair_W = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Stair_W.BuildingItemData_Stair_W");
static UFortItemDefinition* BuildingItemData_RoofS = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_RoofS.BuildingItemData_RoofS");
static UFortItemDefinition* WoodItemData = FindObject<UFortItemDefinition>(L"/Game/Items/ResourcePickups/WoodItemData.WoodItemData");
WorldInventory->AddItem(EditToolItemDefinition, nullptr); static UFortItemDefinition* EditToolItemDefinition = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/EditTool.EditTool");
WorldInventory->AddItem(BuildingItemData_Wall, nullptr); static UFortItemDefinition* PickaxeDefinition = Pickaxe;
WorldInventory->AddItem(BuildingItemData_Floor, nullptr); static UFortItemDefinition* BuildingItemData_Wall = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Wall.BuildingItemData_Wall");
WorldInventory->AddItem(BuildingItemData_Stair_W, nullptr); static UFortItemDefinition* BuildingItemData_Floor = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Floor.BuildingItemData_Floor");
WorldInventory->AddItem(BuildingItemData_RoofS, nullptr); static UFortItemDefinition* BuildingItemData_Stair_W = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Stair_W.BuildingItemData_Stair_W");
WorldInventory->AddItem(PickaxeDefinition, nullptr); static UFortItemDefinition* BuildingItemData_RoofS = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_RoofS.BuildingItemData_RoofS");
WorldInventory->AddItem(WoodItemData, nullptr, 100); static UFortItemDefinition* WoodItemData = FindObject<UFortItemDefinition>(L"/Game/Items/ResourcePickups/WoodItemData.WoodItemData");
WorldInventory->Update(true); WorldInventory->AddItem(EditToolItemDefinition, nullptr);
WorldInventory->AddItem(BuildingItemData_Wall, nullptr);
WorldInventory->AddItem(BuildingItemData_Floor, nullptr);
WorldInventory->AddItem(BuildingItemData_Stair_W, nullptr);
WorldInventory->AddItem(BuildingItemData_RoofS, nullptr);
WorldInventory->AddItem(PickaxeDefinition, nullptr);
WorldInventory->AddItem(WoodItemData, nullptr, 100);
WorldInventory->Update(true);
}
} }
return AGameModeBase_SpawnDefaultPawnAtTransform_Params.ReturnValue; return AGameModeBase_SpawnDefaultPawnAtTransform_Params.ReturnValue;
} }

View File

@@ -11,8 +11,15 @@ struct FGameplayAbilitySpecHandle
void GenerateNewHandle() void GenerateNewHandle()
{ {
static int GHandle = 1; if (true)
Handle = ++GHandle; {
Handle = rand();
}
else
{
static int GHandle = 1;
Handle = ++GHandle;
}
} }
}; };
@@ -23,7 +30,7 @@ struct FGameplayAbilitySpec : FFastArraySerializerItem
static auto GameplayAbilitySpecStruct = FindObject<UClass>("/Script/GameplayAbilities.GameplayAbilitySpec"); static auto GameplayAbilitySpecStruct = FindObject<UClass>("/Script/GameplayAbilities.GameplayAbilitySpec");
static auto StructSize = GameplayAbilitySpecStruct->GetPropertiesSize(); static auto StructSize = GameplayAbilitySpecStruct->GetPropertiesSize();
// *(int*)(__int64(GameplayAbilitySpecStruct) + Offsets::PropertiesSize); // *(int*)(__int64(GameplayAbilitySpecStruct) + Offsets::PropertiesSize);
LOG_INFO(LogAbility, "StructSize: {}", StructSize); // LOG_INFO(LogAbilities, "StructSize: {}", StructSize);
return StructSize; return StructSize;
} }

View File

@@ -17,37 +17,6 @@ FName* getFNameOfProp(void* Property)
return 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) void* UObject::GetProperty(const std::string& ChildName, bool bWarnIfNotFound)
{ {
for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct)) for (auto CurrentClass = ClassPrivate; CurrentClass; CurrentClass = *(UClass**)(__int64(CurrentClass) + Offsets::SuperStruct))

View File

@@ -44,7 +44,6 @@ public:
bool IsA(UClass* Other); bool IsA(UClass* Other);
void* GetProperty(int Offset, bool bWarnIfNotFound = true);
void* GetProperty(const std::string& ChildName, bool bWarnIfNotFound = true); void* GetProperty(const std::string& ChildName, bool bWarnIfNotFound = true);
int GetOffset(const std::string& ChildName, bool bWarnIfNotFound = true); int GetOffset(const std::string& ChildName, bool bWarnIfNotFound = true);

View File

@@ -10,4 +10,10 @@ public:
static auto PlayerStateOffset = GetOffset("PlayerState"); static auto PlayerStateOffset = GetOffset("PlayerState");
return Get(PlayerStateOffset); return Get(PlayerStateOffset);
} }
class APlayerController* GetController()
{
static auto ControllerOffset = GetOffset("Controller");
return Get<class APlayerController*>(ControllerOffset);
}
}; };

View File

@@ -213,6 +213,7 @@
<ClInclude Include="addresses.h" /> <ClInclude Include="addresses.h" />
<ClInclude Include="ai.h" /> <ClInclude Include="ai.h" />
<ClInclude Include="Array.h" /> <ClInclude Include="Array.h" />
<ClInclude Include="AthenaMarkerComponent.h" />
<ClInclude Include="BitArray.h" /> <ClInclude Include="BitArray.h" />
<ClInclude Include="BuildingActor.h" /> <ClInclude Include="BuildingActor.h" />
<ClInclude Include="BuildingContainer.h" /> <ClInclude Include="BuildingContainer.h" />

View File

@@ -386,6 +386,9 @@
<ClInclude Include="FortPlaysetItemDefinition.h"> <ClInclude Include="FortPlaysetItemDefinition.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter> <Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="AthenaMarkerComponent.h">
<Filter>FortniteGame\Source\FortniteGame\Public</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Engine"> <Filter Include="Engine">

View File

@@ -6,4 +6,34 @@ public:
float X; float X;
float Y; float Y;
float Z; float Z;
FVector operator+(const FVector& A)
{
return FVector{ this->X + A.X, this->Y + A.Y, this->Z + A.Z };
}
FVector operator-(const FVector& A)
{
return FVector{ this->X - A.X, this->Y - A.Y, this->Z - A.Z };
}
FVector operator*(const float A)
{
return FVector{ this->X * A, this->Y * A, this->Z * A };
}
bool operator==(const FVector& A)
{
return X == A.X && Y == A.Y && Z == A.Z;
}
void operator+=(const FVector& A)
{
*this = *this + A;
}
void operator-=(const FVector& A)
{
*this = *this - A;
}
}; };

View File

@@ -194,6 +194,7 @@ void Addresses::FindAll()
Addresses::NavSystemCleanUp = FindNavSystemCleanUp(); Addresses::NavSystemCleanUp = FindNavSystemCleanUp();
Addresses::LoadPlayset = FindLoadPlayset(); Addresses::LoadPlayset = FindLoadPlayset();
Addresses::SetZoneToIndex = FindSetZoneToIndex(); Addresses::SetZoneToIndex = FindSetZoneToIndex();
Addresses::CompletePickupAnimation = FindCompletePickupAnimation();
} }
void Addresses::Print() void Addresses::Print()
@@ -231,6 +232,7 @@ void Addresses::Print()
LOG_INFO(LogDev, "NavSystemCleanUp: 0x{:x}", NavSystemCleanUp - Base); LOG_INFO(LogDev, "NavSystemCleanUp: 0x{:x}", NavSystemCleanUp - Base);
LOG_INFO(LogDev, "LoadPlayset: 0x{:x}", LoadPlayset - Base); LOG_INFO(LogDev, "LoadPlayset: 0x{:x}", LoadPlayset - Base);
LOG_INFO(LogDev, "SetZoneToIndex: 0x{:x}", SetZoneToIndex - Base); LOG_INFO(LogDev, "SetZoneToIndex: 0x{:x}", SetZoneToIndex - Base);
LOG_INFO(LogDev, "CompletePickupAnimation: 0x{:x}", CompletePickupAnimation - Base);
} }
void Offsets::FindAll() void Offsets::FindAll()
@@ -292,6 +294,7 @@ void Addresses::Init()
FMemory::Realloc = decltype(FMemory::Realloc)(Realloc); FMemory::Realloc = decltype(FMemory::Realloc)(Realloc);
UAbilitySystemComponent::GiveAbilityOriginal = decltype(UAbilitySystemComponent::GiveAbilityOriginal)(GiveAbility); UAbilitySystemComponent::GiveAbilityOriginal = decltype(UAbilitySystemComponent::GiveAbilityOriginal)(GiveAbility);
UAbilitySystemComponent::InternalTryActivateAbilityOriginal = decltype(UAbilitySystemComponent::InternalTryActivateAbilityOriginal)(InternalTryActivateAbility); UAbilitySystemComponent::InternalTryActivateAbilityOriginal = decltype(UAbilitySystemComponent::InternalTryActivateAbilityOriginal)(InternalTryActivateAbility);
UAbilitySystemComponent::InternalTryActivateAbilityOriginal2 = decltype(UAbilitySystemComponent::InternalTryActivateAbilityOriginal2)(InternalTryActivateAbility);
ABuildingActor::OnDamageServerOriginal = decltype(ABuildingActor::OnDamageServerOriginal)(OnDamageServer); ABuildingActor::OnDamageServerOriginal = decltype(ABuildingActor::OnDamageServerOriginal)(OnDamageServer);
StaticLoadObjectOriginal = decltype(StaticLoadObjectOriginal)(StaticLoadObject); StaticLoadObjectOriginal = decltype(StaticLoadObjectOriginal)(StaticLoadObject);
@@ -350,6 +353,11 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 70 08 48 89 78 10 55 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 ED").Get()); toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 70 08 48 89 78 10 55 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 ED").Get());
} }
if (Fortnite_Version == 17.50)
{
toNull.push_back(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 49 8B D9 45 8A").Get()); // no reservation in game
}
toNull.push_back(Addresses::ChangeGameSessionId); toNull.push_back(Addresses::ChangeGameSessionId);
return toNull; return toNull;

View File

@@ -41,6 +41,7 @@ namespace Addresses
extern inline uint64 NavSystemCleanUp = 0; extern inline uint64 NavSystemCleanUp = 0;
extern inline uint64 LoadPlayset = 0; extern inline uint64 LoadPlayset = 0;
extern inline uint64 SetZoneToIndex = 0; extern inline uint64 SetZoneToIndex = 0;
extern inline uint64 CompletePickupAnimation = 0;
void SetupVersion(); // Finds Engine Version void SetupVersion(); // Finds Engine Version
void FindAll(); void FindAll();

View File

@@ -80,18 +80,17 @@ DWORD WINAPI Main(LPVOID)
{ {
if (Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr)) if (Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr))
{ {
LOG_INFO(LogHook, "Hooking GetNetMode!");
Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr); Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr);
} }
} }
else else
{ {
Hooking::MinHook::Hook((PVOID)Addresses::KickPlayer, (PVOID)AGameSession::KickPlayerHook, (PVOID*)&AGameSession::KickPlayerOriginal);
Hooking::MinHook::Hook((PVOID)Addresses::DispatchRequest, (PVOID)DispatchRequestHook, (PVOID*)&DispatchRequestOriginal); Hooking::MinHook::Hook((PVOID)Addresses::DispatchRequest, (PVOID)DispatchRequestHook, (PVOID*)&DispatchRequestOriginal);
Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr); Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr);
LOG_INFO(LogHook, "Hooking GetNetMode!");
} }
Hooking::MinHook::Hook((PVOID)Addresses::KickPlayer, (PVOID)AGameSession::KickPlayerHook, (PVOID*)&AGameSession::KickPlayerOriginal);
LOG_INFO(LogDev, "Size: 0x{:x}", sizeof(TMap<FName, void*>)); LOG_INFO(LogDev, "Size: 0x{:x}", sizeof(TMap<FName, void*>));
GetLocalPlayerController()->ProcessEvent(SwitchLevel, &Level); GetLocalPlayerController()->ProcessEvent(SwitchLevel, &Level);
@@ -168,6 +167,10 @@ DWORD WINAPI Main(LPVOID)
AFortPlayerController::ServerAttemptInteractHook, (PVOID*)&AFortPlayerController::ServerAttemptInteractOriginal, false, true); AFortPlayerController::ServerAttemptInteractHook, (PVOID*)&AFortPlayerController::ServerAttemptInteractOriginal, false, true);
} }
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/Engine.PlayerController.ServerAcknowledgePossession"),
AFortPlayerControllerAthena::ServerAcknowledgePossessionHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerAttemptInventoryDrop"),
AFortPlayerController::ServerAttemptInventoryDropHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerExecuteInventoryItem"), Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerExecuteInventoryItem"),
AFortPlayerController::ServerExecuteInventoryItemHook, nullptr, false); AFortPlayerController::ServerExecuteInventoryItemHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerPlayEmoteItem"), Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerPlayEmoteItem"),
@@ -180,8 +183,6 @@ DWORD WINAPI Main(LPVOID)
AFortPlayerController::ServerEditBuildingActorHook, nullptr, false); AFortPlayerController::ServerEditBuildingActorHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerEndEditingBuildingActor"), Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerEndEditingBuildingActor"),
AFortPlayerController::ServerEndEditingBuildingActorHook, nullptr, false); 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"), Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerAthena.ServerPlaySquadQuickChatMessage"),
AFortPlayerControllerAthena::ServerPlaySquadQuickChatMessage, nullptr, false); AFortPlayerControllerAthena::ServerPlaySquadQuickChatMessage, nullptr, false);
@@ -224,6 +225,7 @@ DWORD WINAPI Main(LPVOID)
// Hooking::MinHook::Hook((PVOID)Addresses::CollectGarbage, (PVOID)CollectGarbageHook, nullptr); // 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::PickTeam, (PVOID)AFortGameModeAthena::Athena_PickTeamHook, nullptr);
Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)AFortGameModeAthena::SetZoneToIndexHook, (PVOID*)&AFortGameModeAthena::SetZoneToIndexOriginal); Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)AFortGameModeAthena::SetZoneToIndexHook, (PVOID*)&AFortGameModeAthena::SetZoneToIndexOriginal);
Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal);
srand(time(0)); srand(time(0));

View File

@@ -16,8 +16,8 @@ static inline uintptr_t FindBytes(Memcury::Scanner& Scanner, const std::vector<u
{ {
auto CurrentByte = *(Memcury::ASM::MNEMONIC*)(bGoUp ? Scanner.Get() - i : Scanner.Get() + i); auto CurrentByte = *(Memcury::ASM::MNEMONIC*)(bGoUp ? Scanner.Get() - i : Scanner.Get() + i);
// if (bPrint) if (bPrint)
// std::cout << "CurrentByte: " << std::hex << (int)CurrentByte << '\n'; LOG_INFO(LogFinder, "[{}] CurrentByte: 0x{:x}", i, (int)CurrentByte);
if (CurrentByte == Bytes[0]) if (CurrentByte == Bytes[0])
{ {
@@ -224,6 +224,11 @@ static inline uint64 FindStaticLoadObject()
return Addr.Get(); return Addr.Get();
} }
static inline uint64 FindCompletePickupAnimation()
{
return Memcury::Scanner::FindPattern("40 53 56 48 83 EC 38 4C 89 6C 24 ? 48 8B F1 4C 8B A9 ? ? ? ? 4D 85 ED").Get(); // 14.60
}
static inline uint64 FindNoMCP() static inline uint64 FindNoMCP()
{ {
auto fn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.IsRunningNoMCP"); auto fn = FindObject<UFunction>("/Script/FortniteGame.FortKismetLibrary.IsRunningNoMCP");
@@ -568,22 +573,27 @@ static inline uint64 FindInternalTryActivateAbility()
return FindBytes(Addr, { 0x4C, 0x89, 0x4C }, 1000, 0, true); return FindBytes(Addr, { 0x4C, 0x89, 0x4C }, 1000, 0, true);
} }
static inline uint64 FindGiveAbility()
{
auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!");
auto /* callToGiveAbility */ realGiveAbility = Memcury::Scanner(FindBytes(Addr, { 0xE8 }, 1000, 0)).RelativeOffset(1).Get();
// auto realGiveAbility = ((callToGiveAbility + 1 + 4) + *(int*)(callToGiveAbility + 1));
return realGiveAbility;
}
static inline uint64 FindGiveAbilityAndActivateOnce() static inline uint64 FindGiveAbilityAndActivateOnce()
{ {
if (Engine_Version == 426)
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 49 8B 40 10 49 8B D8 48 8B FA 48 8B F1").Get();
auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500); auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500);
auto res = FindBytes(Addr, { 0x48, 0x89, 0x5C }, 1000, 0, true); auto res = FindBytes(Addr, { 0x48, 0x89, 0x5C }, 1000, 0, true);
return res; return res;
} }
static inline uint64 FindGiveAbility()
{
// auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!"); // has 2 refs for some reason on some versions
// auto realGiveAbility = Memcury::Scanner(FindBytes(Addr, { 0xE8 }, 500, 0, false, 0, true)).RelativeOffset(1).Get();
Memcury::Scanner addr = Memcury::Scanner(FindGiveAbilityAndActivateOnce());
return Memcury::Scanner(FindBytes(addr, { 0xE8 }, 500, 0, false, 1)).RelativeOffset(1).Get();
}
static inline uint64 FindCantBuild() static inline uint64 FindCantBuild()
{ {
auto add = Memcury::Scanner::FindPattern("48 89 5C 24 10 48 89 6C 24 18 48 89 74 24 20 41 56 48 83 EC ? 49 8B E9 4D 8B F0", false).Get(); auto add = Memcury::Scanner::FindPattern("48 89 5C 24 10 48 89 6C 24 18 48 89 74 24 20 41 56 48 83 EC ? 49 8B E9 4D 8B F0", false).Get();

View File

@@ -4,7 +4,7 @@ namespace Globals
{ {
extern inline bool bCreative = false; extern inline bool bCreative = false;
extern inline bool bGoingToPlayEvent = false; extern inline bool bGoingToPlayEvent = false;
extern inline bool bNoMCP = false; extern inline bool bNoMCP = true;
extern inline bool bLateGame = false; extern inline bool bLateGame = false;
extern inline bool bAbilitiesEnabled = true; extern inline bool bAbilitiesEnabled = true;
} }

View File

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

View File

@@ -134,7 +134,7 @@ struct PlaceholderBitfield
uint8_t Eighth : 1; uint8_t Eighth : 1;
}; };
inline uint8_t GetFieldMask(void* Property) inline uint8_t GetFieldMask(void* Property, int additional = 0)
{ {
if (!Property) if (!Property)
return -1; return -1;
@@ -142,11 +142,11 @@ inline uint8_t GetFieldMask(void* Property)
// 3 = sizeof(FieldSize) + sizeof(ByteOffset) + sizeof(ByteMask) // 3 = sizeof(FieldSize) + sizeof(ByteOffset) + sizeof(ByteMask)
if (Engine_Version <= 420) if (Engine_Version <= 420)
return *(uint8_t*)(__int64(Property) + (112 + 3)); return *(uint8_t*)(__int64(Property) + (112 + 3 + additional));
else if (Engine_Version >= 421 && Engine_Version <= 424) else if (Engine_Version >= 421 && Engine_Version <= 424)
return *(uint8_t*)(__int64(Property) + (112 + 3)); return *(uint8_t*)(__int64(Property) + (112 + 3 + additional));
else if (Engine_Version >= 425) else if (Engine_Version >= 425)
return *(uint8_t*)(__int64(Property) + (120 + 3)); return *(uint8_t*)(__int64(Property) + (120 + 3 + additional));
return -1; return -1;
} }