fix 7.20, >2.5 emoting, fix removing item bug on >2.5, fix equipping being buggy on >2.5, added ammo depletion to 1.11+
This commit is contained in:
Milxnor
2023-04-02 16:38:53 -04:00
parent c6bbaccf7f
commit ffbba9e9a4
12 changed files with 181 additions and 39 deletions

View File

@@ -807,8 +807,8 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
Parts[(int)EFortCustomPartType::Head] = headPart; Parts[(int)EFortCustomPartType::Head] = headPart;
Parts[(int)EFortCustomPartType::Body] = bodyPart; Parts[(int)EFortCustomPartType::Body] = bodyPart;
// if (Fortnite_Version > 2.5) if (Fortnite_Version > 2.5)
Parts[(int)EFortCustomPartType::Backpack] = backpackPart; Parts[(int)EFortCustomPartType::Backpack] = backpackPart;
static auto OnRep_CharacterPartsFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts"); static auto OnRep_CharacterPartsFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerState.OnRep_CharacterParts");
PlayerStateAthena->ProcessEvent(OnRep_CharacterPartsFn); PlayerStateAthena->ProcessEvent(OnRep_CharacterPartsFn);

View File

@@ -1,14 +1,7 @@
#include "FortInventory.h" #include "FortInventory.h"
#include "FortPlayerController.h" #include "FortPlayerController.h"
#include "FortPickup.h" #include "FortPickup.h"
#include "FortQuickBars.h"
enum class EFortQuickBars : uint8_t
{
Primary = 0,
Secondary = 1,
Max_None = 2,
EFortQuickBars_MAX = 3
};
UFortItem* CreateItemInstance(AFortPlayerController* PlayerController, UFortItemDefinition* ItemDefinition, int Count) UFortItem* CreateItemInstance(AFortPlayerController* PlayerController, UFortItemDefinition* ItemDefinition, int Count)
{ {
@@ -261,19 +254,17 @@ bool AFortInventory::RemoveItem(const FGuid& ItemGuid, bool* bShouldUpdate, int
if (FortPlayerController && Engine_Version < 420) if (FortPlayerController && Engine_Version < 420)
{ {
static auto QuickBarsOffset = FortPlayerController->GetOffset("QuickBars", false); static auto QuickBarsOffset = FortPlayerController->GetOffset("QuickBars", false);
auto QuickBars = FortPlayerController->Get<AActor*>(QuickBarsOffset); auto QuickBars = FortPlayerController->Get<AFortQuickBars*>(QuickBarsOffset);
if (QuickBars) if (QuickBars)
{ {
static auto ServerRemoveItemInternalFn = FindObject<UFunction>("/Script/FortniteGame.FortQuickBars.ServerRemoveItemInternal"); auto SlotIndex = QuickBars->GetSlotIndex(ItemGuid);
struct if (SlotIndex != -1)
{ {
FGuid Item; // (Parm, IsPlainOldData) QuickBars->ServerRemoveItemInternal(ItemGuid, false, true);
bool bFindReplacement; // (Parm, ZeroConstructor, IsPlainOldData) QuickBars->EmptySlot(IsPrimaryQuickbar(ItemDefinition) ? EFortQuickBars::Primary : EFortQuickBars::Secondary, SlotIndex);
bool bForce; // (Parm, ZeroConstructor, IsPlainOldData) }
} AFortQuickBars_ServerRemoveItemInternal_Params{ItemGuid, false, true};
QuickBars->ProcessEvent(ServerRemoveItemInternalFn, &AFortQuickBars_ServerRemoveItemInternal_Params);
} }
} }

View File

@@ -34,5 +34,18 @@ char UFortInventoryInterface::RemoveInventoryItemHook(__int64 a1, FGuid a2, int
if (bShouldUpdate) if (bShouldUpdate)
WorldInventory->Update(); WorldInventory->Update();
if (Engine_Version < 424)
{
auto Pawn = PlayerController->GetMyFortPawn();
if (Pawn)
{
auto CurrentWeapon = Pawn->GetCurrentWeapon();
if (CurrentWeapon)
WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), CurrentWeapon->GetAmmoCount());
}
}
return true; return true;
} }

View File

@@ -67,8 +67,7 @@ void AFortPawn::NetMulticast_Athena_BatchedDamageCuesHook(UObject* Context, FFra
if (!WorldInventory || !CurrentWeapon) if (!WorldInventory || !CurrentWeapon)
return NetMulticast_Athena_BatchedDamageCuesOriginal(Context, Stack, Ret); return NetMulticast_Athena_BatchedDamageCuesOriginal(Context, Stack, Ret);
static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount"); auto AmmoCount = CurrentWeapon->GetAmmoCount();
auto AmmoCount = CurrentWeapon->Get<int>(AmmoCountOffset);
WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount); WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount);

View File

@@ -94,16 +94,6 @@ void AFortPlayerController::ServerExecuteInventoryItemHook(AFortPlayerController
if (!ItemDefinition) if (!ItemDefinition)
return; return;
if (Engine_Version < 420) // wtf
{
static auto CurrentWeaponListOffset = Pawn->GetOffset("CurrentWeaponList");
auto& CurrentWeaponList = Pawn->Get<TArray<AFortWeapon*>>(CurrentWeaponListOffset);
CurrentWeaponList.Data = nullptr;
CurrentWeaponList.ArrayNum = 0;
CurrentWeaponList.ArrayMax = 0;
}
if (auto Weapon = Pawn->EquipWeaponDefinition((UFortWeaponItemDefinition*)ItemDefinition, ItemInstance->GetItemEntry()->GetItemGuid())) if (auto Weapon = Pawn->EquipWeaponDefinition((UFortWeaponItemDefinition*)ItemDefinition, ItemInstance->GetItemEntry()->GetItemGuid()))
{ {
if (Engine_Version < 420) if (Engine_Version < 420)

View File

@@ -0,0 +1,119 @@
#pragma once
#include "reboot.h"
enum class EFortQuickBars : uint8_t // WRONG!!! It has a creative quickbar, do not use unless you know what you are doing.
{
Primary = 0,
Secondary = 1,
Max_None = 2,
EFortQuickBars_MAX = 3
};
struct FQuickBarSlot
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.QuickBarSlot");
return Struct;
}
static int GetStructSize()
{
return GetStruct()->GetPropertiesSize();
}
TArray<FGuid>& GetItems()
{
static auto ItemsOffset = FindOffsetStruct("/Script/FortniteGame.QuickBarSlot", "Items");
return *(TArray<FGuid>*)(__int64(this) + ItemsOffset);
}
};
struct FQuickBar
{
TArray<FQuickBarSlot>& GetSlots()
{
static auto SlotsOffset = FindOffsetStruct("/Script/FortniteGame.QuickBar", "Slots");
return *(TArray<FQuickBarSlot>*)(__int64(this) + SlotsOffset);
}
};
class AFortQuickBars : public AActor
{
public:
void ServerRemoveItemInternal(const FGuid& Item, bool bFindReplacement, bool bForce)
{
static auto ServerRemoveItemInternalFn = FindObject<UFunction>("/Script/FortniteGame.FortQuickBars.ServerRemoveItemInternal");
struct
{
FGuid Item; // (Parm, IsPlainOldData)
bool bFindReplacement; // (Parm, ZeroConstructor, IsPlainOldData)
bool bForce; // (Parm, ZeroConstructor, IsPlainOldData)
} AFortQuickBars_ServerRemoveItemInternal_Params{ Item, bFindReplacement, bForce };
ProcessEvent(ServerRemoveItemInternalFn, &AFortQuickBars_ServerRemoveItemInternal_Params);
}
void EmptySlot(EFortQuickBars InQuickBar, int SlotIndex)
{
static auto EmptySlotFn = FindObject<UFunction>("/Script/FortniteGame.FortQuickBars.EmptySlot");
struct
{
EFortQuickBars InQuickBar; // (Parm, ZeroConstructor, IsPlainOldData)
int SlotIndex; // (Parm, ZeroConstructor, IsPlainOldData)
} AFortQuickBars_EmptySlot_Params{ InQuickBar, SlotIndex };
this->ProcessEvent(EmptySlotFn, &AFortQuickBars_EmptySlot_Params);
}
int GetSlotIndex(const FGuid& Item, EFortQuickBars QuickBars = EFortQuickBars::Max_None)
{
static auto PrimaryQuickBarOffset = GetOffset("PrimaryQuickBar");
static auto SecondaryQuickBarOffset = GetOffset("SecondaryQuickBar");
auto PrimaryQuickBar = GetPtr<FQuickBar>(PrimaryQuickBarOffset);
auto SecondaryQuickBar = GetPtr<FQuickBar>(SecondaryQuickBarOffset);
if (QuickBars == EFortQuickBars::Primary || QuickBars == EFortQuickBars::Max_None)
{
auto& PrimaryQuickBarSlots = PrimaryQuickBar->GetSlots();
for (int i = 0; i < PrimaryQuickBarSlots.Num(); i++)
{
auto Slot = PrimaryQuickBarSlots.AtPtr(i, FQuickBarSlot::GetStructSize());
auto& SlotItems = Slot->GetItems();
for (int z = 0; z < SlotItems.Num(); z++)
{
auto& CurrentItem = SlotItems.at(z);
if (CurrentItem == Item)
return i;
}
}
}
if (QuickBars == EFortQuickBars::Secondary || QuickBars == EFortQuickBars::Max_None)
{
auto& SecondaryQuickBarSlots = SecondaryQuickBar->GetSlots();
for (int i = 0; i < SecondaryQuickBarSlots.Num(); i++)
{
auto Slot = SecondaryQuickBarSlots.AtPtr(i, FQuickBarSlot::GetStructSize());
auto& SlotItems = Slot->GetItems();
for (int z = 0; z < SlotItems.Num(); z++)
{
auto& CurrentItem = SlotItems.at(z);
if (CurrentItem == Item)
return i;
}
}
}
return -1;
}
};

View File

@@ -22,8 +22,7 @@ void AFortWeapon::OnPlayImpactFXHook(AFortWeapon* Weapon, __int64 HitResult, uin
if (!WorldInventory || !CurrentWeapon) if (!WorldInventory || !CurrentWeapon)
return OnPlayImpactFXOriginal(Weapon, HitResult, ImpactPhysicalSurface, SpawnedPSC); return OnPlayImpactFXOriginal(Weapon, HitResult, ImpactPhysicalSurface, SpawnedPSC);
static auto AmmoCountOffset = CurrentWeapon->GetOffset("AmmoCount"); auto AmmoCount = CurrentWeapon->GetAmmoCount();
auto AmmoCount = CurrentWeapon->Get<int>(AmmoCountOffset);
WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount); WorldInventory->CorrectLoadedAmmo(CurrentWeapon->GetItemEntryGuid(), AmmoCount);

View File

@@ -23,6 +23,12 @@ public:
return Get<FGuid>(ItemEntryGuidOffset); return Get<FGuid>(ItemEntryGuidOffset);
} }
int& GetAmmoCount()
{
static auto AmmoCountOffset = GetOffset("AmmoCount");
return Get<int>(AmmoCountOffset);
}
static void OnPlayImpactFXHook(AFortWeapon* Weapon, __int64 HitResult, uint8_t ImpactPhysicalSurface, UObject* SpawnedPSC); static void OnPlayImpactFXHook(AFortWeapon* Weapon, __int64 HitResult, uint8_t ImpactPhysicalSurface, UObject* SpawnedPSC);
static void ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret); static void ServerReleaseWeaponAbilityHook(UObject* Context, FFrame* Stack, void* Ret);

View File

@@ -272,6 +272,7 @@
<ClInclude Include="FortPlayerState.h" /> <ClInclude Include="FortPlayerState.h" />
<ClInclude Include="FortPlayerStateAthena.h" /> <ClInclude Include="FortPlayerStateAthena.h" />
<ClInclude Include="FortPlaysetItemDefinition.h" /> <ClInclude Include="FortPlaysetItemDefinition.h" />
<ClInclude Include="FortQuickBars.h" />
<ClInclude Include="FortResourceItemDefinition.h" /> <ClInclude Include="FortResourceItemDefinition.h" />
<ClInclude Include="FortVolume.h" /> <ClInclude Include="FortVolume.h" />
<ClInclude Include="FortWeapon.h" /> <ClInclude Include="FortWeapon.h" />

View File

@@ -479,6 +479,9 @@
<ClInclude Include="vehicles.h"> <ClInclude Include="vehicles.h">
<Filter>Reboot\Public</Filter> <Filter>Reboot\Public</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="FortQuickBars.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Items</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Engine"> <Filter Include="Engine">

View File

@@ -482,7 +482,8 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal); Hooking::MinHook::Hook((PVOID)Addresses::CompletePickupAnimation, (PVOID)AFortPickup::CompletePickupAnimationHook, (PVOID*)&AFortPickup::CompletePickupAnimationOriginal);
Hooking::MinHook::Hook((PVOID)Addresses::CanActivateAbility, ReturnTrueHook); // ahhh wtf Hooking::MinHook::Hook((PVOID)Addresses::CanActivateAbility, ReturnTrueHook); // ahhh wtf
if (Fortnite_Version >= 2.5) // if (Fortnite_Version >= 2.5)
if (Engine_Version >= 419)
{ {
auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)FindFunctionCall(L"ServerRemoveInventoryItem", 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); Fortnite_Version >= 16 ? std::vector<uint8_t>{ 0x48, 0x8B, 0xC4 } : std::vector<uint8_t>{ 0x48, 0x89, 0x5C }), 0, true);

View File

@@ -325,7 +325,7 @@ static inline uint64 FindGetPlayerViewpoint()
LOG_INFO(LogDev, "GetPlayerViewpoint StringRef: 0x{:x}", __int64(Addrr) - __int64(GetModuleHandleW(0))); LOG_INFO(LogDev, "GetPlayerViewpoint StringRef: 0x{:x}", __int64(Addrr) - __int64(GetModuleHandleW(0)));
for (int i = 0; i < 1500; i++) for (int i = 0; i < 1200; i++)
{ {
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55) if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55)
{ {
@@ -336,6 +336,11 @@ static inline uint64 FindGetPlayerViewpoint()
{ {
return Addrr - i; return Addrr - i;
} }
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0xC3) // hmm
{
break;
}
} }
for (int i = 0; i < 1000; i++) for (int i = 0; i < 1000; i++)
@@ -954,9 +959,7 @@ static inline uint64 FindMcpIsDedicatedServerOffset()
if (Engine_Version == 421 || Engine_Version == 422) // checked on 5.41 & 6.21 & 7.30 if (Engine_Version == 421 || Engine_Version == 422) // checked on 5.41 & 6.21 & 7.30
return 0x28; return 0x28;
return 0x60; // 1.7.2 & 4.1 return 0x60; // 1.7.2 & 1.11 & 4.1
return 0;
} }
static inline uint64 FindGIsClient() static inline uint64 FindGIsClient()
@@ -1200,10 +1203,27 @@ static inline uint64 FindGiveAbilityAndActivateOnce()
if (Engine_Version == 426) if (Engine_Version == 426)
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 49 8B 40 10 49 8B D8 48 8B FA 48 8B F1").Get(); return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 49 8B 40 10 49 8B D8 48 8B FA 48 8B F1").Get();
auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500); auto Addrr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500).Get();
for (int i = 0; i < 1000; i++)
{
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x40 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x55)
{
return Addrr - i;
}
if (*(uint8_t*)(uint8_t*)(Addrr - i) == 0x48 && *(uint8_t*)(uint8_t*)(Addrr - i + 1) == 0x89 && *(uint8_t*)(uint8_t*)(Addrr - i + 2) == 0x5C)
{
return Addrr - i;
}
}
return 0;
/* auto Addr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500);
auto res = FindBytes(Addr, { 0x48, 0x89, 0x5C }, 1000, 0, true); auto res = FindBytes(Addr, { 0x48, 0x89, 0x5C }, 1000, 0, true);
return res; return res; */
} }
static inline uint64 FindGiveAbility() static inline uint64 FindGiveAbility()