a bit of stuff

toys, ammo in bottom right kinda, fix lootin speeds, being inaccurate, playlist looting kindof, or some things just not working.
This commit is contained in:
Milxnor
2023-04-01 15:54:47 -04:00
parent a03c1cef2b
commit 701d3ad0d0
23 changed files with 437 additions and 149 deletions

View File

@@ -96,46 +96,6 @@ void UAbilitySystemComponent::InternalServerTryActivateAbilityHook(UAbilitySyste
{
// LOG_INFO(LogAbilities, "InternalServerTryActivateAbility. Activated {}", AbilityToActivate->GetName());
}
// bro ignore this next part idk where to put it ok
/* static auto OwnerActorOffset = AbilitySystemComponent->GetOffset("OwnerActor");
auto PlayerState = Cast<AFortPlayerStateAthena>(AbilitySystemComponent->Get<AActor*>(OwnerActorOffset));
if (!PlayerState)
return;
auto Controller = Cast<AFortPlayerController>(PlayerState->GetOwner());
LOG_INFO(LogAbilities, "Owner {}", PlayerState->GetOwner()->GetFullName());
if (!Controller)
return;
auto Pawn = Controller->GetMyFortPawn();
if (!Pawn)
return;
auto CurrentWeapon = Pawn->GetCurrentWeapon();
auto WorldInventory = Controller ? Controller->GetWorldInventory() : nullptr;
if (!WorldInventory || !CurrentWeapon)
return;
auto CurrentWeaponInstance = WorldInventory->FindItemInstance(CurrentWeapon->GetItemEntryGuid());
auto CurrentWeaponReplicatedEntry = WorldInventory->FindReplicatedEntry(CurrentWeapon->GetItemEntryGuid());
static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount");
auto AmmoCount = CurrentWeapon->Get<int>(AmmoCountOffset);
if (CurrentWeaponReplicatedEntry->GetLoadedAmmo() != AmmoCount)
{
CurrentWeaponInstance->GetItemEntry()->GetLoadedAmmo() = AmmoCount;
CurrentWeaponReplicatedEntry->GetLoadedAmmo() = AmmoCount;
WorldInventory->GetItemList().MarkItemDirty(CurrentWeaponInstance->GetItemEntry());
WorldInventory->GetItemList().MarkItemDirty(CurrentWeaponReplicatedEntry);
} */
}
FGameplayAbilitySpecHandle UAbilitySystemComponent::GiveAbilityEasy(UClass* AbilityClass)

View File

@@ -72,6 +72,8 @@ static UObject* GetPlaylistToUse()
// Playlist = FindObject("/MoleGame/Playlists/Playlist_MoleGame.Playlist_MoleGame");
// Playlist = FindObject("/Game/Athena/Playlists/DADBRO/Playlist_DADBRO_Squads_8.Playlist_DADBRO_Squads_8");
// Playlist = FindObject("/Game/Athena/Playlists/Low/Playlist_Low_Solo.Playlist_Low_Solo");
if (Globals::bCreative)
Playlist = FindObject("/Game/Athena/Playlists/Creative/Playlist_PlaygroundV2.Playlist_PlaygroundV2");
@@ -613,7 +615,9 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
auto GameState = Cast<AFortGameStateAthena>(GameMode->GetGameState());
auto Playlist = GameState->GetCurrentPlaylist();
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
auto Playlist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
static int CurrentTeamMembers = 0; // bad
static int Current = 3;

View File

@@ -170,7 +170,7 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
return std::make_pair(NewItemInstances, ModifiedItemInstances);
}
bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count)
bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval)
{
if (bShouldUpdate)
*bShouldUpdate = false;
@@ -188,8 +188,11 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int
auto NewCount = ReplicatedEntry->GetCount() - Count;
if (NewCount > 0)
if (NewCount > 0 || (ItemDefinition->ShouldPersistWhenFinalStackEmpty() && !bForceRemoval))
{
if (ItemDefinition->ShouldPersistWhenFinalStackEmpty())
NewCount = NewCount < 0 ? 0 : NewCount; // min(NewCount, 0) or something i forgot
ItemInstance->GetItemEntry()->GetCount() = NewCount;
ReplicatedEntry->GetCount() = NewCount;
@@ -291,6 +294,28 @@ UFortItem* AFortInventory::FindItemInstance(UFortItemDefinition* ItemDefinition)
return nullptr;
}
void AFortInventory::CorrectLoadedAmmo(const FGuid& Guid, int NewAmmoCount)
{
auto CurrentWeaponInstance = FindItemInstance(Guid);
if (!CurrentWeaponInstance)
return;
auto CurrentWeaponReplicatedEntry = FindReplicatedEntry(Guid);
if (!CurrentWeaponReplicatedEntry)
return;
if (CurrentWeaponReplicatedEntry->GetLoadedAmmo() != NewAmmoCount)
{
CurrentWeaponInstance->GetItemEntry()->GetLoadedAmmo() = NewAmmoCount;
CurrentWeaponReplicatedEntry->GetLoadedAmmo() = NewAmmoCount;
GetItemList().MarkItemDirty(CurrentWeaponInstance->GetItemEntry());
GetItemList().MarkItemDirty(CurrentWeaponReplicatedEntry);
}
}
UFortItem* AFortInventory::FindItemInstance(const FGuid& Guid)
{
auto& ItemInstances = GetItemList().GetItemInstances();

View File

@@ -117,12 +117,14 @@ public:
}
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);
bool RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int Count, bool bForceRemoval = false);
void ModifyCount(UFortItem* ItemInstance, int New, bool bRemove = false, std::pair<FFortItemEntry*, FFortItemEntry*>* outEntries = nullptr, bool bUpdate = true);
UFortItem* GetPickaxeInstance();
UFortItem* FindItemInstance(UFortItemDefinition* ItemDefinition);
void CorrectLoadedAmmo(const FGuid& Guid, int NewAmmoCount);
UFortItem* FindItemInstance(const FGuid& Guid);
FFortItemEntry* FindReplicatedEntry(const FGuid& Guid);
};

View File

@@ -11,8 +11,9 @@ char UFortInventoryInterface::RemoveInventoryItemHook(__int64 a1, FGuid a2, int
int SuperAdditionalOffset = Engine_Version >= 427 ? 16 : 8;
auto ControllerObject = (UObject*)(__int64(a1) - (FortPlayerControllerSuperSize + SuperAdditionalOffset));
LOG_INFO(LogDev, "FortPlayerControllerSuperSize: {}", FortPlayerControllerSuperSize);
LOG_INFO(LogDev, "ControllerObject: {}", ControllerObject->GetFullName());
LOG_INFO(LogDev, "bForceRemoval: {}", (bool)bForceRemoval);
// LOG_INFO(LogDev, "FortPlayerControllerSuperSize: {}", FortPlayerControllerSuperSize);
// LOG_INFO(LogDev, "ControllerObject: {}", ControllerObject->GetFullName());
if (!ControllerObject)
return false;
@@ -28,7 +29,7 @@ char UFortInventoryInterface::RemoveInventoryItemHook(__int64 a1, FGuid a2, int
return false;
bool bShouldUpdate = false;
WorldInventory->RemoveItem(a2, &bShouldUpdate, Count);
WorldInventory->RemoveItem(a2, &bShouldUpdate, Count, bForceRemoval);
if (bShouldUpdate)
WorldInventory->Update();

View File

@@ -312,7 +312,7 @@ void UFortKismetLibrary::K2_RemoveItemFromPlayerByGuidHook(UObject* Context, FFr
return K2_RemoveItemFromPlayerByGuidOriginal(Context, Stack, Ret);
bool bShouldUpdate = false;
WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, AmountToRemove);
WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, AmountToRemove, bForceRemoval);
if (bShouldUpdate)
WorldInventory->Update();
@@ -374,8 +374,9 @@ void UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook(UObject* Context, FFram
if (!WorldInventory)
return K2_RemoveFortItemFromPlayerOriginal(Context, Stack, Ret);
LOG_INFO(LogDev, "bForceRemoval: {}", bForceRemoval);
bool bShouldUpdate = false;
WorldInventory->RemoveItem(Item->GetItemEntry()->GetItemGuid(), &bShouldUpdate, AmountToRemove);
WorldInventory->RemoveItem(Item->GetItemEntry()->GetItemGuid(), &bShouldUpdate, AmountToRemove, bForceRemoval);
if (bShouldUpdate)
WorldInventory->Update();

View File

@@ -7,38 +7,42 @@
#include "GameplayTagContainer.h"
#include "FortGameModeAthena.h"
#include <random>
float GetRandomFloatForLooting(float min, float max)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(min, max);
float random_number = dis(gen);
return random_number;
return UKismetMathLibrary::RandomFloatInRange(min, max);
}
static FFortLootTierData* GetLootTierData2(std::vector<FFortLootTierData*>& LootTierData, bool bPrint)
{
float TotalWeight = 0;
FFortLootTierData* SelectedItem = nullptr;
for (auto Item : LootTierData)
{
TotalWeight += Item->GetWeight();
}
float RandomNumber = TotalWeight * (rand() * 0.000030518509); // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed?
FFortLootTierData* SelectedItem = nullptr;
if (bPrint)
{
std::cout << std::format("TotalWeight: {}\n", TotalWeight);
}
float RandomNumber = GetRandomFloatForLooting(0, 1);
float cumulative_weight = 0.0f;
for (auto Item : LootTierData)
{
if (bPrint)
{
std::cout << std::format("Rand: {} Weight: {}\n", RandomNumber, Item->GetWeight());
}
cumulative_weight += Item->GetWeight() / TotalWeight;
if (RandomNumber <= Item->GetWeight())
{
SelectedItem = Item;
break;
}
RandomNumber -= Item->GetWeight();
}
if (!SelectedItem)
@@ -50,25 +54,25 @@ static FFortLootTierData* GetLootTierData2(std::vector<FFortLootTierData*>& Loot
static FFortLootPackageData* GetLootPackage2(std::vector<FFortLootPackageData*>& LootPackages)
{
float TotalWeight = 0;
FFortLootPackageData* SelectedItem = nullptr;
for (auto Item : LootPackages)
{
TotalWeight += Item->GetWeight();
}
float RandomNumber = TotalWeight * (rand() * 0.000030518509); // UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed?
FFortLootPackageData* SelectedItem = nullptr;
float RandomNumber = GetRandomFloatForLooting(0, 1);
float cumulative_weight = 0.0f;
for (auto Item : LootPackages)
{
cumulative_weight += Item->GetWeight() / TotalWeight;
if (RandomNumber <= Item->GetWeight())
{
SelectedItem = Item;
break;
}
RandomNumber -= Item->GetWeight();
}
if (!SelectedItem)
@@ -79,31 +83,20 @@ static FFortLootPackageData* GetLootPackage2(std::vector<FFortLootPackageData*>&
static FFortLootTierData* GetLootTierData(std::vector<FFortLootTierData*>& LootTierData, bool bPrint)
{
return GetLootTierData2(LootTierData, bPrint);
// return GetLootTierData2(LootTierData, bPrint);
float TotalWeight = 0;
FFortLootTierData* SelectedItem = nullptr;
for (auto Item : LootTierData)
{
TotalWeight += Item->GetWeight();
}
float RandomNumber = UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed?
FFortLootTierData* SelectedItem = nullptr;
if (bPrint)
{
std::cout << std::format("TotalWeight: {}\n", TotalWeight);
}
float RandomNumber = GetRandomFloatForLooting(0, TotalWeight); // is -1 needed?
for (auto Item : LootTierData)
{
if (bPrint)
{
std::cout << std::format("Rand: {} Weight: {}\n", RandomNumber, Item->GetWeight());
}
if (RandomNumber <= Item->GetWeight())
{
SelectedItem = Item;
@@ -121,18 +114,17 @@ static FFortLootTierData* GetLootTierData(std::vector<FFortLootTierData*>& LootT
static FFortLootPackageData* GetLootPackage(std::vector<FFortLootPackageData*>& LootPackages)
{
return GetLootPackage2(LootPackages);
// return GetLootPackage2(LootPackages);
float TotalWeight = 0;
FFortLootPackageData* SelectedItem = nullptr;
for (auto Item : LootPackages)
{
TotalWeight += Item->GetWeight();
}
float RandomNumber = UKismetMathLibrary::RandomFloatInRange(0, TotalWeight); // is -1 needed?
FFortLootPackageData* SelectedItem = nullptr;
float RandomNumber = GetRandomFloatForLooting(0, TotalWeight); // is -1 needed?
for (auto Item : LootPackages)
{
@@ -158,8 +150,6 @@ public:
TSoftObjectPtr<UDataTable> LootPackageData; // 0x28(0x28)(Edit, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic)
};
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recursive)
{
std::vector<LootDrop> LootDrops;
@@ -168,8 +158,9 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
return LootDrops;
auto GameState = ((AFortGameModeAthena*)GetWorld()->GetGameMode())->GetGameStateAthena();
static auto CurrentPlaylistDataOffset = GameState->GetOffset("CurrentPlaylistData", false);
// #define BELUGA
#define BELUGA
#ifndef BELUGA
/* static */ std::vector<UDataTable*> LTDTables;
@@ -183,19 +174,56 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
static bool bHasFoundTables = false;
#endif
auto CurrentPlaylist = GameState->GetCurrentPlaylist();
auto CurrentPlaylist = CurrentPlaylistDataOffset == -1 && Fortnite_Version < 6 ? nullptr : GameState->GetCurrentPlaylist();
if (!bHasFoundTables)
{
bHasFoundTables = true;
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
bool bFoundPlaylistTable = false;
static auto DataTableClass = FindObject<UClass>("/Script/Engine.DataTable");
static auto CompositeDataTableClass = FindObject<UClass>("/Script/Engine.CompositeDataTable");
if (CurrentPlaylist)
{
static auto LootTierDataOffset = CurrentPlaylist->GetOffset("LootTierData");
auto& LootTierDataSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootTierDataOffset);
static auto LootPackagesOffset = CurrentPlaylist->GetOffset("LootPackages");
auto& LootPackagesSoft = CurrentPlaylist->Get<TSoftObjectPtr<UDataTable>>(LootPackagesOffset);
if (LootTierDataSoft.IsValid() && LootPackagesSoft.IsValid())
{
auto LootTierDataStr = LootTierDataSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
auto LootPackagesStr = LootPackagesSoft.SoftObjectPtr.ObjectID.AssetPathName.ToString();
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
auto StrongLootTierData = LootTierDataSoft.Get(LootTierDataTableIsComposite ? CompositeDataTableClass : DataTableClass, true);
auto StrongLootPackage = LootPackagesSoft.Get(LootPackageTableIsComposite ? CompositeDataTableClass : DataTableClass, true);
if (StrongLootTierData && StrongLootPackage)
{
LTDTables.push_back(StrongLootTierData);
LPTables.push_back(StrongLootPackage);
bFoundPlaylistTable = true;
}
}
}
if (!bFoundPlaylistTable)
{
LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
LPTables.push_back(LoadObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
}
// LTDTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootTierData_Client.AthenaLootTierData_Client"));
// LPTables.push_back(LoadObject<UDataTable>(L"/Game/Athena/Playlists/Playground/AthenaLootPackages_Client.AthenaLootPackages_Client"));
#ifdef BELUGA
static auto FortGameFeatureDataClass = FindObject<UClass>("/Script/FortniteGame.FortGameFeatureData");
static auto DataTableClass = FindObject<UClass>("/Script/Engine.DataTable");
static auto CompositeDataTableClass = FindObject<UClass>("/Script/Engine.CompositeDataTable");
if (FortGameFeatureDataClass)
{
@@ -340,15 +368,17 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
}
#endif
/* for (int i = 0; i < LTDTables.size(); i++)
for (int i = 0; i < LTDTables.size(); i++)
{
LTDTables.at(i)->AddToRoot();
LOG_INFO(LogDev, "[{}] LTD {}", i, LTDTables.at(i)->GetFullName());
}
for (int i = 0; i < LPTables.size(); i++)
{
LPTables.at(i)->AddToRoot();
LOG_INFO(LogDev, "[{}] LP {}", i, LPTables.at(i)->GetFullName());
} */
}
}
std::vector<FFortLootTierData*> TierGroupLTDs;
@@ -357,7 +387,10 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
{
auto LTD = LTDTables[p];
if (!LTD)
// if (bPrint)
// LOG_INFO(LogLoot, "LTD: {}", !LTD->IsValidLowLevel() ? "BadRead" : LTD->GetFullName());
if (!LTD->IsValidLowLevel())
continue;
auto& LTDRowMap = LTD->GetRowMap();
@@ -365,9 +398,6 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
// auto TierGroupNameStr = TierGroupName.ToString();
// if (bPrint)
// LOG_INFO(LogLoot, "LTDRowMapNum: {} LTD: {}", LTDRowMapNum, IsBadReadPtr(LTD, 8) ? "BadRead" : LTD->GetFullName());
for (int i = 0; i < LTDRowMapNum; i++)
{
auto& CurrentLTD = LTDRowMap.Pairs.Elements[i].ElementData.Value;
@@ -474,6 +504,10 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
for (int p = 0; p < LPTables.size(); p++)
{
auto LP = LPTables[p];
if (!LP->IsValidLowLevel())
continue;
auto& LPRowMap = LP->GetRowMap();
for (int i = 0; i < LPRowMap.Pairs.Elements.Num(); i++)
@@ -573,6 +607,9 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
{
for (int p = 0; p < LPTables.size(); p++)
{
if (!LPTables[p]->IsValidLowLevel())
continue;
auto& LPRowMap = LPTables[p]->GetRowMap();
for (int j = 0; j < LPRowMap.Pairs.Elements.Num(); j++)

View File

@@ -145,7 +145,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
auto SwappedPickup = SpawnPickup(ItemDefinitionToSwap, PawnLoc, ItemEntryToSwap->GetCount(),
EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::Unset, ItemEntryToSwap->GetLoadedAmmo(), Pawn);
WorldInventory->RemoveItem(CurrentItemGuid, nullptr, ItemEntryToSwap->GetCount());
WorldInventory->RemoveItem(CurrentItemGuid, nullptr, ItemEntryToSwap->GetCount(), true);
bHasSwapped = true;

View File

@@ -489,6 +489,34 @@ void AFortPlayerController::ServerCreateBuildingActorHook(UObject* Context, FFra
return ServerCreateBuildingActorOriginal(Context, Stack, Ret);
}
AActor* AFortPlayerController::SpawnToyInstanceHook(UObject* Context, FFrame* Stack, AActor** Ret)
{
LOG_INFO(LogDev, "SpawnToyInstance!");
auto PlayerController = Cast<AFortPlayerController>(Context);
UClass* ToyClass = nullptr;
FTransform SpawnPosition;
Stack->StepCompiledIn(&ToyClass);
Stack->StepCompiledIn(&SpawnPosition);
SpawnToyInstanceOriginal(Context, Stack, Ret);
if (!ToyClass)
return nullptr;
FActorSpawnParameters SpawnParameters{};
SpawnParameters.Owner = PlayerController;
auto NewToy = GetWorld()->SpawnActor<AActor>(ToyClass, SpawnPosition, SpawnParameters);
static auto ActiveToyInstancesOffset = PlayerController->GetOffset("ActiveToyInstances");
*Ret = NewToy;
return *Ret;
}
void AFortPlayerController::DropSpecificItemHook(UObject* Context, FFrame& Stack, void* Ret)
{
UFortItemDefinition* DropItemDef = nullptr;
@@ -546,7 +574,7 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController
bool bShouldUpdate = false;
if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count))
if (!WorldInventory->RemoveItem(ItemGuid, &bShouldUpdate, Count, true))
return;
if (bShouldUpdate)
@@ -564,6 +592,7 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe
UObject* AbilityToUse = nullptr;
static auto AthenaSprayItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.AthenaSprayItemDefinition");
static auto AthenaToyItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.AthenaToyItemDefinition");
if (EmoteAsset->IsA(AthenaSprayItemDefinitionClass))
{
@@ -571,6 +600,21 @@ void AFortPlayerController::ServerPlayEmoteItemHook(AFortPlayerController* Playe
AbilityToUse = SprayGameplayAbilityDefault;
}
else if (EmoteAsset->IsA(AthenaToyItemDefinitionClass))
{
static auto ToySpawnAbilityOffset = EmoteAsset->GetOffset("ToySpawnAbility");
auto& ToySpawnAbilitySoft = EmoteAsset->Get<TSoftObjectPtr<UClass>>(ToySpawnAbilityOffset);
static auto BGAClass = FindObject<UClass>("/Script/Engine.BlueprintGeneratedClass");
auto ToySpawnAbility = ToySpawnAbilitySoft.Get(BGAClass, true);
if (ToySpawnAbility)
AbilityToUse = ToySpawnAbility->CreateDefaultObject();
}
// LOG_INFO(LogDev, "Before AbilityToUse: {}", AbilityToUse ? AbilityToUse->GetFullName() : "InvalidObject");
if (!AbilityToUse)
{
static auto EmoteGameplayAbilityDefault = FindObject("/Game/Abilities/Emotes/GAB_Emote_Generic.Default__GAB_Emote_Generic_C");
@@ -767,7 +811,7 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
for (auto& Pair : GuidAndCountsToRemove)
{
WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second);
WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true);
}
WorldInventory->Update();

View File

@@ -31,6 +31,7 @@ public:
static inline void (*ServerAttemptInteractOriginal)(UObject* Context, FFrame* Stack, void* Ret);
static inline void (*ServerEditBuildingActorOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static inline void (*DropSpecificItemOriginal)(UObject* Context, FFrame& Stack, void* Ret);
static inline AActor* (*SpawnToyInstanceOriginal)(UObject* Context, FFrame* Stack, AActor** Ret);
void ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot);
@@ -69,6 +70,7 @@ public:
static void ServerAttemptAircraftJumpHook(AFortPlayerController* PC, FRotator ClientRotation);
// static void ServerCreateBuildingActorHook(AFortPlayerController* PlayerController, FCreateBuildingActorData CreateBuildingData);
static void ServerCreateBuildingActorHook(UObject* Context, FFrame* Stack, void* Ret);
static AActor* SpawnToyInstanceHook(UObject* Context, FFrame* Stack, AActor** Ret);
static void DropSpecificItemHook(UObject* Context, FFrame& Stack, void* Ret);
static void ServerDropAllItemsHook(AFortPlayerController* PlayerController, UFortItemDefinition* IgnoreItemDef);

View File

@@ -43,7 +43,7 @@ void AFortPlayerStateAthena::ServerSetInAircraftHook(UObject* Context, FFrame& S
for (auto& Pair : GuidAndCountsToRemove)
{
WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second);
WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true);
}
WorldInventory->Update();

View File

@@ -1,6 +1,35 @@
#include "FortWeapon.h"
#include "FortPlayerPawn.h"
#include "reboot.h"
#include "FortPlayerController.h"
void AFortWeapon::ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret)
{
// I don't know where to put this..
auto Weapon = (AFortWeapon*)Context;
auto Pawn = Cast<AFortPlayerPawn>(Weapon->GetOwner());
// LOG_INFO(LogDev, "Owner: {}", Weapon->GetOwner() ? Weapon->GetOwner()->GetFullName() : "InvalidObject");
if (!Pawn)
return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret);
auto Controller = Cast<AFortPlayerController>(Pawn->GetController());
auto CurrentWeapon = Weapon; // Pawn->GetCurrentWeapon();
auto WorldInventory = Controller ? Controller->GetWorldInventory() : nullptr;
if (!WorldInventory || !CurrentWeapon)
return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret);
static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount");
auto AmmoCount = CurrentWeapon->Get<int>(AmmoCountOffset);
WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount);
return ServerReleaseWeaponAbilityOriginal(Context, Stack, Ret);
}
UClass* AFortWeapon::StaticClass()
{

View File

@@ -1,10 +1,14 @@
#pragma once
#include "Actor.h"
#include "GameplayAbilitySpec.h"
#include "Stack.h"
class AFortWeapon : public AActor
{
public:
static inline void (*ServerReleaseWeaponAbilityOriginal)(UObject* Context, FFrame* Stack, void* Ret);
template <typename T = class UFortWeaponItemDefinition>
T* GetWeaponData()
{
@@ -18,5 +22,7 @@ public:
return Get<FGuid>(ItemEntryGuidOffset);
}
static void ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret);
static UClass* StaticClass();
};

View File

@@ -19,6 +19,13 @@ public:
return ReadBitfieldValue(bDropOnDeathOffset, bDropOnDeathFieldMask);
}
bool ShouldPersistWhenFinalStackEmpty()
{
static auto bPersistInInventoryWhenFinalStackEmptyOffset = GetOffset("bPersistInInventoryWhenFinalStackEmpty");
static auto bPersistInInventoryWhenFinalStackEmptyFieldMask = GetFieldMask(GetProperty("bPersistInInventoryWhenFinalStackEmpty"));
return ReadBitfieldValue(bPersistInInventoryWhenFinalStackEmptyOffset, bPersistInInventoryWhenFinalStackEmptyFieldMask);
}
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortWorldItemDefinition");

View File

@@ -4,6 +4,7 @@
#include "Class.h"
#include "KismetSystemLibrary.h"
#include "UObjectArray.h"
FName* getFNameOfProp(void* Property)
{
@@ -100,3 +101,35 @@ bool UObject::IsA(UClass* otherClass)
static auto Class = FindObject<UClass>("/Script/CoreUObject.Object");
return Class;
} */
void UObject::AddToRoot()
{
auto Item = GetItemByIndex(InternalIndex);
if (!Item)
{
LOG_INFO(LogDev, "Invalid item");
return;
}
Item->SetRootSet();
}
bool UObject::IsValidLowLevel()
{
if (this == nullptr)
{
// UE_LOG(LogUObjectBase, Warning, TEXT("NULL object"));
return false;
}
if (IsBadReadPtr(this, 8)) // needed?
{
return false;
}
if (!ClassPrivate)
{
// UE_LOG(LogUObjectBase, Warning, TEXT("Object is not registered"));
return false;
}
return ChunkedObjects ? ChunkedObjects->IsValid(this) : UnchunkedObjects ? UnchunkedObjects->IsValid(this) : false;
}

View File

@@ -88,5 +88,8 @@ public:
template <typename T = UObject*>
T* GetPtr(const std::string& ChildName) { return GetPtr<T>(GetOffset(ChildName)); }
void AddToRoot();
bool IsValidLowLevel();
// static class UClass* StaticClass();
};

View File

@@ -1,5 +1,7 @@
#pragma once
#include "inc.h"
enum EObjectFlags
{
RF_NoFlags = 0x00000000,
@@ -33,3 +35,31 @@ enum EObjectFlags
RF_HasExternalPackage = 0x10000000,
RF_AllocatedInSharedPage = 0x80000000,
};
enum class EInternalObjectFlags : int
{
None = 0,
LoaderImport = 1 << 20, ///< Object is ready to be imported by another package during loading
Garbage = 1 << 21, ///< Garbage from logical point of view and should not be referenced. This flag is mirrored in EObjectFlags as RF_Garbage for performance
PersistentGarbage = 1 << 22, ///< Same as above but referenced through a persistent reference so it can't be GC'd
ReachableInCluster = 1 << 23, ///< External reference to object in cluster exists
ClusterRoot = 1 << 24, ///< Root of a cluster
Native = 1 << 25, ///< Native (UClass only).
Async = 1 << 26, ///< Object exists only on a different thread than the game thread.
AsyncLoading = 1 << 27, ///< Object is being asynchronously loaded.
Unreachable = 1 << 28, ///< Object is not reachable on the object graph.
// PendingKill UE_DEPRECATED(5.0, "PendingKill flag should no longer be used. Use Garbage flag instead.") = 1 << 29, ///< Objects that are pending destruction (invalid for gameplay but valid objects). This flag is mirrored in EObjectFlags as RF_PendingKill for performance
RootSet = 1 << 30, ///< Object will not be garbage collected, even if unreferenced.
PendingConstruction = 1 << 31 ///< Object didn't have its class constructor called yet (only the UObjectBase one to initialize its most basic members)
/* GarbageCollectionKeepFlags = Native | Async | AsyncLoading | LoaderImport,
PRAGMA_DISABLE_DEPRECATION_WARNINGS
MirroredFlags = Garbage | PendingKill, /// Flags mirrored in EObjectFlags
//~ Make sure this is up to date!
AllFlags = LoaderImport | Garbage | PersistentGarbage | ReachableInCluster | ClusterRoot | Native | Async | AsyncLoading | Unreachable | PendingKill | RootSet | PendingConstruction
PRAGMA_ENABLE_DEPRECATION_WARNINGS */
};
ENUM_CLASS_FLAGS(EInternalObjectFlags)

View File

@@ -19,6 +19,19 @@ struct TSoftObjectPtr
public:
FSoftObjectPtr SoftObjectPtr;
bool IsValid()
{
if (Engine_Version <= 416)
{
auto& AssetPtr = *(TAssetPtr<T>*)this;
return true;
}
else
{
return SoftObjectPtr.ObjectID.AssetPathName.ComparisonIndex.Value;
}
}
T* Get(UClass* ClassToLoad = nullptr, bool bTryToLoad = false)
{
if (Engine_Version <= 416)

View File

@@ -3,6 +3,7 @@
#include "inc.h"
#include "Object.h"
#include "ObjectMacros.h"
struct FUObjectItem
{
@@ -10,6 +11,24 @@ struct FUObjectItem
int32 Flags;
int32 ClusterRootIndex;
int32 SerialNumber;
FORCEINLINE void SetFlag(EInternalObjectFlags FlagToSet)
{
// static_assert(sizeof(int32) == sizeof(Flags), "Flags must be 32-bit for atomics.");
int32 StartValue = int32(Flags);
if ((StartValue & int32(FlagToSet)) == int32(FlagToSet))
{
return;
}
int32 NewValue = StartValue | int32(FlagToSet);
}
FORCEINLINE void SetRootSet()
{
SetFlag(EInternalObjectFlags::RootSet);
}
};
class FFixedUObjectArray
@@ -28,6 +47,34 @@ public:
return &Objects[Index];
}
bool IsValid(UObject* Object)
{
int32 Index = Object->InternalIndex;
if (Index == -1)
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Object is not in global object array"));
return false;
}
if (!IsValidIndex(Index))
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Invalid object index %i"), Index);
return false;
}
FUObjectItem* Slot = GetItemByIndex(Index);
if (!Slot || Slot->Object == nullptr)
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Empty slot"));
return false;
}
if (Slot->Object != Object)
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Other object in slot"));
return false;
}
return true;
}
FORCEINLINE UObject* GetObjectByIndex(int32 Index)
{
if (auto Item = GetItemByIndex(Index))
@@ -69,6 +116,34 @@ public:
return Chunk + WithinChunkIndex;
}
bool IsValid(UObject* Object)
{
int32 Index = Object->InternalIndex;
if (Index == -1)
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Object is not in global object array"));
return false;
}
if (!IsValidIndex(Index))
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Invalid object index %i"), Index);
return false;
}
FUObjectItem* Slot = GetItemByIndex(Index);
if (!Slot || Slot->Object == nullptr)
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Empty slot"));
return false;
}
if (Slot->Object != Object)
{
// UE_LOG(LogUObjectArray, Warning, TEXT("Other object in slot"));
return false;
}
return true;
}
FORCEINLINE UObject* GetObjectByIndex(int32 Index)
{
if (auto Item = GetItemByIndex(Index))
@@ -85,3 +160,8 @@ FORCEINLINE UObject* GetObjectByIndex(int32 Index)
{
return ChunkedObjects ? ChunkedObjects->GetObjectByIndex(Index) : UnchunkedObjects->GetObjectByIndex(Index);
}
FORCEINLINE FUObjectItem* GetItemByIndex(int32 Index)
{
return ChunkedObjects ? ChunkedObjects->GetItemByIndex(Index) : UnchunkedObjects->GetItemByIndex(Index);
}

View File

@@ -393,12 +393,6 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
toNull.push_back(Memcury::Scanner::FindPattern("40 57 41 56 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F1 74 3A 80 3D ? ? ? ? ? 0F 82").Get()); // collect garbage
}
if (Engine_Version == 500)
{
// toNull.push_back(Memcury::Scanner::FindPattern("").Get()); // collectgarbage
// toNull.push_back(Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 48 8B FA 48 8B D9 48 85 D2 0F 84 ? ? ? ? 8B").Get()); // idk lmfao
}
if (Fortnite_Version == 12.61)
{
// toNull.push_back(Memcury::Scanner::FindPattern("48 89 4C 24 ? 55 56 57 41 56 48 81 EC ? ? ? ? 4C 8B B1 ? ? ? ? 33 F6 4C 89 B4 24 ? ? ? ? 48 8B").Get()); // fritter crash
@@ -409,9 +403,9 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
toNull.push_back(Memcury::Scanner::FindPattern("40 55 57 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 80 3D ? ? ? ? ? 0F B6 FA 44 8B F9 74 3B 80 3D ? ? ? ? ? 0F").Get());
}
if (Fortnite_Version == 17.30)
if (std::floor(Fortnite_Version) == 17)
{
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()); // collectgarbage
}
if (Fortnite_Version == 17.50)
@@ -419,6 +413,12 @@ std::vector<uint64> Addresses::GetFunctionsToNull()
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
}
if (Engine_Version == 500)
{
// toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 68 A1 48 81 EC ? ? ? ? 45 33 F6 0F 29 70 A8 44 38 35").Get()); // zone
// toNull.push_back(Memcury::Scanner::FindPattern("48 8B C4 48 89 58 08 55 56 57 41 54 41 55 41 56 41 57 48 8D 68 A8 48 81 EC ? ? ? ? 45 33 FF").Get()); // Garbage collection
}
toNull.push_back(Addresses::ChangeGameSessionId);
return toNull;

View File

@@ -76,13 +76,3 @@ namespace Offsets
void FindAll();
void Print();
}
#define ENUM_CLASS_FLAGS(Enum) \
inline Enum& operator|=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
inline Enum& operator&=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
inline Enum& operator^=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator| (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator& (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator^ (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
inline constexpr bool operator! (Enum E) { return !(__underlying_type(Enum))E; } \
inline constexpr Enum operator~ (Enum E) { return (Enum)~(__underlying_type(Enum))E; }

View File

@@ -99,14 +99,17 @@ DWORD WINAPI Main(LPVOID)
static auto FortPlayerStateAthenaDefault = FindObject<AFortPlayerStateAthena>(L"/Script/FortniteGame.Default__FortPlayerStateAthena");
static auto FortKismetLibraryDefault = FindObject<UFortKismetLibrary>(L"/Script/FortniteGame.Default__FortKismetLibrary");
static auto AthenaMarkerComponentDefault = FindObject<UAthenaMarkerComponent>(L"/Script/FortniteGame.Default__AthenaMarkerComponent");
static auto FortWeaponDefault = FindObject<AFortWeapon>(L"/Script/FortniteGame.Default__FortWeapon");
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogBuilding VeryVerbose", nullptr);
// UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFortUIDirector NoLogging", nullptr);
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogAbilitySystem VeryVerbose", nullptr);
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogFort VeryVerbose", nullptr);
UKismetSystemLibrary::ExecuteConsoleCommand(GetWorld(), L"log LogGameMode VeryVerbose", nullptr);
if (Globals::bNoMCP)
{
if (Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr))
if (Fortnite_Version > 2.5 ? Hooking::MinHook::Hook((PVOID)Addresses::NoMCP, (PVOID)NoMCPHook, nullptr) : true)
{
Hooking::MinHook::Hook((PVOID)Addresses::GetNetMode, (PVOID)GetNetModeHook, nullptr);
}
@@ -263,6 +266,9 @@ DWORD WINAPI Main(LPVOID)
nullptr, false);
}
Hooking::MinHook::Hook(FortWeaponDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"),
AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerDropAllItems"),
AFortPlayerController::ServerDropAllItemsHook, nullptr, false);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.ServerAttemptInventoryDrop"),
@@ -325,6 +331,8 @@ DWORD WINAPI Main(LPVOID)
// TODO Add RemoveItemFromInventoryOwner
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.SpawnToyInstance"),
AFortPlayerController::SpawnToyInstanceHook, (PVOID*)&AFortPlayerController::SpawnToyInstanceOriginal, false, true);
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerController.DropSpecificItem"),
AFortPlayerController::DropSpecificItemHook, (PVOID*)&AFortPlayerController::DropSpecificItemOriginal, false, true);
@@ -438,33 +446,36 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal);
Hooking::MinHook::Hook((PVOID)Addresses::CanActivateAbility, ReturnTrueHook); // ahhh wtf
auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)FindFunctionCall(L"ServerRemoveInventoryItem",
Fortnite_Version >= 16 ? std::vector<uint8_t>{ 0x48, 0x8B, 0xC4 } : std::vector<uint8_t>{ 0x48, 0x89, 0x5C }), 0, true);
LOG_INFO(LogDev, "ServerRemoveInventoryItemFunctionCallRef: 0x{:x}", ServerRemoveInventoryItemFunctionCallRef.Get() - __int64(GetModuleHandleW(0)));
uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0;
for (int i = 0; i < 400; i++)
if (Fortnite_Version >= 2.5)
{
if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0x5C)
auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)FindFunctionCall(L"ServerRemoveInventoryItem",
Fortnite_Version >= 16 ? std::vector<uint8_t>{ 0x48, 0x8B, 0xC4 } : std::vector<uint8_t>{ 0x48, 0x89, 0x5C }), 0, true);
LOG_INFO(LogDev, "ServerRemoveInventoryItemFunctionCallRef: 0x{:x}", ServerRemoveInventoryItemFunctionCallRef.Get() - __int64(GetModuleHandleW(0)));
uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0;
for (int i = 0; i < 400; i++)
{
ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i;
break;
if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0x5C)
{
ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i;
break;
}
if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x83 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0xEC)
{
ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i;
break;
}
}
if (*(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i) == 0x48 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 1) == 0x83 && *(uint8_t*)(uint8_t*)(ServerRemoveInventoryItemFunctionCallRef.Get() - i + 2) == 0xEC)
{
ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = ServerRemoveInventoryItemFunctionCallRef.Get() - i;
break;
}
Hooking::MinHook::Hook(
Memcury::Scanner(ServerRemoveInventoryItemFunctionCallBeginFunctionAddr).GetAs<PVOID>(),
UFortInventoryInterface::RemoveInventoryItemHook
);
}
Hooking::MinHook::Hook(
Memcury::Scanner(ServerRemoveInventoryItemFunctionCallBeginFunctionAddr).GetAs<PVOID>(),
UFortInventoryInterface::RemoveInventoryItemHook
);
if (Fortnite_Version >= 13)
Hooking::MinHook::Hook((PVOID)Addresses::SetZoneToIndex, (PVOID)SetZoneToIndexHook, (PVOID*)&SetZoneToIndexOriginal);

View File

@@ -17,3 +17,13 @@ extern inline double Fortnite_Version = 0; // For example, 4.1, 6.21, etc. // Pr
#define MS_ALIGN(n) __declspec(align(n))
#define FORCENOINLINE __declspec(noinline)
#define ENUM_CLASS_FLAGS(Enum) \
inline Enum& operator|=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
inline Enum& operator&=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
inline Enum& operator^=(Enum& Lhs, Enum Rhs) { return Lhs = (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator| (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs | (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator& (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs & (__underlying_type(Enum))Rhs); } \
inline constexpr Enum operator^ (Enum Lhs, Enum Rhs) { return (Enum)((__underlying_type(Enum))Lhs ^ (__underlying_type(Enum))Rhs); } \
inline constexpr bool operator! (Enum E) { return !(__underlying_type(Enum))E; } \
inline constexpr Enum operator~ (Enum E) { return (Enum)~(__underlying_type(Enum))E; }