mirror of
https://github.com/Milxnor/Project-Reboot-3.0.git
synced 2026-01-13 02:42:22 +01:00
great
pickup combining, almost finish shadow stones, fix some bugs with gadgets, clean up some code.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "Transform.h"
|
||||
|
||||
#include "reboot.h"
|
||||
#include "GameplayStatics.h"
|
||||
|
||||
bool AActor::HasAuthority()
|
||||
{
|
||||
@@ -210,6 +211,40 @@ void AActor::GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation)
|
||||
*OutRotation = AActor_GetActorEyesViewPoint_Params.OutRotation;
|
||||
}
|
||||
|
||||
AActor* AActor::GetClosestActor(UClass* ActorClass, float DistMax, std::function<bool(AActor*)> AdditionalCheck)
|
||||
{
|
||||
float TargetDist = FLT_MAX;
|
||||
AActor* TargetActor = nullptr;
|
||||
|
||||
TArray<AActor*> AllActors = UGameplayStatics::GetAllActorsOfClass(GetWorld(), ActorClass);
|
||||
auto ActorLocation = GetActorLocation();
|
||||
|
||||
for (int i = 0; i < AllActors.Num(); i++)
|
||||
{
|
||||
auto Actor = AllActors.at(i);
|
||||
|
||||
if (!Actor || Actor == this)
|
||||
continue;
|
||||
|
||||
if (!AdditionalCheck(Actor))
|
||||
continue;
|
||||
|
||||
auto CurrentActorLocation = Actor->GetActorLocation();
|
||||
|
||||
int Dist = float(sqrtf(powf(CurrentActorLocation.X - ActorLocation.X, 2.0) + powf(CurrentActorLocation.Y - ActorLocation.Y, 2.0) + powf(CurrentActorLocation.Z - ActorLocation.Z, 2.0))) / 100.f;
|
||||
|
||||
if (Dist <= DistMax && Dist < TargetDist)
|
||||
{
|
||||
TargetDist = Dist;
|
||||
TargetActor = Actor;
|
||||
}
|
||||
}
|
||||
|
||||
AllActors.Free();
|
||||
|
||||
return TargetActor;
|
||||
}
|
||||
|
||||
bool AActor::IsAlwaysRelevant()
|
||||
{
|
||||
static auto bAlwaysRelevantOffset = GetOffset("bAlwaysRelevant");
|
||||
|
||||
@@ -49,7 +49,8 @@ public:
|
||||
float& GetMinNetUpdateFrequency();
|
||||
const AActor* GetNetOwner() const;
|
||||
void GetActorEyesViewPoint(FVector* OutLocation, FRotator* OutRotation) const;
|
||||
|
||||
AActor* GetClosestActor(UClass* ActorClass, float DistMax, std::function<bool(AActor*)> AdditionalCheck = [&](AActor*) { return true; });
|
||||
|
||||
bool IsRelevancyOwnerFor(const AActor* ReplicatedActor, const AActor* ActorOwner, const AActor* ConnectionActor) const
|
||||
{
|
||||
// we should call virtual function but eh
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "reboot.h"
|
||||
|
||||
class UAttributeSet : public UObject
|
||||
{
|
||||
public:
|
||||
};
|
||||
|
||||
struct FGameplayAttribute
|
||||
{
|
||||
FString AttributeName;
|
||||
void* Attribute;
|
||||
UStruct* AttributeOwner;
|
||||
};
|
||||
@@ -48,7 +48,7 @@ public:
|
||||
return this->GetPtr<TArray<FGameplayEffectApplicationInfoHard>>(GrantedGameplayEffectsOffset);
|
||||
}
|
||||
|
||||
void ApplyGrantedGameplayAffectsToAbilitySystem(UAbilitySystemComponent* AbilitySystemComponent)
|
||||
void ApplyGrantedGameplayAffectsToAbilitySystem(UAbilitySystemComponent* AbilitySystemComponent) // i dont think this is proper
|
||||
{
|
||||
if (!FGameplayEffectApplicationInfoHard::GetStruct())
|
||||
return;
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "SoftObjectPath.h"
|
||||
#include "FortPlayerStateAthena.h"
|
||||
#include "addresses.h"
|
||||
#include "FortPlayerPawnAthena.h"
|
||||
#include "FortPlayerControllerAthena.h"
|
||||
|
||||
void UFortGadgetItemDefinition::UnequipGadgetData(AFortPlayerController* PlayerController, UFortItem* Item)
|
||||
{
|
||||
@@ -10,64 +12,21 @@ void UFortGadgetItemDefinition::UnequipGadgetData(AFortPlayerController* PlayerC
|
||||
__int64 (*RemoveGadgetDataOriginal)(UFortGadgetItemDefinition* a1, __int64 a2, UFortItem* a3) = decltype(RemoveGadgetDataOriginal)(Addresses::RemoveGadgetData);
|
||||
RemoveGadgetDataOriginal(this, __int64(PlayerController->GetInterfaceAddress(FortInventoryOwnerInterfaceClass)), Item);
|
||||
|
||||
/* auto Pawn = PlayerController->GetMyFortPawn();
|
||||
|
||||
if (Pawn)
|
||||
if (auto CosmeticLoadoutPC = PlayerController->GetCosmeticLoadout())
|
||||
{
|
||||
static auto OriginalFootstepBankOffset = Pawn->GetOffset("OriginalFootstepBank");
|
||||
static auto FootstepBankOverrideOffset = Pawn->GetOffset("FootstepBankOverride");
|
||||
Pawn->Get(FootstepBankOverrideOffset) = Pawn->Get(OriginalFootstepBankOffset);
|
||||
|
||||
static auto AnimBPOverrideOffset = Pawn->GetOffset("AnimBPOverride");
|
||||
static auto OriginalAnimBPOffset = Pawn->GetOffset("OriginalAnimBP");
|
||||
Pawn->Get(AnimBPOverrideOffset) = Pawn->Get(OriginalAnimBPOffset);
|
||||
}
|
||||
|
||||
static auto AbilitySetOffset = this->GetOffset("AbilitySet");
|
||||
auto& AbilitySetSoft = this->Get<TSoftObjectPtr<UFortAbilitySet>>(AbilitySetOffset);
|
||||
|
||||
auto StrongAbilitySet = AbilitySetSoft.Get(UFortAbilitySet::StaticClass(), true);
|
||||
|
||||
if (StrongAbilitySet)
|
||||
{
|
||||
auto PlayerState = (AFortPlayerStateAthena*)PlayerController->GetPlayerState();
|
||||
auto ASC = PlayerState ? PlayerState->GetAbilitySystemComponent() : nullptr;
|
||||
|
||||
if (ASC)
|
||||
if (auto CharacterToApply = CosmeticLoadoutPC->GetCharacter())
|
||||
{
|
||||
if (FGameplayEffectApplicationInfoHard::GetStruct())
|
||||
{
|
||||
auto AS_GrantedGameplayEffects = StrongAbilitySet->GetGrantedGameplayEffects();
|
||||
|
||||
if (AS_GrantedGameplayEffects)
|
||||
{
|
||||
for (int i = 0; i < AS_GrantedGameplayEffects->Num(); i++)
|
||||
{
|
||||
ASC->RemoveActiveGameplayEffectBySourceEffect(AS_GrantedGameplayEffects->at(i, FGameplayEffectApplicationInfoHard::GetStructSize()).GameplayEffect, ASC, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto& ActivatableAbilitiesItems = ASC->GetActivatableAbilities()->GetItems();
|
||||
auto AS_GameplayAbilities = StrongAbilitySet->GetGameplayAbilities();
|
||||
|
||||
for (int j = 0; j < AS_GameplayAbilities->Num(); j++)
|
||||
{
|
||||
auto CurrentDefaultAbility = AS_GameplayAbilities->at(j)->CreateDefaultObject();
|
||||
|
||||
for (int i = 0; i < ActivatableAbilitiesItems.Num(); i++)
|
||||
{
|
||||
auto Spec = ActivatableAbilitiesItems.AtPtr(i, FGameplayAbilitySpec::GetStructSize());
|
||||
|
||||
if (Spec->GetAbility() == CurrentDefaultAbility)
|
||||
{
|
||||
ASC->ClearAbility(Spec->GetHandle());
|
||||
}
|
||||
}
|
||||
}
|
||||
ApplyCID(Cast<AFortPlayerPawn>(PlayerController->GetMyFortPawn()), CharacterToApply); // idk why no automatic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PlayerController->ApplyCosmeticLoadout();
|
||||
*/
|
||||
void UFortGadgetItemDefinition::UpdateTrackedAttributesHook(UFortGadgetItemDefinition* GadgetItemDefinition)
|
||||
{
|
||||
// LOG_INFO(LogDev, "UpdateTrackedAttributesHook Return: 0x{:x}", __int64(_ReturnAddress()) - __int64(GetModuleHandleW(0)));
|
||||
|
||||
if (GadgetItemDefinition->ShouldDestroyGadgetWhenTrackedAttributesIsZero())
|
||||
{
|
||||
// PlayerState->MulticastTriggerOnGadgetTrackedAttributeDestroyedFX
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,17 @@ public:
|
||||
return ReadBitfieldValue(bDropAllOnEquipOffset, bDropAllOnEquipFieldMask);
|
||||
}
|
||||
|
||||
bool ShouldDestroyGadgetWhenTrackedAttributesIsZero()
|
||||
{
|
||||
static auto bDestroyGadgetWhenTrackedAttributesIsZeroOffset = GetOffset("bDestroyGadgetWhenTrackedAttributesIsZero", false);
|
||||
|
||||
if (bDestroyGadgetWhenTrackedAttributesIsZeroOffset == -1)
|
||||
return false;
|
||||
|
||||
static auto bDestroyGadgetWhenTrackedAttributesIsZeroFieldMask = GetFieldMask(GetProperty("bDestroyGadgetWhenTrackedAttributesIsZero"));
|
||||
return ReadBitfieldValue(bDestroyGadgetWhenTrackedAttributesIsZeroOffset, bDestroyGadgetWhenTrackedAttributesIsZeroFieldMask);
|
||||
}
|
||||
|
||||
UAttributeSet* GetAttributeSet()
|
||||
{
|
||||
static auto AttributeSetOffset = this->GetOffset("AttributeSet", false);
|
||||
@@ -34,6 +45,8 @@ public:
|
||||
|
||||
void UnequipGadgetData(AFortPlayerController* PlayerController, UFortItem* Item);
|
||||
|
||||
static void UpdateTrackedAttributesHook(UFortGadgetItemDefinition* GadgetItemDefinition);
|
||||
|
||||
static UClass* StaticClass()
|
||||
{
|
||||
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortGadgetItemDefinition");
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
#include "FortGameplayAbilityAthena_PeriodicItemGrant.h"
|
||||
|
||||
void UFortGameplayAbilityAthena_PeriodicItemGrant::StopItemAwardTimersHook(UObject* Context, FFrame& Stack, void* Ret)
|
||||
{
|
||||
// (Milxnor) We need clear all the timers in ActiveTimers.
|
||||
|
||||
return StopItemAwardTimersOriginal(Context, Stack, Ret);
|
||||
}
|
||||
|
||||
void UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersHook(UObject* Context, FFrame& Stack, void* Ret)
|
||||
{
|
||||
LOG_INFO(LogDev, "StartItemAwardTimersHook!");
|
||||
// (Milxnor) We need to loop through ItemsToGrant, and then using the Pair.Value we set a timer and then the Pair.Key for the item to grant, then we add the timer to ActiveTimers.
|
||||
|
||||
return StartItemAwardTimersOriginal(Context, Stack, Ret);
|
||||
}
|
||||
@@ -38,6 +38,7 @@ struct FActiveItemGrantInfo
|
||||
class UFortGameplayAbilityAthena_PeriodicItemGrant : public UObject // UFortGameplayAbility
|
||||
{
|
||||
public:
|
||||
static inline void (*StopItemAwardTimersOriginal)(UObject* Context, FFrame& Stack, void* Ret);
|
||||
static inline void (*StartItemAwardTimersOriginal)(UObject* Context, FFrame& Stack, void* Ret);
|
||||
|
||||
TMap<FActiveItemGrantInfo, FScalableFloat>& GetItemsToGrant()
|
||||
@@ -52,5 +53,6 @@ public:
|
||||
return Get<TArray<FTimerHandle>>(ActiveTimersOffset);
|
||||
}
|
||||
|
||||
static void StopItemAwardTimersHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||
static void StartItemAwardTimersHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||
};
|
||||
@@ -146,7 +146,8 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
||||
if (FortPlayerController && WorldItemDefinition->IsValidLowLevel())
|
||||
{
|
||||
bool AreGadgetsEnabled = Addresses::ApplyGadgetData && Addresses::RemoveGadgetData && Globals::bEnableAGIDs;
|
||||
|
||||
bool bWasGadget = false;
|
||||
|
||||
if (AreGadgetsEnabled)
|
||||
{
|
||||
if (auto GadgetItemDefinition = Cast<UFortGadgetItemDefinition>(WorldItemDefinition))
|
||||
@@ -156,10 +157,14 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
||||
FortPlayerController->DropAllItems({ GadgetItemDefinition });
|
||||
}
|
||||
|
||||
bool (*ApplyGadgetData)(UFortGadgetItemDefinition * a1, __int64 a2, UFortItem* a3, unsigned __int8 a4) = decltype(ApplyGadgetData)(Addresses::ApplyGadgetData);
|
||||
bool (*ApplyGadgetData)(UFortGadgetItemDefinition* a1, __int64 a2, UFortItem* a3, unsigned __int8 a4) = decltype(ApplyGadgetData)(Addresses::ApplyGadgetData);
|
||||
static auto FortInventoryOwnerInterfaceClass = FindObject<UClass>("/Script/FortniteGame.FortInventoryOwnerInterface");
|
||||
auto Interface = __int64(FortPlayerController->GetInterfaceAddress(FortInventoryOwnerInterfaceClass));
|
||||
LOG_INFO(LogDev, "Res: {}", ApplyGadgetData(GadgetItemDefinition, Interface, NewItemInstance, true));
|
||||
bool idktbh = true; // Something to do with durability
|
||||
|
||||
bool DidApplyingGadgetSucceed = ApplyGadgetData(GadgetItemDefinition, Interface, NewItemInstance, idktbh);
|
||||
LOG_INFO(LogDev, "DidApplyingGadgetSucceed: {}", DidApplyingGadgetSucceed);
|
||||
bWasGadget = true;
|
||||
|
||||
if (Fortnite_Version < 7)
|
||||
{
|
||||
@@ -168,6 +173,7 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
||||
if (PickaxeInstance)
|
||||
{
|
||||
RemoveItem(PickaxeInstance->GetItemEntry()->GetItemGuid(), nullptr, PickaxeInstance->GetItemEntry()->GetCount(), true);
|
||||
Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,6 +183,15 @@ std::pair<std::vector<UFortItem*>, std::vector<UFortItem*>> AFortInventory::AddI
|
||||
{
|
||||
LOG_INFO(LogDev, "Force focus {}", ItemDefinition->GetFullName());
|
||||
FortPlayerController->ServerExecuteInventoryItemHook(FortPlayerController, NewItemInstance->GetItemEntry()->GetItemGuid());
|
||||
FortPlayerController->ClientEquipItem(NewItemInstance->GetItemEntry()->GetItemGuid(), true);
|
||||
}
|
||||
|
||||
if (bWasGadget)
|
||||
{
|
||||
if (Fortnite_Version < 7)
|
||||
{
|
||||
// FortPlayerController->AddPickaxeToInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -325,32 +340,26 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int
|
||||
|
||||
auto FortPlayerController = Cast<AFortPlayerController>(GetOwner());
|
||||
|
||||
bool bWasGadget = false;
|
||||
|
||||
for (int i = 0; i < ItemInstances.Num(); i++)
|
||||
{
|
||||
if (ItemInstances.at(i)->GetItemEntry()->GetItemGuid() == ItemGuid)
|
||||
{
|
||||
bool AreGadgetsEnabled = Addresses::ApplyGadgetData && Addresses::RemoveGadgetData && Globals::bEnableAGIDs;
|
||||
|
||||
if (AreGadgetsEnabled)
|
||||
if (FortPlayerController && AreGadgetsEnabled)
|
||||
{
|
||||
if (auto GadgetItemDefinition = Cast<UFortGadgetItemDefinition>(ItemDefinition))
|
||||
{
|
||||
LOG_INFO(LogDev, "Unequipping Gadget!");
|
||||
GadgetItemDefinition->UnequipGadgetData(FortPlayerController, ItemInstances.at(i));
|
||||
|
||||
bWasGadget = true;
|
||||
|
||||
if (Fortnite_Version < 7)
|
||||
{
|
||||
auto CosmeticLoadout = FortPlayerController->GetCosmeticLoadout();
|
||||
// LOG_INFO(LogDev, "CosmeticLoadout: {}", __int64(CosmeticLoadout));
|
||||
auto CosmeticLoadoutPickaxe = CosmeticLoadout ? CosmeticLoadout->GetPickaxe() : nullptr;
|
||||
// LOG_INFO(LogDev, "CosmeticLoadoutPickaxe: {}", __int64(CosmeticLoadoutPickaxe));
|
||||
// LOG_INFO(LogDev, "CosmeticLoadoutPickaxe Name: {}", CosmeticLoadoutPickaxe ? CosmeticLoadoutPickaxe->GetFullName() : "InvalidObject");
|
||||
static auto WeaponDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.AthenaPickaxeItemDefinition", "WeaponDefinition");
|
||||
|
||||
auto PickaxeDefinition = CosmeticLoadoutPickaxe ? CosmeticLoadoutPickaxe->Get<UFortItemDefinition*>(WeaponDefinitionOffset)
|
||||
: FindObject<UFortItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01");
|
||||
|
||||
this->AddItem(PickaxeDefinition, nullptr);
|
||||
FortPlayerController->AddPickaxeToInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,27 +394,6 @@ void UFortKismetLibrary::K2_GiveBuildingResourceHook(UObject* Context, FFrame& S
|
||||
return K2_GiveBuildingResourceOriginal(Context, Stack, Ret);
|
||||
}
|
||||
|
||||
int UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook1(AFortPlayerController* PlayerController, UFortItem* Item, int AmountToRemove, bool bForceRemoval)
|
||||
{
|
||||
LOG_INFO(LogDev, "K2_RemoveFortItemFromPlayerHookNative!");
|
||||
|
||||
if (!PlayerController || !Item)
|
||||
return 0;
|
||||
|
||||
auto WorldInventory = PlayerController->GetWorldInventory();
|
||||
|
||||
if (!WorldInventory)
|
||||
return 0;
|
||||
|
||||
bool bShouldUpdate = false;
|
||||
WorldInventory->RemoveItem(Item->GetItemEntry()->GetItemGuid(), &bShouldUpdate, AmountToRemove, bForceRemoval);
|
||||
|
||||
if (bShouldUpdate)
|
||||
WorldInventory->Update();
|
||||
|
||||
return 1; // idk probably how much we removed
|
||||
}
|
||||
|
||||
void UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret)
|
||||
{
|
||||
AFortPlayerController* PlayerController = nullptr; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
|
||||
@@ -95,7 +95,6 @@ public:
|
||||
static void K2_RemoveItemFromPlayerByGuidHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||
static void K2_GiveItemToPlayerHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||
static void K2_GiveBuildingResourceHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||
static int K2_RemoveFortItemFromPlayerHook1(AFortPlayerController* PlayerController, UFortItem* Item, int AmountToRemove, bool bForceRemoval);
|
||||
static void K2_RemoveFortItemFromPlayerHook(UObject* Context, FFrame& Stack, void* Ret);
|
||||
static AFortPickup* K2_SpawnPickupInWorldHook(UObject* Context, FFrame& Stack, AFortPickup** Ret);
|
||||
static AFortPickup* K2_SpawnPickupInWorldWithClassHook(UObject* Context, FFrame& Stack, AFortPickup** Ret);
|
||||
|
||||
@@ -62,23 +62,13 @@ AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Locatio
|
||||
}
|
||||
else
|
||||
{
|
||||
auto OldGuid = PrimaryPickupItemEntry->GetItemGuid();
|
||||
|
||||
if (false)
|
||||
{
|
||||
CopyStruct(PrimaryPickupItemEntry, ItemEntry, FFortItemEntry::GetStructSize(), FFortItemEntry::GetStruct());
|
||||
}
|
||||
else
|
||||
{
|
||||
PrimaryPickupItemEntry->GetItemDefinition() = ItemEntry->GetItemDefinition();
|
||||
PrimaryPickupItemEntry->GetLoadedAmmo() = ItemEntry->GetLoadedAmmo();
|
||||
}
|
||||
PrimaryPickupItemEntry->CopyFromAnotherItemEntry(ItemEntry);
|
||||
}
|
||||
|
||||
static auto PickupSourceTypeFlagsOffset = Pickup->GetOffset("PickupSourceTypeFlags", false);
|
||||
|
||||
if (PickupSourceTypeFlagsOffset != -1)
|
||||
Pickup->Get<int32>(PickupSourceTypeFlagsOffset) |= (int)PickupSource;
|
||||
Pickup->Get<int32>(PickupSourceTypeFlagsOffset) |= (int)PickupSource; // Assuming its the same enum on older versions.
|
||||
|
||||
PrimaryPickupItemEntry->GetCount() = OverrideCount == -1 ? ItemEntry->GetCount() : OverrideCount;
|
||||
|
||||
@@ -88,8 +78,50 @@ AFortPickup* AFortPickup::SpawnPickup(FFortItemEntry* ItemEntry, FVector Locatio
|
||||
|
||||
// static auto OptionalOwnerIDOffset = Pickup->GetOffset("OptionalOwnerID");
|
||||
// Pickup->Get<int>(OptionalOwnerIDOffset) = PlayerState ? PlayerState->GetWorldPlayerId() : -1;
|
||||
|
||||
auto PickupLocationData = Pickup->GetPickupLocationData();
|
||||
|
||||
Pickup->TossPickup(Location, Pawn, 0, bToss, PickupSource, SpawnSource);
|
||||
auto CanCombineWithPickup = [&](AActor* OtherPickupActor) -> bool
|
||||
{
|
||||
auto OtherPickup = (AFortPickup*)OtherPickupActor;
|
||||
|
||||
if (OtherPickup->GetPickupLocationData()->GetCombineTarget())
|
||||
return false;
|
||||
|
||||
if (PrimaryPickupItemEntry->GetItemDefinition() == OtherPickup->GetPrimaryPickupItemEntry()->GetItemDefinition())
|
||||
{
|
||||
auto IncomingCount = OtherPickup->GetPrimaryPickupItemEntry()->GetCount();
|
||||
|
||||
if (PrimaryPickupItemEntry->GetCount() + IncomingCount > PrimaryPickupItemEntry->GetItemDefinition()->GetMaxStackSize())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
if (Addresses::CombinePickupLea)
|
||||
{
|
||||
PickupLocationData->GetCombineTarget() = (AFortPickup*)Pickup->GetClosestActor(AFortPickup::StaticClass(), 4, CanCombineWithPickup);
|
||||
}
|
||||
|
||||
// our little remake of tosspickup
|
||||
|
||||
Pickup->GetPickupLocationData()->GetLootFinalPosition() = Location;
|
||||
Pickup->GetPickupLocationData()->GetLootInitialPosition() = Pickup->GetActorLocation();
|
||||
Pickup->GetPickupLocationData()->GetFlyTime() = 1.4f; // not right really
|
||||
Pickup->GetPickupLocationData()->GetItemOwner() = Pawn;
|
||||
Pickup->GetPickupLocationData()->GetFinalTossRestLocation() = Pickup->GetActorLocation(); // ong ong proper
|
||||
|
||||
if (!PickupLocationData->GetCombineTarget()) // I don't think we should call TossPickup for every pickup.
|
||||
{
|
||||
Pickup->TossPickup(Location, Pawn, 0, bToss, PickupSource, SpawnSource);
|
||||
}
|
||||
else
|
||||
{
|
||||
Pickup->OnRep_PickupLocationData();
|
||||
}
|
||||
|
||||
if (PickupSource == EFortPickupSourceTypeFlag::Container) // crashes if we do this then tosspickup
|
||||
{
|
||||
@@ -126,6 +158,26 @@ AFortPickup* AFortPickup::SpawnPickup(UFortItemDefinition* ItemDef, FVector Loca
|
||||
return Pickup;
|
||||
}
|
||||
|
||||
void AFortPickup::CombinePickupHook(AFortPickup* Pickup)
|
||||
{
|
||||
// LOG_INFO(LogDev, "CombinePickupHook!");
|
||||
|
||||
auto PickupToCombineInto = (AFortPickup*)Pickup->GetPickupLocationData()->GetCombineTarget();
|
||||
|
||||
if (!PickupToCombineInto->IsActorBeingDestroyed())
|
||||
{
|
||||
// TODO Add more checks
|
||||
|
||||
PickupToCombineInto->GetPrimaryPickupItemEntry()->GetCount() += Pickup->GetPrimaryPickupItemEntry()->GetCount();
|
||||
PickupToCombineInto->OnRep_PrimaryPickupItemEntry();
|
||||
|
||||
PickupToCombineInto->ForceNetUpdate();
|
||||
PickupToCombineInto->FlushNetDormancy();
|
||||
|
||||
Pickup->K2_DestroyActor();
|
||||
}
|
||||
}
|
||||
|
||||
char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
||||
{
|
||||
constexpr bool bTestPrinting = false; // we could just use our own logger but eh
|
||||
@@ -355,18 +407,7 @@ char AFortPickup::CompletePickupAnimationHook(AFortPickup* Pickup)
|
||||
|
||||
if (bWasHoldingSameItemWhenSwap && NewSwappedItem != FGuid(-1, -1, -1, -1))
|
||||
{
|
||||
static auto ClientEquipItemFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") ? FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") : FindObject<UFunction>("/Script/FortniteGame.FortPlayerController.ClientEquipItem");
|
||||
|
||||
if (ClientEquipItemFn)
|
||||
{
|
||||
struct
|
||||
{
|
||||
FGuid ItemGuid; // (ConstParm, Parm, ZeroConstructor, ReferenceParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
bool bForceExecution; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
} AFortPlayerController_ClientEquipItem_Params{ NewSwappedItem, true };
|
||||
|
||||
PlayerController->ProcessEvent(ClientEquipItemFn, &AFortPlayerController_ClientEquipItem_Params);
|
||||
}
|
||||
PlayerController->ClientEquipItem(NewSwappedItem, true);
|
||||
}
|
||||
|
||||
return CompletePickupAnimationOriginal(Pickup);
|
||||
|
||||
@@ -49,12 +49,36 @@ struct FFortPickupLocationData
|
||||
return *(AFortPawn**)(__int64(this) + ItemOwnerOffset);
|
||||
}
|
||||
|
||||
class AFortPickup*& GetCombineTarget()
|
||||
{
|
||||
static auto CombineTargetOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "CombineTarget");
|
||||
return *(AFortPickup**)(__int64(this) + CombineTargetOffset);
|
||||
}
|
||||
|
||||
FVector& GetStartDirection()
|
||||
{
|
||||
static auto StartDirectionOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "StartDirection");
|
||||
return *(FVector*)(__int64(this) + StartDirectionOffset);
|
||||
}
|
||||
|
||||
FVector& GetFinalTossRestLocation()
|
||||
{
|
||||
static auto FinalTossRestLocationOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "FinalTossRestLocation");
|
||||
return *(FVector*)(__int64(this) + FinalTossRestLocationOffset);
|
||||
}
|
||||
|
||||
FVector& GetLootInitialPosition()
|
||||
{
|
||||
static auto LootInitialPositionOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "LootInitialPosition");
|
||||
return *(FVector*)(__int64(this) + LootInitialPositionOffset);
|
||||
}
|
||||
|
||||
FVector& GetLootFinalPosition()
|
||||
{
|
||||
static auto LootFinalPositionOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "LootFinalPosition");
|
||||
return *(FVector*)(__int64(this) + LootFinalPositionOffset);
|
||||
}
|
||||
|
||||
FGuid& GetPickupGuid()
|
||||
{
|
||||
static auto PickupGuidOffset = FindOffsetStruct("/Script/FortniteGame.FortPickupLocationData", "PickupGuid");
|
||||
@@ -88,6 +112,12 @@ public:
|
||||
return this->GetPtr<FFortItemEntry>(PrimaryPickupItemEntryOffset);
|
||||
}
|
||||
|
||||
void OnRep_PickupLocationData()
|
||||
{
|
||||
static auto OnRep_PickupLocationDataFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPickup.OnRep_PickupLocationData");
|
||||
this->ProcessEvent(OnRep_PickupLocationDataFn);
|
||||
}
|
||||
|
||||
static AFortPickup* SpawnPickup(FFortItemEntry* ItemEntry, FVector Location,
|
||||
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
|
||||
class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true, int OverrideCount = -1);
|
||||
@@ -96,6 +126,7 @@ public:
|
||||
EFortPickupSourceTypeFlag PickupSource = EFortPickupSourceTypeFlag::Other, EFortPickupSpawnSource SpawnSource = EFortPickupSpawnSource::Unset,
|
||||
int LoadedAmmo = -1, class AFortPawn* Pawn = nullptr, UClass* OverrideClass = nullptr, bool bToss = true);
|
||||
|
||||
static void CombinePickupHook(AFortPickup* Pickup);
|
||||
static char CompletePickupAnimationHook(AFortPickup* Pickup);
|
||||
|
||||
static UClass* StaticClass();
|
||||
|
||||
@@ -35,6 +35,22 @@ void AFortPlayerController::ClientReportDamagedResourceBuilding(ABuildingSMActor
|
||||
this->ProcessEvent(fn, &AFortPlayerController_ClientReportDamagedResourceBuilding_Params);
|
||||
}
|
||||
|
||||
void AFortPlayerController::ClientEquipItem(const FGuid& ItemGuid, bool bForceExecution)
|
||||
{
|
||||
static auto ClientEquipItemFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") ? FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerAthena.ClientEquipItem") : FindObject<UFunction>("/Script/FortniteGame.FortPlayerController.ClientEquipItem");
|
||||
|
||||
if (ClientEquipItemFn)
|
||||
{
|
||||
struct
|
||||
{
|
||||
FGuid ItemGuid; // (ConstParm, Parm, ZeroConstructor, ReferenceParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
bool bForceExecution; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
|
||||
} AFortPlayerController_ClientEquipItem_Params{ ItemGuid, bForceExecution };
|
||||
|
||||
this->ProcessEvent(ClientEquipItemFn, &AFortPlayerController_ClientEquipItem_Params);
|
||||
}
|
||||
}
|
||||
|
||||
bool AFortPlayerController::DoesBuildFree()
|
||||
{
|
||||
if (Globals::bInfiniteMaterials)
|
||||
@@ -185,6 +201,10 @@ void AFortPlayerController::ApplyCosmeticLoadout()
|
||||
}
|
||||
|
||||
UFortKismetLibrary::StaticClass()->ProcessEvent(UpdatePlayerCustomCharacterPartsVisualizationFn, &PlayerStateAsFort);
|
||||
|
||||
PlayerStateAsFort->ForceNetUpdate();
|
||||
PawnAsFort->ForceNetUpdate();
|
||||
this->ForceNetUpdate();
|
||||
}
|
||||
|
||||
void AFortPlayerController::ServerLoadingScreenDroppedHook(UObject* Context, FFrame* Stack, void* Ret)
|
||||
@@ -879,6 +899,13 @@ void AFortPlayerController::ServerAttemptInventoryDropHook(AFortPlayerController
|
||||
if (Count < 0 || !Pawn)
|
||||
return;
|
||||
|
||||
if (auto PlayerControllerAthena = Cast<AFortPlayerControllerAthena>(PlayerController))
|
||||
{
|
||||
if (PlayerControllerAthena->IsInGhostMode())
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
auto WorldInventory = PlayerController->GetWorldInventory();
|
||||
auto ReplicatedEntry = WorldInventory->FindReplicatedEntry(ItemGuid);
|
||||
|
||||
|
||||
@@ -87,6 +87,25 @@ public:
|
||||
return CosmeticLoadout;
|
||||
}
|
||||
|
||||
void AddPickaxeToInventory()
|
||||
{
|
||||
auto CosmeticLoadout = GetCosmeticLoadout();
|
||||
auto CosmeticLoadoutPickaxe = CosmeticLoadout ? CosmeticLoadout->GetPickaxe() : nullptr;
|
||||
|
||||
static auto WeaponDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.AthenaPickaxeItemDefinition", "WeaponDefinition");
|
||||
|
||||
auto PickaxeDefinition = CosmeticLoadoutPickaxe ? CosmeticLoadoutPickaxe->Get<UFortItemDefinition*>(WeaponDefinitionOffset)
|
||||
: FindObject<UFortItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01");
|
||||
|
||||
auto WorldInventory = GetWorldInventory();
|
||||
|
||||
if (!WorldInventory || WorldInventory->GetPickaxeInstance())
|
||||
return;
|
||||
|
||||
WorldInventory->AddItem(PickaxeDefinition, nullptr);
|
||||
WorldInventory->Update();
|
||||
}
|
||||
|
||||
bool& ShouldTryPickupSwap()
|
||||
{
|
||||
static auto bTryPickupSwapOffset = GetOffset("bTryPickupSwap");
|
||||
@@ -99,6 +118,8 @@ public:
|
||||
return bTryPickupSwapOffset != -1;
|
||||
}
|
||||
|
||||
void ClientEquipItem(const FGuid& ItemGuid, bool bForceExecution);
|
||||
|
||||
bool DoesBuildFree();
|
||||
void DropAllItems(const std::vector<UFortItemDefinition*>& IgnoreItemDefs, bool bIgnoreSecondaryQuickbar = false, bool bRemoveIfNotDroppable = false);
|
||||
void ApplyCosmeticLoadout();
|
||||
|
||||
@@ -14,7 +14,7 @@ void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* S
|
||||
{
|
||||
LOG_INFO(LogDev, __FUNCTION__);
|
||||
|
||||
auto Controller = (AFortPlayerControllerAthena*)Context;
|
||||
auto PlayerController = (AFortPlayerControllerAthena*)Context;
|
||||
|
||||
UFortWorldItemDefinition* ItemProvidingGhostMode = nullptr;
|
||||
|
||||
@@ -26,11 +26,12 @@ void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* S
|
||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||
}
|
||||
|
||||
// if (!Controller->HasAuthority()) return StartGhostModeOriginal(Context, Stack, Ret);
|
||||
if (!PlayerController->HasAuthority()) // for real
|
||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||
|
||||
LOG_INFO(LogDev, "Attempting to give item {}", ItemProvidingGhostMode->IsValidLowLevel() ? ItemProvidingGhostMode->GetFullName() : "BadRead");
|
||||
|
||||
auto GhostModeRepData = Controller->GetGhostModeRepData();
|
||||
auto GhostModeRepData = PlayerController->GetGhostModeRepData();
|
||||
|
||||
if (GhostModeRepData->IsInGhostMode())
|
||||
{
|
||||
@@ -38,7 +39,7 @@ void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* S
|
||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||
}
|
||||
|
||||
auto WorldInventory = Controller->GetWorldInventory();
|
||||
auto WorldInventory = PlayerController->GetWorldInventory();
|
||||
|
||||
if (!WorldInventory)
|
||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||
@@ -53,7 +54,8 @@ void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* S
|
||||
if (bShouldUpdate)
|
||||
WorldInventory->Update();
|
||||
|
||||
Controller->ServerExecuteInventoryItemHook(Controller, GhostModeItemInstance->GetItemEntry()->GetItemGuid());
|
||||
PlayerController->ServerExecuteInventoryItemHook(PlayerController, GhostModeItemInstance->GetItemEntry()->GetItemGuid());
|
||||
PlayerController->ClientEquipItem(GhostModeItemInstance->GetItemEntry()->GetItemGuid(), true);
|
||||
LOG_INFO(LogDev, "Finished!");
|
||||
|
||||
return StartGhostModeOriginal(Context, Stack, Ret);
|
||||
@@ -65,25 +67,41 @@ void AFortPlayerControllerAthena::EndGhostModeHook(AFortPlayerControllerAthena*
|
||||
|
||||
LOG_INFO(LogDev, __FUNCTION__);
|
||||
|
||||
if (!PlayerController->HasAuthority()) // for real
|
||||
return EndGhostModeOriginal(PlayerController);
|
||||
|
||||
auto WorldInventory = PlayerController->GetWorldInventory();
|
||||
|
||||
if (!WorldInventory)
|
||||
return EndGhostModeOriginal(PlayerController);
|
||||
|
||||
auto GhostModeRepData = PlayerController->GetGhostModeRepData();
|
||||
FGhostModeRepData* GhostModeRepData = PlayerController->GetGhostModeRepData();
|
||||
UFortWorldItemDefinition* GhostModeItemDef = GhostModeRepData->GetGhostModeItemDef();
|
||||
|
||||
LOG_INFO(LogDev, "GhostModeItemDef: {}", GhostModeItemDef->IsValidLowLevel() ? GhostModeItemDef->GetFullName() : "BadRead");
|
||||
|
||||
if (!GhostModeItemDef) // bro IDFK
|
||||
{
|
||||
GhostModeItemDef = FindObject<UFortWorldItemDefinition>("/Game/Athena/Items/Gameplay/SpookyMist/AGID_SpookyMist.AGID_SpookyMist");
|
||||
}
|
||||
|
||||
if (!GhostModeItemDef)
|
||||
return EndGhostModeOriginal(PlayerController);
|
||||
|
||||
auto GhostModeItemDef = GhostModeRepData->GetGhostModeItemDef();
|
||||
auto GhostModeItemInstance = WorldInventory->FindItemInstance(GhostModeItemDef);
|
||||
|
||||
if (GhostModeItemInstance)
|
||||
{
|
||||
bool bShouldUpdate = false;
|
||||
int Count = 1; // GhostModeItemInstance->GetItemEntry()->GetCount()
|
||||
WorldInventory->RemoveItem(GhostModeItemInstance->GetItemEntry()->GetItemGuid(), &bShouldUpdate, Count);
|
||||
LOG_INFO(LogDev, "GhostModeItemInstance: {}", GhostModeItemInstance->IsValidLowLevel() ? GhostModeItemInstance->GetFullName() : "BadRead");
|
||||
|
||||
if (bShouldUpdate)
|
||||
WorldInventory->Update();
|
||||
}
|
||||
if (!GhostModeItemInstance)
|
||||
return EndGhostModeOriginal(PlayerController);
|
||||
|
||||
bool bShouldUpdate = false;
|
||||
int Count = GhostModeItemInstance->GetItemEntry()->GetCount(); // 1
|
||||
bool bForceRemoval = true; // false
|
||||
WorldInventory->RemoveItem(GhostModeItemInstance->GetItemEntry()->GetItemGuid(), &bShouldUpdate, Count, bForceRemoval);
|
||||
|
||||
if (bShouldUpdate)
|
||||
WorldInventory->Update();
|
||||
|
||||
return EndGhostModeOriginal(PlayerController);
|
||||
}
|
||||
|
||||
@@ -139,10 +139,24 @@ public:
|
||||
|
||||
FGhostModeRepData* GetGhostModeRepData()
|
||||
{
|
||||
static auto GhostModeRepDataOffset = GetOffset("GhostModeRepData");
|
||||
static auto GhostModeRepDataOffset = GetOffset("GhostModeRepData", false);
|
||||
|
||||
if (GhostModeRepDataOffset == -1)
|
||||
return nullptr;
|
||||
|
||||
return GetPtr<FGhostModeRepData>(GhostModeRepDataOffset);
|
||||
}
|
||||
|
||||
bool IsInGhostMode()
|
||||
{
|
||||
auto GhostModeRepData = GetGhostModeRepData();
|
||||
|
||||
if (!GhostModeRepData)
|
||||
return false;
|
||||
|
||||
return GhostModeRepData->IsInGhostMode();
|
||||
}
|
||||
|
||||
UAthenaMarkerComponent* GetMarkerComponent()
|
||||
{
|
||||
static auto MarkerComponentOffset = GetOffset("MarkerComponent");
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <memcury.h>
|
||||
#include "FortPlayerController.h"
|
||||
#include "FortGadgetItemDefinition.h"
|
||||
#include "FortPlayerControllerAthena.h"
|
||||
|
||||
FFortAthenaLoadout* AFortPlayerPawn::GetCosmeticLoadout()
|
||||
{
|
||||
@@ -273,6 +274,11 @@ void AFortPlayerPawn::ServerHandlePickupHook(AFortPlayerPawn* Pawn, AFortPickup*
|
||||
return;
|
||||
}
|
||||
|
||||
auto PlayerControllerAthena = Cast<AFortPlayerControllerAthena>(Pawn->GetController());
|
||||
|
||||
if (PlayerControllerAthena && PlayerControllerAthena->IsInGhostMode())
|
||||
return;
|
||||
|
||||
static auto IncomingPickupsOffset = Pawn->GetOffset("IncomingPickups");
|
||||
Pawn->Get<TArray<AFortPickup*>>(IncomingPickupsOffset).Add(Pickup);
|
||||
|
||||
|
||||
@@ -99,17 +99,9 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
|
||||
{
|
||||
// TODO Check Playlist->bRequirePickaxeInStartingInventory
|
||||
|
||||
auto CosmeticLoadout = NewPlayerAsAthena->GetCosmeticLoadoutOffset() != -1 ? NewPlayerAsAthena->GetCosmeticLoadout() : nullptr;
|
||||
auto CosmeticLoadoutPickaxe = CosmeticLoadout ? CosmeticLoadout->GetPickaxe() : nullptr;
|
||||
|
||||
static auto WeaponDefinitionOffset = FindOffsetStruct("/Script/FortniteGame.AthenaPickaxeItemDefinition", "WeaponDefinition", false);
|
||||
|
||||
auto PickaxeDefinition = CosmeticLoadoutPickaxe ? CosmeticLoadoutPickaxe->Get<UFortItemDefinition*>(WeaponDefinitionOffset)
|
||||
: FindObject<UFortItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01");
|
||||
|
||||
auto& StartingItems = ((AFortGameModeAthena*)GameMode)->GetStartingItems();
|
||||
|
||||
WorldInventory->AddItem(PickaxeDefinition, nullptr);
|
||||
NewPlayerAsAthena->AddPickaxeToInventory();
|
||||
|
||||
for (int i = 0; i < StartingItems.Num(); i++)
|
||||
{
|
||||
|
||||
@@ -529,9 +529,6 @@
|
||||
<ClInclude Include="BuildingTrap.h">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Public\Building</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="FortAthenaSupplyDrop.h">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Public\Building\GameplayActors</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BuildingGameplayActor.h">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Public\Building</Filter>
|
||||
</ClInclude>
|
||||
@@ -842,6 +839,9 @@
|
||||
<Filter>FortniteGame\Source\FortniteGame\Public\Mutators</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="discord.h" />
|
||||
<ClInclude Include="FortAthenaSupplyDrop.h">
|
||||
<Filter>FortniteGame\Source\FortniteGame\Public\Building</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Engine">
|
||||
@@ -1081,6 +1081,9 @@
|
||||
<Filter Include="Engine\Source\Runtime\Core\Private\GenericPlatform">
|
||||
<UniqueIdentifier>{c04eb59f-e186-49a3-a145-1fd3dc1dcd3d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Reboot\Private">
|
||||
<UniqueIdentifier>{00ba0f86-7eef-4ffd-9a9d-47477e5193b2}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="UnrealEngine.cpp">
|
||||
|
||||
@@ -279,6 +279,15 @@ void Addresses::FindAll()
|
||||
LOG_INFO(LogDev, "Finding FreeArrayOfEntries");
|
||||
Addresses::FreeArrayOfEntries = FindFreeArrayOfEntries();
|
||||
|
||||
LOG_INFO(LogDev, "Finding UpdateTrackedAttributesLea");
|
||||
Addresses::UpdateTrackedAttributesLea = FindUpdateTrackedAttributesLea();
|
||||
|
||||
LOG_INFO(LogDev, "Finding CombinePickupLea");
|
||||
Addresses::CombinePickupLea = FindCombinePickupLea();
|
||||
|
||||
LOG_INFO(LogDev, "Finding CreateBuildingActorCallForDeco");
|
||||
Addresses::CreateBuildingActorCallForDeco = FindCreateBuildingActorCallForDeco();
|
||||
|
||||
LOG_INFO(LogDev, "Finished finding!");
|
||||
}
|
||||
|
||||
@@ -341,6 +350,9 @@ void Addresses::Print()
|
||||
LOG_INFO(LogDev, "EnterAircraft: 0x{:x}", EnterAircraft - Base);
|
||||
LOG_INFO(LogDev, "SetTimer: 0x{:x}", SetTimer - Base);
|
||||
LOG_INFO(LogDev, "PickupInitialize: 0x{:x}", PickupInitialize - Base);
|
||||
LOG_INFO(LogDev, "UpdateTrackedAttributesLea: 0x{:x}", UpdateTrackedAttributesLea - Base);
|
||||
LOG_INFO(LogDev, "CombinePickupLea: 0x{:x}", CombinePickupLea - Base);
|
||||
LOG_INFO(LogDev, "CreateBuildingActorCallForDeco: 0x{:x}", CreateBuildingActorCallForDeco - Base);
|
||||
}
|
||||
|
||||
void Offsets::FindAll()
|
||||
|
||||
@@ -65,6 +65,9 @@ namespace Addresses
|
||||
extern inline uint64 PickupInitialize = 0;
|
||||
extern inline uint64 FreeEntry = 0;
|
||||
extern inline uint64 FreeArrayOfEntries = 0;
|
||||
extern inline uint64 UpdateTrackedAttributesLea = 0;
|
||||
extern inline uint64 CombinePickupLea = 0;
|
||||
extern inline uint64 CreateBuildingActorCallForDeco = 0;
|
||||
|
||||
void SetupVersion(); // Finds Engine Version
|
||||
void FindAll();
|
||||
|
||||
@@ -426,6 +426,9 @@ DWORD WINAPI Main(LPVOID)
|
||||
nullptr, false);
|
||||
}
|
||||
|
||||
HookInstruction(Addresses::UpdateTrackedAttributesLea, (PVOID)UFortGadgetItemDefinition::UpdateTrackedAttributesHook, "/Script/FortniteGame.FortPlayerController.Suicide", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
||||
HookInstruction(Addresses::CombinePickupLea, (PVOID)AFortPickup::CombinePickupHook, "/Script/Engine.PlayerController.SetVirtualJoystickVisibility", ERelativeOffsets::LEA, FortPlayerControllerAthenaDefault);
|
||||
|
||||
Hooking::MinHook::Hook(FortWeaponDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortWeapon.ServerReleaseWeaponAbility"),
|
||||
AFortWeapon::ServerReleaseWeaponAbilityHook, (PVOID*)&AFortWeapon::ServerReleaseWeaponAbilityOriginal, false, true);
|
||||
|
||||
@@ -489,13 +492,33 @@ DWORD WINAPI Main(LPVOID)
|
||||
AFortPlayerControllerAthena::ServerReadyToStartMatchHook, (PVOID*)&AFortPlayerControllerAthena::ServerReadyToStartMatchOriginal, false);
|
||||
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerZone.ServerRequestSeatChange"),
|
||||
AFortPlayerControllerAthena::ServerRequestSeatChangeHook, (PVOID*)&AFortPlayerControllerAthena::ServerRequestSeatChangeOriginal, false);
|
||||
|
||||
if (false)
|
||||
{
|
||||
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.StartGhostMode"), // (Milxnor) TODO: This changes to a component in later seasons.
|
||||
AFortPlayerControllerAthena::StartGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::StartGhostModeOriginal, false, true);
|
||||
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.EndGhostMode"),
|
||||
AFortPlayerControllerAthena::EndGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::EndGhostModeOriginal, false);
|
||||
AFortPlayerControllerAthena::StartGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::StartGhostModeOriginal, false, true); // We can exec hook since it only gets called via blueprint.
|
||||
|
||||
auto EndGhostModeFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.EndGhostMode");
|
||||
|
||||
if (EndGhostModeFn)
|
||||
{
|
||||
auto EndGhostModeExec = (uint64)EndGhostModeFn->GetFunc();
|
||||
|
||||
for (int i = 0; i < 400; i++)
|
||||
{
|
||||
if (*(uint8_t*)(EndGhostModeExec + i) == 0xE9 // thanks 6.21
|
||||
|| *(uint8_t*)(EndGhostModeExec + i) == 0xE8)
|
||||
{
|
||||
Hooking::MinHook::Hook((PVOID)Memcury::Scanner(EndGhostModeExec + i).RelativeOffset(1).Get(), AFortPlayerControllerAthena::EndGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::EndGhostModeOriginal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerGameplay.EndGhostMode"),
|
||||
// AFortPlayerControllerAthena::EndGhostModeHook, (PVOID*)&AFortPlayerControllerAthena::EndGhostModeOriginal, false);
|
||||
}
|
||||
}
|
||||
|
||||
Hooking::MinHook::Hook(FortPlayerControllerAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerAthena.ServerGiveCreativeItem"),
|
||||
AFortPlayerControllerAthena::ServerGiveCreativeItemHook, nullptr, true);
|
||||
|
||||
@@ -526,18 +549,15 @@ DWORD WINAPI Main(LPVOID)
|
||||
AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false);
|
||||
Hooking::MinHook::Hook((PVOID)GetFunctionIdxOrPtr(FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerOnExitVehicle"), true), AFortPlayerPawn::ServerOnExitVehicleHook, (PVOID*)&AFortPlayerPawn::ServerOnExitVehicleOriginal);
|
||||
|
||||
bool bNativeHookRemoveFortItemFromPlayer = false;
|
||||
|
||||
if (bNativeHookRemoveFortItemFromPlayer)
|
||||
{
|
||||
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_RemoveFortItemFromPlayer"),
|
||||
UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook1, nullptr, false);
|
||||
}
|
||||
|
||||
static auto FortGameplayAbilityAthena_PeriodicItemGrantDefault = FindObject<UFortGameplayAbilityAthena_PeriodicItemGrant>("/Script/FortniteGame.Default__FortGameplayAbilityAthena_PeriodicItemGrant");
|
||||
|
||||
Hooking::MinHook::Hook(FortGameplayAbilityAthena_PeriodicItemGrantDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortGameplayAbilityAthena_PeriodicItemGrant.StartItemAwardTimers"),
|
||||
UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersHook, (PVOID*)&UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersOriginal, false, true);
|
||||
if (FortGameplayAbilityAthena_PeriodicItemGrantDefault)
|
||||
{
|
||||
Hooking::MinHook::Hook(FortGameplayAbilityAthena_PeriodicItemGrantDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortGameplayAbilityAthena_PeriodicItemGrant.StopItemAwardTimers"),
|
||||
UFortGameplayAbilityAthena_PeriodicItemGrant::StopItemAwardTimersHook, (PVOID*)&UFortGameplayAbilityAthena_PeriodicItemGrant::StopItemAwardTimersOriginal, false, true);
|
||||
Hooking::MinHook::Hook(FortGameplayAbilityAthena_PeriodicItemGrantDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortGameplayAbilityAthena_PeriodicItemGrant.StartItemAwardTimers"),
|
||||
UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersHook, (PVOID*)&UFortGameplayAbilityAthena_PeriodicItemGrant::StartItemAwardTimersOriginal, false, true);
|
||||
}
|
||||
|
||||
Hooking::MinHook::Hook(FindObject<AFortAthenaMutator_Barrier>(L"/Script/FortniteGame.Default__FortAthenaMutator_Barrier"), FindObject<UFunction>(L"/Script/FortniteGame.FortAthenaMutator_Barrier.OnGamePhaseStepChanged"),
|
||||
AFortAthenaMutator_Barrier::OnGamePhaseStepChangedHook, (PVOID*)&AFortAthenaMutator_Barrier::OnGamePhaseStepChangedOriginal, false, true);
|
||||
@@ -564,12 +584,8 @@ DWORD WINAPI Main(LPVOID)
|
||||
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawnAthena.OnCapsuleBeginOverlap") ? FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawnAthena.OnCapsuleBeginOverlap") : FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.OnCapsuleBeginOverlap"),
|
||||
AFortPlayerPawnAthena::OnCapsuleBeginOverlapHook, (PVOID*)&AFortPlayerPawnAthena::OnCapsuleBeginOverlapOriginal, false, true);
|
||||
|
||||
if (!bNativeHookRemoveFortItemFromPlayer)
|
||||
{
|
||||
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_RemoveFortItemFromPlayer"),
|
||||
UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook, (PVOID*)&UFortKismetLibrary::K2_RemoveFortItemFromPlayerOriginal, false, true);
|
||||
}
|
||||
|
||||
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_RemoveFortItemFromPlayer"),
|
||||
UFortKismetLibrary::K2_RemoveFortItemFromPlayerHook, (PVOID*)&UFortKismetLibrary::K2_RemoveFortItemFromPlayerOriginal, false, true);
|
||||
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_SpawnPickupInWorld"),
|
||||
UFortKismetLibrary::K2_SpawnPickupInWorldHook, (PVOID*)&UFortKismetLibrary::K2_SpawnPickupInWorldOriginal, false, true);
|
||||
Hooking::MinHook::Hook(FortKismetLibraryDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortKismetLibrary.K2_SpawnPickupInWorldWithLootTier"),
|
||||
@@ -765,7 +781,6 @@ DWORD WINAPI Main(LPVOID)
|
||||
// if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11)
|
||||
{
|
||||
auto ClientOnPawnDiedCallAddr = FindFunctionCall(L"ClientOnPawnDied", Engine_Version == 416 ? std::vector<uint8_t>{ 0x48, 0x89, 0x54 } : std::vector<uint8_t>{ 0x48, 0x89, 0x5C });
|
||||
LOG_INFO(LogDev, "ahh!");
|
||||
LOG_INFO(LogDev, "ClientOnPawnDiedCallAddr: 0x{:x}", ClientOnPawnDiedCallAddr - __int64(GetModuleHandleW(0)));
|
||||
Hooking::MinHook::Hook((PVOID)ClientOnPawnDiedCallAddr, AFortPlayerController::ClientOnPawnDiedHook, (PVOID*)&AFortPlayerController::ClientOnPawnDiedOriginal);
|
||||
}
|
||||
|
||||
@@ -551,6 +551,77 @@ static inline uint64 FindSpecConstructor()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint64 FindCreateBuildingActorCallForDeco() // kill me
|
||||
{
|
||||
auto Addrr = Memcury::Scanner::FindStringRef(L"ServerCreateBuildingAndSpawnDeco called without a valid DecoItemDef").Get(); // honestly L (we should get it from the ufunc not string)
|
||||
|
||||
if (!Addrr)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < 10000; i++)
|
||||
{
|
||||
if ((*(uint8_t*)(uint8_t*)(Addrr + i) == 0xC6 && *(uint8_t*)(uint8_t*)(Addrr + i + 6) == 0xE8)) // Checked 10.40
|
||||
{
|
||||
return Addrr - i + 6;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint64 FindUpdateTrackedAttributesLea() // kill me
|
||||
{
|
||||
// 10.40 = (__int64(GetModuleHandleW(0)) + 0x19E19A5)
|
||||
|
||||
// So we keep going until we find a lea with nullsub..
|
||||
|
||||
uint64 ApplyGadgetAttributesAddr = 0;
|
||||
|
||||
if (!ApplyGadgetAttributesAddr)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < 10000; i++)
|
||||
{
|
||||
if ((*(uint8_t*)(uint8_t*)(ApplyGadgetAttributesAddr + i) == 0x48 && *(uint8_t*)(uint8_t*)(ApplyGadgetAttributesAddr + i + 1) == 0x8D
|
||||
&& *(uint8_t*)(uint8_t*)(ApplyGadgetAttributesAddr + i + 2) == 0x05))
|
||||
{
|
||||
auto loadAddress = Memcury::Scanner(ApplyGadgetAttributesAddr + i).RelativeOffset(3).Get();
|
||||
|
||||
if (IsNullSub(loadAddress)) // Safety
|
||||
return ApplyGadgetAttributesAddr + i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint64 FindCombinePickupLea() // kill me
|
||||
{
|
||||
/* uint64 OnRep_PickupLocationDataAddr = 0; // TODO (Idea: Find SetupCombinePickupDelegates from this).
|
||||
|
||||
if (!OnRep_PickupLocationDataAddr)
|
||||
return 0; */
|
||||
|
||||
uint64 SetupCombinePickupDelegatesAddr = Memcury::Scanner::FindPattern("48 89 AC 24 ? ? ? ? 48 89 B4 24 ? ? ? ? 48 89 BC 24 ? ? ? ? 0F 29 B4 24 ? ? ? ? 75").Get(); // Haha so funny thing, this isn't actually the start its the middle because it's in function chunks yay!
|
||||
|
||||
if (!SetupCombinePickupDelegatesAddr)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
if (*(uint8_t*)(uint8_t*)(SetupCombinePickupDelegatesAddr + i) == 0x48 && *(uint8_t*)(uint8_t*)(SetupCombinePickupDelegatesAddr + i + 1) == 0x8D
|
||||
&& *(uint8_t*)(uint8_t*)(SetupCombinePickupDelegatesAddr + i + 2) == 0x05) // Checked on 10.40, it was the first lea.
|
||||
{
|
||||
auto loadAddress = Memcury::Scanner(SetupCombinePickupDelegatesAddr + i).RelativeOffset(3).Get();
|
||||
|
||||
if (IsNullSub(loadAddress)) // Safety
|
||||
return SetupCombinePickupDelegatesAddr + i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint64 FindCompletePickupAnimation()
|
||||
{
|
||||
if (Engine_Version == 416 || Engine_Version == 419)
|
||||
@@ -771,8 +842,43 @@ static inline uint64 FindFreeEntry()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint64 FindBeginningOfFuncEXP(uint64 Addr, int ToSearch = 1000)
|
||||
{
|
||||
for (int i = 0; i < ToSearch; i++)
|
||||
{
|
||||
if (Fortnite_Version >= 10)
|
||||
{
|
||||
if ((*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x53))
|
||||
{
|
||||
return Addr - i;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x55))
|
||||
{
|
||||
return Addr - i;
|
||||
|
||||
}
|
||||
|
||||
if (*(uint8_t*)(uint8_t*)(Addr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addr - i + 2) == 0x5C)
|
||||
{
|
||||
return Addr - i;
|
||||
|
||||
}
|
||||
|
||||
/* if (*(uint8_t*)(uint8_t*)(Addr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x8B && *(uint8_t*)(uint8_t*)(Addr - i + 2) == 0xC4)
|
||||
{
|
||||
return Addr - i;
|
||||
} */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint64 FindRemoveGadgetData()
|
||||
{
|
||||
uint64 RemoveGadgetDataAddr = 0;
|
||||
|
||||
if (Engine_Version <= 423)
|
||||
{
|
||||
auto Addr = Memcury::Scanner::FindStringRef(L"UFortGadgetItemDefinition::RemoveGadgetData - Removing Gadget Data for Gadget Item [%s]!", false).Get();
|
||||
@@ -781,56 +887,64 @@ static inline uint64 FindRemoveGadgetData()
|
||||
Addr = Memcury::Scanner::FindStringRef(L"UFortGadgetItemDefinition::RemoveGadgetData - Removing Gadget Data for Gadet Item [%s]!", false).Get();
|
||||
|
||||
if (!Addr)
|
||||
{
|
||||
Addr = Memcury::Scanner::FindStringRef(L"UFortGadgetItemDefinition::RemoveGadgetData - Failed to get the Player Controller to cleanup Gadget Item [%s]!").Get();
|
||||
}
|
||||
|
||||
if (!Addr)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
if (Fortnite_Version >= 10)
|
||||
{
|
||||
if ((*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x53))
|
||||
{
|
||||
return Addr - i;
|
||||
}
|
||||
}
|
||||
|
||||
if ((*(uint8_t*)(uint8_t*)(Addr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x55))
|
||||
{
|
||||
return Addr - i;
|
||||
}
|
||||
|
||||
if (*(uint8_t*)(uint8_t*)(Addr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addr - i + 2) == 0x5C)
|
||||
{
|
||||
return Addr - i;
|
||||
}
|
||||
|
||||
/* if (*(uint8_t*)(uint8_t*)(Addr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addr - i + 1) == 0x8B && *(uint8_t*)(uint8_t*)(Addr - i + 2) == 0xC4)
|
||||
{
|
||||
return Addr - i;
|
||||
} */
|
||||
}
|
||||
|
||||
return 0;
|
||||
// return FindBytes(StringRef, { 0x40, 0x55 }, 1000, 0, true);
|
||||
RemoveGadgetDataAddr = FindBeginningOfFuncEXP(Addr);
|
||||
}
|
||||
if (Engine_Version == 426)
|
||||
return Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 56 41 56 41 57 48 83 EC 30 48 8B 02 48").Get(); // 14.60
|
||||
else if (Engine_Version == 426)
|
||||
RemoveGadgetDataAddr = Memcury::Scanner::FindPattern("48 85 D2 0F 84 ? ? ? ? 56 41 56 41 57 48 83 EC 30 48 8B 02 48").Get(); // 14.60
|
||||
|
||||
LOG_INFO(LogDev, "RemoveGadgetData: 0x{:x}", RemoveGadgetDataAddr - __int64(GetModuleHandleW(0)));
|
||||
|
||||
return 0;
|
||||
if (!RemoveGadgetDataAddr)
|
||||
return 0;
|
||||
|
||||
uint64 RemoveGadgetDataCall = Memcury::Scanner::FindPointerRef((PVOID)RemoveGadgetDataAddr, 0, false, false).Get();
|
||||
|
||||
if (!RemoveGadgetDataCall)
|
||||
return RemoveGadgetDataAddr;
|
||||
|
||||
uint64 FortGadgetItemDefinition_RemoveGadgetDataAddr = FindBeginningOfFuncEXP(RemoveGadgetDataCall);
|
||||
|
||||
if (!FortGadgetItemDefinition_RemoveGadgetDataAddr)
|
||||
return RemoveGadgetDataAddr;
|
||||
|
||||
uint64 FortGadgetItemDefinition_RemoveGadgetDataCall = Memcury::Scanner::FindPointerRef((PVOID)FortGadgetItemDefinition_RemoveGadgetDataAddr, 0, false, false).Get();
|
||||
|
||||
if (!FortGadgetItemDefinition_RemoveGadgetDataCall)
|
||||
return FortGadgetItemDefinition_RemoveGadgetDataAddr;
|
||||
|
||||
uint64 AthenaGadgetItemDefinition_RemoveGadgetDataAddr = FindBeginningOfFuncEXP(FortGadgetItemDefinition_RemoveGadgetDataCall);
|
||||
|
||||
if (!AthenaGadgetItemDefinition_RemoveGadgetDataAddr)
|
||||
return FortGadgetItemDefinition_RemoveGadgetDataAddr;
|
||||
|
||||
return AthenaGadgetItemDefinition_RemoveGadgetDataAddr;
|
||||
}
|
||||
|
||||
static inline uint64 FindApplyGadgetData()
|
||||
{
|
||||
if (Engine_Version >= 420 && Engine_Version <= 422)
|
||||
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 41 0F B6 D9 49 8B").Get(); // 4.1 & 6.21 & 7.40
|
||||
if (Engine_Version >= 423 && Engine_Version <= 426)
|
||||
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 7C 24 ? 41 54 41 56 41 57 48 83 EC 20 41 0F").Get(); // 8.51 & 12.41
|
||||
uint64 FortGadgetItemDefinition_ApplyGadgetDataAddr = 0;
|
||||
|
||||
return 0;
|
||||
if (Engine_Version >= 420 && Engine_Version <= 422)
|
||||
FortGadgetItemDefinition_ApplyGadgetDataAddr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 20 41 0F B6 D9 49 8B").Get(); // 4.1 & 6.21 & 7.40
|
||||
if (Engine_Version >= 423 && Engine_Version <= 426)
|
||||
FortGadgetItemDefinition_ApplyGadgetDataAddr = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 7C 24 ? 41 54 41 56 41 57 48 83 EC 20 41 0F").Get(); // 8.51 & 12.41
|
||||
|
||||
uint64 FortGadgetItemDefinition_ApplyGadgetDataCall = Memcury::Scanner::FindPointerRef((PVOID)FortGadgetItemDefinition_ApplyGadgetDataAddr, 0, false, false).Get();
|
||||
|
||||
if (!FortGadgetItemDefinition_ApplyGadgetDataCall)
|
||||
return FortGadgetItemDefinition_ApplyGadgetDataAddr;
|
||||
|
||||
auto AthenaGadgetItemDefinition_ApplyGadgetDataAddr = FindBeginningOfFuncEXP(FortGadgetItemDefinition_ApplyGadgetDataCall);
|
||||
|
||||
if (!AthenaGadgetItemDefinition_ApplyGadgetDataAddr)
|
||||
return FortGadgetItemDefinition_ApplyGadgetDataAddr;
|
||||
|
||||
return AthenaGadgetItemDefinition_ApplyGadgetDataAddr;
|
||||
}
|
||||
|
||||
static inline uint64 FindGetInterfaceAddress()
|
||||
|
||||
@@ -806,7 +806,6 @@ static inline void MainUI()
|
||||
if (WeaponsFile.is_open())
|
||||
{
|
||||
WeaponsFile << FortniteVersionStr;
|
||||
static auto FortWeaponItemDefinitionClass = FindObject<UClass>("/Script/FortniteGame.FortWeaponItemDefinition");
|
||||
|
||||
auto DumpItemDefinitionClass = [&WeaponsFile](UClass* Class) {
|
||||
auto AllObjects = GetAllObjectsOfClass(Class);
|
||||
@@ -831,6 +830,7 @@ static inline void MainUI()
|
||||
|
||||
DumpItemDefinitionClass(UFortWeaponItemDefinition::StaticClass());
|
||||
DumpItemDefinitionClass(UFortGadgetItemDefinition::StaticClass());
|
||||
DumpItemDefinitionClass(FindObject<UClass>("/Script/FortniteGame.FortAmmoItemDefinition"));
|
||||
}
|
||||
else
|
||||
std::cout << "Failed to open playlist file!\n";
|
||||
|
||||
@@ -338,4 +338,43 @@ namespace Hooking
|
||||
*Addr = Original;
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
static inline void ChangeBytesThing(uint8_t* instrAddr, uint8_t* DetourAddr, int Offset)
|
||||
{
|
||||
int64_t delta = DetourAddr - (instrAddr + Offset + 4);
|
||||
*(int32_t*)(instrAddr + Offset) = static_cast<int32_t>(delta);
|
||||
}
|
||||
|
||||
enum ERelativeOffsets
|
||||
{
|
||||
CALL = 1,
|
||||
LEA = 3
|
||||
};
|
||||
|
||||
static inline void HookInstruction(uint64 instrAddr, void* Detour, const std::string& FunctionToReplace, ERelativeOffsets Offset, UObject* DefaultClass = nullptr) // we need better name
|
||||
{
|
||||
if (!instrAddr)
|
||||
return;
|
||||
|
||||
auto UFunc = FindObject<UFunction>(FunctionToReplace);
|
||||
|
||||
uint64 FunctionAddr = __int64(UFunc->GetFunc()); // GetFunctionIdxOrPtr(FindObject<UFunction>(FunctionToReplace));
|
||||
|
||||
if (IsBadReadPtr((void*)FunctionAddr))
|
||||
{
|
||||
auto Idx = FunctionAddr / 8;
|
||||
|
||||
FunctionAddr = (uint64)DefaultClass->VFTable[Idx];
|
||||
}
|
||||
|
||||
if (__int64(instrAddr) - FunctionAddr < 0) // We do not want the FunctionAddr (detour) to be less than where we are replacing.
|
||||
{
|
||||
LOG_INFO(LogDev, "Hooking Instruction will not work! Function is after ({})!", FunctionToReplace);
|
||||
return;
|
||||
}
|
||||
|
||||
Hooking::MinHook::Hook((PVOID)FunctionAddr, Detour, nullptr, FunctionToReplace);
|
||||
|
||||
ChangeBytesThing((uint8_t*)instrAddr, (uint8_t*)FunctionAddr, (int)Offset);
|
||||
}
|
||||
26
vendor/memcury.h
vendored
26
vendor/memcury.h
vendored
@@ -758,10 +758,13 @@
|
||||
return Scanner(add);
|
||||
}
|
||||
|
||||
static auto FindPointerRef(void* Pointer, int useRefNum = 0, bool bUseFirstResult = false) -> Scanner // credit me and ender
|
||||
static auto FindPointerRef(void* Pointer, int useRefNum = 0, bool bUseFirstResult = false, bool bWarnIfNotFound = true) -> Scanner // credit me and ender
|
||||
{
|
||||
PE::Address add{ nullptr };
|
||||
|
||||
if (!Pointer)
|
||||
return Scanner(add);
|
||||
|
||||
auto textSection = PE::Section::GetSection(".text");
|
||||
|
||||
const auto scanBytes = reinterpret_cast<std::uint8_t*>(textSection.GetSectionStart().Get());
|
||||
@@ -803,14 +806,17 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (add == 0)
|
||||
|
||||
if (bWarnIfNotFound)
|
||||
{
|
||||
MessageBoxA(0, "FindPointerRef return nullptr", "Memcury", MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MessageBoxA(0, std::format("FindPointerRef return 0x{:x}", add.Get() - __int64(GetModuleHandleW(0))).c_str(), "Memcury", MB_OK);
|
||||
if (add == 0)
|
||||
{
|
||||
MessageBoxA(0, "FindPointerRef return nullptr", "Memcury", MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// MessageBoxA(0, std::format("FindPointerRef return 0x{:x}", add.Get() - __int64(GetModuleHandleW(0))).c_str(), "Memcury", MB_OK);
|
||||
}
|
||||
}
|
||||
|
||||
return Scanner(add);
|
||||
@@ -1423,4 +1429,6 @@
|
||||
} */
|
||||
|
||||
return PtrRef.ScanFor(Bytes, false).Get();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IsNullSub(uint64 Addr) { return *(uint8_t*)(Addr) == 0xC3 || *(uint8_t*)(Addr) == 0xC2; }
|
||||
Reference in New Issue
Block a user