a medium amount

fix some playlist starter loot, cleanup some code, fix death bugs on 1.8 and 1.7.2, fix reloading not taking items on 1.8 and 1.7.2, fix looting on s9, fix some s15 & s16 builds, fix bug with higher version looting
This commit is contained in:
Milxnor
2023-04-30 22:12:03 -04:00
parent 18f92ccf52
commit 02717f33f3
25 changed files with 477 additions and 240 deletions

View File

@@ -24,6 +24,11 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
auto BGAConsumableSpawner = AllBGAConsumableSpawners.at(i);
auto SpawnLocation = BGAConsumableSpawner->GetActorLocation();
FTransform SpawnTransform{};
SpawnTransform.Translation = SpawnLocation;
SpawnTransform.Scale3D = FVector{ 1, 1, 1 };
SpawnTransform.Rotation = FQuat();
if (FBuildingGameplayActorSpawnDetails::GetStruct())
{
// todo handle?
@@ -33,6 +38,7 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
else
{
// SpawnLocation.Z += 100;
// SpawnLocation.Z -= 50; // proper frfr
}
static auto SpawnLootTierGroupOffset = BGAConsumableSpawner->GetOffset("SpawnLootTierGroup");
@@ -45,7 +51,7 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
static auto ConsumableClassOffset = LootDrop.ItemDefinition->GetOffset("ConsumableClass");
auto ConsumableClassSoft = LootDrop.ItemDefinition->GetPtr<TSoftObjectPtr<UClass>>(ConsumableClassOffset);
static auto BlueprintGeneratedClassClass = FindObject<UClass>("/Script/Engine.BlueprintGeneratedClass");
static auto BlueprintGeneratedClassClass = FindObject<UClass>(L"/Script/Engine.BlueprintGeneratedClass");
auto StrongConsumableClass = ConsumableClassSoft->Get(BlueprintGeneratedClassClass, true);
if (!StrongConsumableClass)
@@ -54,12 +60,20 @@ void SpawnBGAs() // hahah not "proper", there's a function that we can hook and
continue;
}
auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnLocation);
bool bDeferConstruction = false; // hm?
FActorSpawnParameters SpawnParameters{};
// SpawnParameters.ObjectFlags = RF_Transactional; // idk fortnite does this i think
SpawnParameters.bDeferConstruction = bDeferConstruction;
auto ConsumableActor = GetWorld()->SpawnActor<ABuildingGameplayActor>(StrongConsumableClass, SpawnTransform, SpawnParameters);
if (ConsumableActor)
{
// BeginDeferredActorSpawnFromClass ??
// ConsumableActor->InitializeBuildingActor(nullptr, nullptr, true); // idk UFortKismetLibrary::SpawnBuildingGameplayActor does this
if (bDeferConstruction)
UGameplayStatics::FinishSpawningActor(ConsumableActor, SpawnTransform); // what
ConsumableActor->InitializeBuildingActor(nullptr, nullptr, true); // idk UFortKismetLibrary::SpawnBuildingGameplayActor does this
}
}
}

View File

@@ -0,0 +1,26 @@
#include "BuildingContainer.h"
#include "FortPickup.h"
#include "FortLootPackage.h"
#include "FortGameModeAthena.h"
bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
{
FVector LocationToSpawnLoot = this->GetActorLocation() + this->GetActorRightVector() * 70.f + FVector{ 0, 0, 50 };
static auto SearchLootTierGroupOffset = this->GetOffset("SearchLootTierGroup");
auto RedirectedLootTier = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode())->RedirectLootTier(this->Get<FName>(SearchLootTierGroupOffset));
// LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
auto LootDrops = PickLootDrops(RedirectedLootTier, true);
// LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
for (int i = 0; i < LootDrops.size(); i++)
{
auto& lootDrop = LootDrops.at(i);
AFortPickup::SpawnPickup(lootDrop.ItemDefinition, LocationToSpawnLoot, lootDrop.Count, EFortPickupSourceTypeFlag::Container, EFortPickupSpawnSource::Unset, lootDrop.LoadedAmmo);
}
return true;
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "BuildingSMActor.h"
#include "FortPawn.h"
class ABuildingContainer : public ABuildingSMActor
{
@@ -12,6 +13,8 @@ public:
return this->ReadBitfieldValue(bDestroyContainerOnSearchOffset, bDestroyContainerOnSearchFieldMask);
}
bool SpawnLoot(AFortPawn* Pawn);
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.BuildingContainer");

View File

@@ -27,3 +27,10 @@ struct FDataTableRowHandle
UDataTable* DataTable; // 0x0000(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FName RowName; // 0x0008(0x0008) (Edit, BlueprintVisible, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
};
template <typename StructType = uint8>
struct RowNameAndRowData
{
FName RowName;
StructType* RowData;
};

View File

@@ -0,0 +1,8 @@
#pragma once
#include "FortAthenaMutator.h"
class AFortAthenaMutator_LoadoutSwap : public AFortAthenaMutator
{
public:
};

View File

@@ -0,0 +1,15 @@
#pragma once
#include "FortAthenaMutator.h"
#include "reboot.h"
class AFortAthenaMutator_TDM : public AFortAthenaMutator
{
public:
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortAthenaMutator_TDM");
return Class;
}
};

View File

@@ -103,6 +103,8 @@ struct FFortItemEntry : FFastArraySerializerItem
void CopyFromAnotherItemEntry(FFortItemEntry* OtherItemEntry, bool bCopyGuid = false)
{
// We can use FortItemEntryStruct->CopyScriptStruct
FGuid OldGuid = this->GetItemGuid();
if (false)

View File

@@ -74,9 +74,8 @@ static FFortLootPackageData* GetLootPackage(std::vector<FFortLootPackageData*>&
struct FFortGameFeatureLootTableData
{
public:
TSoftObjectPtr<UDataTable> LootTierData; // 0x0(0x28)(Edit, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic)
TSoftObjectPtr<UDataTable> LootPackageData; // 0x28(0x28)(Edit, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic)
TSoftObjectPtr<UDataTable> LootTierData;
TSoftObjectPtr<UDataTable> LootPackageData;
};
std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recursive)
@@ -203,7 +202,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
if (ptr)
{
if (bOverrideIsComposite)
/* if (bOverrideIsComposite)
{
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
@@ -218,7 +217,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
LPTables.push_back(ParentTable);
}
}
}
} */
LPTables.push_back(ptr);
}
@@ -257,7 +256,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
if (ptr)
{
if (bOverrideIsComposite)
/* if (bOverrideIsComposite)
{
static auto ParentTablesOffset = ptr->GetOffset("ParentTables");
@@ -272,7 +271,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
LTDTables.push_back(ParentTable);
}
}
}
} */
LTDTables.push_back(ptr);
}
@@ -312,7 +311,7 @@ std::vector<LootDrop> PickLootDrops(FName TierGroupName, bool bPrint, int recurs
}
}
if (Fortnite_Version <= 6) // ahhh
if (Fortnite_Version <= 6 || std::floor(Fortnite_Version) == 9) // ahhh
{
LTDTables.clear();
LPTables.clear();

View File

@@ -22,6 +22,8 @@
#include "vendingmachine.h"
#include "KismetSystemLibrary.h"
#include "gui.h"
#include "FortAthenaMutator_InventoryOverride.h"
#include "FortAthenaMutator_TDM.h"
void AFortPlayerController::ClientReportDamagedResourceBuilding(ABuildingSMActor* BuildingSMActor, EFortResourceType PotentialResourceType, int PotentialResourceCount, bool bDestroyed, bool bJustHitWeakspot)
{
@@ -416,22 +418,7 @@ void AFortPlayerController::ServerAttemptInteractHook(UObject* Context, FFrame*
static auto OnRep_bAlreadySearchedFn = FindObject<UFunction>(L"/Script/FortniteGame.BuildingContainer.OnRep_bAlreadySearched");
BuildingContainer->ProcessEvent(OnRep_bAlreadySearchedFn);
static auto SearchLootTierGroupOffset = BuildingContainer->GetOffset("SearchLootTierGroup");
auto RedirectedLootTier = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode(), false)->RedirectLootTier(BuildingContainer->Get<FName>(SearchLootTierGroupOffset));
LOG_INFO(LogInteraction, "RedirectedLootTier: {}", RedirectedLootTier.ToString());
auto LootDrops = PickLootDrops(RedirectedLootTier, true);
LOG_INFO(LogInteraction, "LootDrops.size(): {}", LootDrops.size());
for (int i = 0; i < LootDrops.size(); i++)
{
auto& lootDrop = LootDrops.at(i);
AFortPickup::SpawnPickup(lootDrop.ItemDefinition, LocationToSpawnLoot, lootDrop.Count, EFortPickupSourceTypeFlag::Container, EFortPickupSpawnSource::Unset, lootDrop.LoadedAmmo
// , (AFortPawn*)PlayerController->GetPawn() // should we put this here?
);
}
BuildingContainer->SpawnLoot(PlayerController->GetMyFortPawn());
// if (BuildingContainer->ShouldDestroyOnSearch())
// BuildingContainer->K2_DestroyActor();
@@ -1135,188 +1122,231 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
static auto FallDamageEnumValue = 1;
auto DeathInfo = (void*)(__int64(DeadPlayerState) + MemberOffsets::FortPlayerStateAthena::DeathInfo); // Alloc<void>(DeathInfoStructSize);
RtlSecureZeroMemory(DeathInfo, DeathInfoStructSize);
uint8_t DeathCause = 0;
auto/*&*/ Tags = MemberOffsets::FortPlayerPawn::CorrectTags == 0 ? FGameplayTagContainer()
: DeadPawn->Get<FGameplayTagContainer>(MemberOffsets::FortPlayerPawn::CorrectTags);
// *(FGameplayTagContainer*)(__int64(DeathReport) + MemberOffsets::DeathReport::Tags);
// LOG_INFO(LogDev, "Tags: {}", Tags.ToStringSimple(true));
auto DeathCause = ToDeathCause(Tags, false, DeadPawn); // DeadPawn->IsDBNO() ??
LOG_INFO(LogDev, "DeathCause: {}", (int)DeathCause);
*(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bDBNO) = DeadPawn->IsDBNO();
*(uint8*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathCause) = DeathCause;
*(AActor**)(__int64(DeathInfo) + MemberOffsets::DeathInfo::FinisherOrDowner) = KillerPlayerState ? KillerPlayerState : DeadPlayerState;
if (MemberOffsets::DeathInfo::DeathLocation != -1)
*(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) = DeathLocation;
if (MemberOffsets::DeathInfo::DeathTags != -1)
*(FGameplayTagContainer*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathTags) = Tags;
if (MemberOffsets::DeathInfo::bInitialized != -1)
*(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bInitialized) = true;
if (DeathCause == FallDamageEnumValue)
if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11)
{
if (MemberOffsets::FortPlayerPawnAthena::LastFallDistance != -1)
*(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = DeadPawn->Get<float>(MemberOffsets::FortPlayerPawnAthena::LastFallDistance);
auto DeathInfo = (void*)(__int64(DeadPlayerState) + MemberOffsets::FortPlayerStateAthena::DeathInfo); // Alloc<void>(DeathInfoStructSize);
RtlSecureZeroMemory(DeathInfo, DeathInfoStructSize);
auto/*&*/ Tags = MemberOffsets::FortPlayerPawn::CorrectTags == 0 ? FGameplayTagContainer()
: DeadPawn->Get<FGameplayTagContainer>(MemberOffsets::FortPlayerPawn::CorrectTags);
// *(FGameplayTagContainer*)(__int64(DeathReport) + MemberOffsets::DeathReport::Tags);
// LOG_INFO(LogDev, "Tags: {}", Tags.ToStringSimple(true));
DeathCause = ToDeathCause(Tags, false, DeadPawn); // DeadPawn->IsDBNO() ??
LOG_INFO(LogDev, "DeathCause: {}", (int)DeathCause);
*(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bDBNO) = DeadPawn->IsDBNO();
*(uint8*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathCause) = DeathCause;
*(AActor**)(__int64(DeathInfo) + MemberOffsets::DeathInfo::FinisherOrDowner) = KillerPlayerState ? KillerPlayerState : DeadPlayerState;
if (MemberOffsets::DeathInfo::DeathLocation != -1)
*(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) = DeathLocation;
if (MemberOffsets::DeathInfo::DeathTags != -1)
*(FGameplayTagContainer*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathTags) = Tags;
if (MemberOffsets::DeathInfo::bInitialized != -1)
*(bool*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::bInitialized) = true;
if (DeathCause == FallDamageEnumValue)
{
if (MemberOffsets::FortPlayerPawnAthena::LastFallDistance != -1)
*(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = DeadPawn->Get<float>(MemberOffsets::FortPlayerPawnAthena::LastFallDistance);
}
else
{
if (MemberOffsets::DeathInfo::Distance != -1)
*(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = KillerPawn ? KillerPawn->GetDistanceTo(DeadPawn) : 0;
}
if (MemberOffsets::FortPlayerState::PawnDeathLocation != -1)
DeadPlayerState->Get<FVector>(MemberOffsets::FortPlayerState::PawnDeathLocation) = DeathLocation;
static auto OnRep_DeathInfoFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerStateAthena.OnRep_DeathInfo");
if (OnRep_DeathInfoFn)
{
DeadPlayerState->ProcessEvent(OnRep_DeathInfoFn);
}
if (KillerPlayerState && KillerPlayerState != DeadPlayerState)
{
if (MemberOffsets::FortPlayerStateAthena::KillScore != -1)
KillerPlayerState->Get<int>(MemberOffsets::FortPlayerStateAthena::KillScore)++;
if (MemberOffsets::FortPlayerStateAthena::TeamKillScore != -1)
KillerPlayerState->Get<int>(MemberOffsets::FortPlayerStateAthena::TeamKillScore)++;
KillerPlayerState->ClientReportKill(DeadPlayerState);
/* LoopMutators([&](AFortAthenaMutator* Mutator) {
if (auto TDM_Mutator = Cast<AFortAthenaMutator_TDM>(Mutator))
{
struct
{
int EventId; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
int EventParam1; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
int EventParam2; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
int EventParam3; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
} AFortAthenaMutator_TDM_OnMutatorGameplayEvent_Params{ 1, 0, 0, 0 };
static auto TDM_OnMutatorGameplayEventFn = FindObject<UFunction>("/Script/FortniteGame.FortAthenaMutator_TDM.OnMutatorGameplayEvent");
TDM_Mutator->ProcessEvent(TDM_OnMutatorGameplayEventFn, &AFortAthenaMutator_TDM_OnMutatorGameplayEvent_Params);
}
}); */
// KillerPlayerState->OnRep_Kills();
}
// LOG_INFO(LogDev, "Reported kill.");
/* if (KillerPawn && KillerPawn != DeadPawn)
{
KillerPawn->SetHealth(100);
KillerPawn->SetShield(100);
} */
}
else
{
if (MemberOffsets::DeathInfo::Distance != -1)
*(float*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::Distance) = KillerPawn ? KillerPawn->GetDistanceTo(DeadPawn) : 0;
}
if (MemberOffsets::FortPlayerState::PawnDeathLocation != -1)
DeadPlayerState->Get<FVector>(MemberOffsets::FortPlayerState::PawnDeathLocation) = DeathLocation;
static auto OnRep_DeathInfoFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerStateAthena.OnRep_DeathInfo");
if (OnRep_DeathInfoFn)
{
DeadPlayerState->ProcessEvent(OnRep_DeathInfoFn);
}
if (KillerPlayerState && KillerPlayerState != DeadPlayerState)
{
KillerPlayerState->Get<int>(MemberOffsets::FortPlayerStateAthena::KillScore)++;
if (MemberOffsets::FortPlayerStateAthena::TeamKillScore != -1)
KillerPlayerState->Get<int>(MemberOffsets::FortPlayerStateAthena::TeamKillScore)++;
KillerPlayerState->ClientReportKill(DeadPlayerState);
// KillerPlayerState->OnRep_Kills();
}
LOG_INFO(LogDev, "Reported kill.");
/* if (KillerPawn && KillerPawn != DeadPawn)
{
KillerPawn->SetHealth(100);
KillerPawn->SetShield(100);
} */
bool bIsRespawningAllowed = GameState->IsRespawningAllowed(DeadPlayerState);
if (!bIsRespawningAllowed)
{
auto WorldInventory = PlayerController->GetWorldInventory();
bool bDropInventory = true;
if (!WorldInventory)
return ClientOnPawnDiedOriginal(PlayerController, DeathReport);
LoopMutators([&](AFortAthenaMutator* Mutator)
{
if (auto FortAthenaMutator_InventoryOverride = Cast<AFortAthenaMutator_InventoryOverride>(Mutator))
{
if (FortAthenaMutator_InventoryOverride->GetDropAllItemsOverride(DeadPlayerState->GetTeamIndex()) == EAthenaLootDropOverride::ForceKeep)
{
bDropInventory = false;
}
}
}
);
auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances();
std::vector<std::pair<FGuid, int>> GuidAndCountsToRemove;
for (int i = 0; i < ItemInstances.Num(); i++)
if (bDropInventory)
{
auto ItemInstance = ItemInstances.at(i);
auto WorldInventory = PlayerController->GetWorldInventory();
// LOG_INFO(LogDev, "[{}/{}] CurrentItemInstance {}", i, ItemInstances.Num(), __int64(ItemInstance));
if (!WorldInventory)
return ClientOnPawnDiedOriginal(PlayerController, DeathReport);
if (!ItemInstance)
continue;
auto& ItemInstances = WorldInventory->GetItemList().GetItemInstances();
auto ItemEntry = ItemInstance->GetItemEntry();
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemEntry->GetItemDefinition());
std::vector<std::pair<FGuid, int>> GuidAndCountsToRemove;
// LOG_INFO(LogDev, "[{}/{}] WorldItemDefinition {}", i, ItemInstances.Num(), WorldItemDefinition ? WorldItemDefinition->GetFullName() : "InvalidObject");
for (int i = 0; i < ItemInstances.Num(); i++)
{
auto ItemInstance = ItemInstances.at(i);
if (!WorldItemDefinition)
continue;
// LOG_INFO(LogDev, "[{}/{}] CurrentItemInstance {}", i, ItemInstances.Num(), __int64(ItemInstance));
auto ShouldBeDropped = WorldItemDefinition->CanBeDropped(); // WorldItemDefinition->ShouldDropOnDeath();
if (!ItemInstance)
continue;
// LOG_INFO(LogDev, "[{}/{}] ShouldBeDropped {}", i, ItemInstances.Num(), ShouldBeDropped);
auto ItemEntry = ItemInstance->GetItemEntry();
auto WorldItemDefinition = Cast<UFortWorldItemDefinition>(ItemEntry->GetItemDefinition());
if (!ShouldBeDropped)
continue;
// LOG_INFO(LogDev, "[{}/{}] WorldItemDefinition {}", i, ItemInstances.Num(), WorldItemDefinition ? WorldItemDefinition->GetFullName() : "InvalidObject");
AFortPickup::SpawnPickup(WorldItemDefinition, DeathLocation, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::PlayerElimination,
ItemEntry->GetLoadedAmmo());
if (!WorldItemDefinition)
continue;
GuidAndCountsToRemove.push_back({ ItemEntry->GetItemGuid(), ItemEntry->GetCount() });
// WorldInventory->RemoveItem(ItemEntry->GetItemGuid(), nullptr, ItemEntry->GetCount());
auto ShouldBeDropped = WorldItemDefinition->CanBeDropped(); // WorldItemDefinition->ShouldDropOnDeath();
// LOG_INFO(LogDev, "[{}/{}] ShouldBeDropped {}", i, ItemInstances.Num(), ShouldBeDropped);
if (!ShouldBeDropped)
continue;
AFortPickup::SpawnPickup(WorldItemDefinition, DeathLocation, ItemEntry->GetCount(), EFortPickupSourceTypeFlag::Player, EFortPickupSpawnSource::PlayerElimination,
ItemEntry->GetLoadedAmmo());
GuidAndCountsToRemove.push_back({ ItemEntry->GetItemGuid(), ItemEntry->GetCount() });
// WorldInventory->RemoveItem(ItemEntry->GetItemGuid(), nullptr, ItemEntry->GetCount());
}
for (auto& Pair : GuidAndCountsToRemove)
{
WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true);
}
WorldInventory->Update();
}
for (auto& Pair : GuidAndCountsToRemove)
{
WorldInventory->RemoveItem(Pair.first, nullptr, Pair.second, true);
}
WorldInventory->Update();
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
if (!DeadPawn->IsDBNO())
{
static void (*RemoveFromAlivePlayers)(AFortGameModeAthena* GameMode, AFortPlayerController* PlayerController, APlayerState* PlayerState, APawn* FinisherPawn,
UFortWeaponItemDefinition* FinishingWeapon, uint8_t DeathCause, char a7)
= decltype(RemoveFromAlivePlayers)(Addresses::RemoveFromAlivePlayers);
AActor* DamageCauser = *(AActor**)(__int64(DeathReport) + MemberOffsets::DeathReport::DamageCauser);
UFortWeaponItemDefinition* KillerWeaponDef = nullptr;
static auto FortProjectileBaseClass = FindObject<UClass>(L"/Script/FortniteGame.FortProjectileBase");
LOG_INFO(LogDev, "FortProjectileBaseClass: {}", __int64(FortProjectileBaseClass));
if (DamageCauser)
if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11)
{
if (DamageCauser->IsA(FortProjectileBaseClass))
static void (*RemoveFromAlivePlayers)(AFortGameModeAthena * GameMode, AFortPlayerController * PlayerController, APlayerState * PlayerState, APawn * FinisherPawn,
UFortWeaponItemDefinition * FinishingWeapon, uint8_t DeathCause, char a7)
= decltype(RemoveFromAlivePlayers)(Addresses::RemoveFromAlivePlayers);
AActor* DamageCauser = *(AActor**)(__int64(DeathReport) + MemberOffsets::DeathReport::DamageCauser);
UFortWeaponItemDefinition* KillerWeaponDef = nullptr;
static auto FortProjectileBaseClass = FindObject<UClass>(L"/Script/FortniteGame.FortProjectileBase");
LOG_INFO(LogDev, "FortProjectileBaseClass: {}", __int64(FortProjectileBaseClass));
if (DamageCauser)
{
LOG_INFO(LogDev, "From a projectile!");
auto Owner = Cast<AFortWeapon>(DamageCauser->GetOwner());
KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys?
}
if (auto Weapon = Cast<AFortWeapon>(DamageCauser))
{
LOG_INFO(LogDev, "From a weapon!");
KillerWeaponDef = Weapon->GetWeaponData();
}
}
// LOG_INFO(LogDev, "KillerWeaponDef: {}", KillerWeaponDef ? KillerWeaponDef->GetFullName() : "InvalidObject");
RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0);
LOG_INFO(LogDev, "Removed!");
if (Fortnite_Version < 6) // Spectating
{
static auto bAllowSpectateAfterDeathOffset = GameMode->GetOffset("bAllowSpectateAfterDeath");
bool bAllowSpectate = false; // GameMode->Get<bool>(bAllowSpectateAfterDeathOffset);
LOG_INFO(LogDev, "bAllowSpectate: {}", bAllowSpectate);
if (bAllowSpectate)
{
LOG_INFO(LogDev, "Starting Spectating!");
static auto PlayerToSpectateOnDeathOffset = PlayerController->GetOffset("PlayerToSpectateOnDeath");
PlayerController->Get<APawn*>(PlayerToSpectateOnDeathOffset) = KillerPawn;
PlayerControllersDead.push_back(PlayerController);
/* if (numValidElements < PlayerControllersDead.size())
if (DamageCauser->IsA(FortProjectileBaseClass))
{
PlayerControllersDead[numValidElements].store(PlayerController);
numValidElements.fetch_add(1);
} */
static bool bCreatedThread = false;
if (!bCreatedThread)
LOG_INFO(LogDev, "From a projectile!");
auto Owner = Cast<AFortWeapon>(DamageCauser->GetOwner());
KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys?
}
if (auto Weapon = Cast<AFortWeapon>(DamageCauser))
{
bCreatedThread = true;
LOG_INFO(LogDev, "From a weapon!");
KillerWeaponDef = Weapon->GetWeaponData();
}
}
CreateThread(0, 0, SpectateThread, 0, 0, 0);
// LOG_INFO(LogDev, "KillerWeaponDef: {}", KillerWeaponDef ? KillerWeaponDef->GetFullName() : "InvalidObject");
RemoveFromAlivePlayers(GameMode, PlayerController, KillerPlayerState == DeadPlayerState ? nullptr : KillerPlayerState, KillerPawn, KillerWeaponDef, DeathCause, 0);
LOG_INFO(LogDev, "Removed!");
if (Fortnite_Version < 6) // Spectating
{
static auto bAllowSpectateAfterDeathOffset = GameMode->GetOffset("bAllowSpectateAfterDeath");
bool bAllowSpectate = false; // GameMode->Get<bool>(bAllowSpectateAfterDeathOffset);
LOG_INFO(LogDev, "bAllowSpectate: {}", bAllowSpectate);
if (bAllowSpectate)
{
LOG_INFO(LogDev, "Starting Spectating!");
static auto PlayerToSpectateOnDeathOffset = PlayerController->GetOffset("PlayerToSpectateOnDeath");
PlayerController->Get<APawn*>(PlayerToSpectateOnDeathOffset) = KillerPawn;
PlayerControllersDead.push_back(PlayerController);
/* if (numValidElements < PlayerControllersDead.size())
{
PlayerControllersDead[numValidElements].store(PlayerController);
numValidElements.fetch_add(1);
} */
static bool bCreatedThread = false;
if (!bCreatedThread)
{
bCreatedThread = true;
CreateThread(0, 0, SpectateThread, 0, 0, 0);
}
}
}
}

View File

@@ -95,7 +95,7 @@ public:
bool HasTryPickupSwap()
{
static auto bTryPickupSwapOffset = GetOffset("bTryPickupSwap");
static auto bTryPickupSwapOffset = GetOffset("bTryPickupSwap", false);
return bTryPickupSwapOffset != -1;
}

View File

@@ -8,6 +8,7 @@
#include "hooking.h"
#include "FortAthenaMutator_GiveItemsAtGamePhaseStep.h"
#include "DataTableFunctionLibrary.h"
#include "FortAthenaMutator_InventoryOverride.h"
void AFortPlayerControllerAthena::StartGhostModeHook(UObject* Context, FFrame* Stack, void* Ret)
{
@@ -135,20 +136,15 @@ void AFortPlayerControllerAthena::EnterAircraftHook(UObject* PC, AActor* Aircraf
std::vector<std::pair<AFortAthenaMutator*, UFunction*>> FunctionsToCall;
for (int i = 0; i < AllMutators.Num(); i++)
{
auto Mutator = (AFortAthenaMutator*)AllMutators.at(i);
LOG_INFO(LogDev, "[{}] Mutator: {}", i, Mutator->GetFullName());
FunctionsToCall.push_back(std::make_pair(Mutator, Mutator->FindFunction("OnGamePhaseStepChanged")));
LoopMutators([&](AFortAthenaMutator* Mutator) { FunctionsToCall.push_back(std::make_pair(Mutator, Mutator->FindFunction("OnGamePhaseStepChanged"))); });
auto HandleGiveItemsAtGamePhaseStepMutator = [&](AFortAthenaMutator* Mutator) {
if (auto GiveItemsAtGamePhaseStepMutator = Cast<AFortAthenaMutator_GiveItemsAtGamePhaseStep>(Mutator))
{
auto PhaseToGive = GiveItemsAtGamePhaseStepMutator->GetPhaseToGiveItems();
auto& ItemsToGive = GiveItemsAtGamePhaseStepMutator->GetItemsToGive();
LOG_INFO(LogDev, "[{}] PhaseToGiveItems: {} ItemsToGive.Num(): {}", i, (int)PhaseToGive, ItemsToGive.Num());
// LOG_INFO(LogDev, "[{}] PhaseToGiveItems: {} ItemsToGive.Num(): {}", i, (int)PhaseToGive, ItemsToGive.Num());
if (PhaseToGive <= 5) // Flying or lower
{
@@ -166,27 +162,54 @@ void AFortPlayerControllerAthena::EnterAircraftHook(UObject* PC, AActor* Aircraf
Out2 = UDataTableFunctionLibrary::EvaluateCurveTableRow(ItemToGive->GetNumberToGive().GetCurve().CurveTable, ItemToGive->GetNumberToGive().GetCurve().RowName, 0.f);
}
LOG_INFO(LogDev, "[{}] [{}] Out2: {} ItemToGive.ItemToDrop: {}", i, j, Out2, ItemToGive->GetItemToDrop()->IsValidLowLevel() ? ItemToGive->GetItemToDrop()->GetFullName() : "BadRead");
LOG_INFO(LogDev, "[{}] Out2: {} ItemToGive.ItemToDrop: {}", j, Out2, ItemToGive->GetItemToDrop()->IsValidLowLevel() ? ItemToGive->GetItemToDrop()->GetFullName() : "BadRead");
if (!Out2)
if (!Out2) // ?
continue;
WorldInventory->AddItem(ItemToGive->GetItemToDrop(), nullptr, Out2);
}
}
}
/* else if (auto GGMutator = Cast<AFortAthenaMutator_GG>(Mutator))
};
LoopMutators(HandleGiveItemsAtGamePhaseStepMutator);
/* if (auto GGMutator = Cast<AFortAthenaMutator_GG>(Mutator))
{
auto& WeaponEntries = GGMutator->GetWeaponEntries();
LOG_INFO(LogDev, "[{}] WeaponEntries.Num(): {}", i, WeaponEntries.Num());
for (int j = 0; j < WeaponEntries.Num(); j++)
{
auto& WeaponEntries = GGMutator->GetWeaponEntries();
WorldInventory->AddItem(WeaponEntries.at(j).Weapon, nullptr, 1);
}
} */
LOG_INFO(LogDev, "[{}] WeaponEntries.Num(): {}", i, WeaponEntries.Num());
auto PlayerStateAthena = Cast<AFortPlayerStateAthena>(PlayerController->GetPlayerState());
for (int j = 0; j < WeaponEntries.Num(); j++)
auto AddInventoryOverrideTeamLoadouts = [&](AFortAthenaMutator* Mutator)
{
if (auto InventoryOverride = Cast<AFortAthenaMutator_InventoryOverride>(Mutator))
{
auto TeamIndex = PlayerStateAthena->GetTeamIndex();
auto LoadoutTeam = InventoryOverride->GetLoadoutTeamForTeamIndex(TeamIndex);
if (LoadoutTeam.UpdateOverrideType == EAthenaInventorySpawnOverride::AircraftPhaseOnly)
{
WorldInventory->AddItem(WeaponEntries.at(j).Weapon, nullptr, 1);
auto LoadoutContainer = InventoryOverride->GetLoadoutContainerForTeamIndex(TeamIndex);
for (int i = 0; i < LoadoutContainer.Loadout.Num(); i++)
{
auto& ItemAndCount = LoadoutContainer.Loadout.at(i);
WorldInventory->AddItem(ItemAndCount.GetItem(), nullptr, ItemAndCount.GetCount());
}
}
} */
}
}
};
LoopMutators(AddInventoryOverrideTeamLoadouts);
static int LastNum1 = 3125;

View File

@@ -8,6 +8,7 @@
#include "GameplayTagContainer.h"
#include "BuildingActor.h"
#include "FortPlayerPawnAthena.h"
#include "GameplayAbilityTypes.h"
struct FGameplayTagRequirements
{
@@ -236,6 +237,41 @@ public:
}
};
struct FAthenaScoreData
{
};
struct FWinConditionScoreData
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/FortniteGame.WinConditionScoreData");
return Struct;
}
static int GetStructSize() { return GetStruct()->GetPropertiesSize(); }
FScalableFloat* GetGoalScore()
{
static auto GoalScoreOffset = FindOffsetStruct("/Script/FortniteGame.WinConditionScoreData", "GoalScore");
return (FScalableFloat*)(__int64(this) + GoalScoreOffset);
}
FScalableFloat* GetBigScoreThreshold()
{
static auto BigScoreThresholdOffset = FindOffsetStruct("/Script/FortniteGame.WinConditionScoreData", "BigScoreThreshold");
return (FScalableFloat*)(__int64(this) + BigScoreThresholdOffset);
}
TArray<FAthenaScoreData>& GetScoreDataList()
{
static auto ScoreDataListOffset = FindOffsetStruct("/Script/FortniteGame.WinConditionScoreData", "ScoreDataList");
return *(TArray<FAthenaScoreData>*)(__int64(this) + ScoreDataListOffset);
}
};
class UFortPlaylist : public UObject
{
public:
@@ -245,6 +281,12 @@ public:
return this->Get<TArray<TSoftObjectPtr<UFortGameplayModifierItemDefinition>>>(ModifierListOffset);
}
FWinConditionScoreData* GetScoringData()
{
static auto ScoringDataOffset = GetOffset("ScoringData");
return GetPtr<FWinConditionScoreData>(ScoringDataOffset);
}
void ApplyModifiersToActor(AActor* Actor)
{
if (!Actor)

View File

@@ -107,20 +107,16 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
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");
static UFortItemDefinition* EditToolItemDefinition = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/EditTool.EditTool");
static UFortItemDefinition* BuildingItemData_Wall = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Wall.BuildingItemData_Wall");
static UFortItemDefinition* BuildingItemData_Floor = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Floor.BuildingItemData_Floor");
static UFortItemDefinition* BuildingItemData_Stair_W = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_Stair_W.BuildingItemData_Stair_W");
static UFortItemDefinition* BuildingItemData_RoofS = FindObject<UFortItemDefinition>(L"/Game/Items/Weapons/BuildingTools/BuildingItemData_RoofS.BuildingItemData_RoofS");
static UFortItemDefinition* WoodItemData = FindObject<UFortItemDefinition>(L"/Game/Items/ResourcePickups/WoodItemData.WoodItemData");
static UFortItemDefinition* DamageTrap = FindObject<UFortItemDefinition>(L"/Game/Athena/Items/Traps/TID_ContextTrap_Athena.TID_ContextTrap_Athena");
auto& StartingItems = ((AFortGameModeAthena*)GameMode)->GetStartingItems();
WorldInventory->AddItem(PickaxeDefinition, nullptr);
WorldInventory->AddItem(EditToolItemDefinition, nullptr);
WorldInventory->AddItem(BuildingItemData_Wall, nullptr);
WorldInventory->AddItem(BuildingItemData_Floor, nullptr);
WorldInventory->AddItem(BuildingItemData_Stair_W, nullptr);
WorldInventory->AddItem(BuildingItemData_RoofS, nullptr);
for (int i = 0; i < StartingItems.Num(); i++)
{
auto& StartingItem = StartingItems.at(i);
WorldInventory->AddItem(StartingItem.GetItem(), nullptr, StartingItem.GetCount());
}
/* if (Globals::bLateGame)
{
@@ -142,12 +138,17 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
if (auto InventoryOverride = Cast<AFortAthenaMutator_InventoryOverride>(Mutator))
{
auto TeamIndex = PlayerStateAthena->GetTeamIndex();
auto LoadoutContainer = InventoryOverride->GetLoadoutContainerForTeamIndex(TeamIndex);
auto LoadoutTeam = InventoryOverride->GetLoadoutTeamForTeamIndex(TeamIndex);
for (int i = 0; i < LoadoutContainer.Loadout.Num(); i++)
if (LoadoutTeam.UpdateOverrideType == EAthenaInventorySpawnOverride::Always)
{
auto& ItemAndCount = LoadoutContainer.Loadout.at(i);
WorldInventory->AddItem(ItemAndCount.GetItem(), nullptr, ItemAndCount.GetCount());
auto LoadoutContainer = InventoryOverride->GetLoadoutContainerForTeamIndex(TeamIndex);
for (int i = 0; i < LoadoutContainer.Loadout.Num(); i++)
{
auto& ItemAndCount = LoadoutContainer.Loadout.at(i);
WorldInventory->AddItem(ItemAndCount.GetItem(), nullptr, ItemAndCount.GetCount());
}
}
}
};

View File

@@ -74,6 +74,43 @@ void UGameplayStatics::RemovePlayer(APlayerController* Player, bool bDestroyPawn
defaultObj->ProcessEvent(fn, &UGameplayStatics_RemovePlayer_Params);
}
AActor* UGameplayStatics::BeginDeferredActorSpawnFromClass(const UObject* WorldContextObject, UClass* ActorClass, const FTransform& SpawnTransform, ESpawnActorCollisionHandlingMethod CollisionHandlingOverride, AActor* Owner)
{
static auto fn = FindObject<UFunction>("/Script/Engine.GameplayStatics.BeginDeferredActorSpawnFromClass");
struct
{
const UObject* WorldContextObject; // (ConstParm, Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
UClass* ActorClass; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, UObjectWrapper, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FTransform SpawnTransform; // (ConstParm, Parm, OutParm, ReferenceParm, IsPlainOldData, NoDestructor, NativeAccessSpecifierPublic)
ESpawnActorCollisionHandlingMethod CollisionHandlingOverride; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
AActor* Owner; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
AActor* ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
} UGameplayStatics_BeginDeferredActorSpawnFromClass_Params{ WorldContextObject, ActorClass, SpawnTransform, CollisionHandlingOverride, Owner };
static auto defaultObj = StaticClass();
defaultObj->ProcessEvent(fn, &UGameplayStatics_BeginDeferredActorSpawnFromClass_Params);
return UGameplayStatics_BeginDeferredActorSpawnFromClass_Params.ReturnValue;
}
AActor* UGameplayStatics::FinishSpawningActor(AActor* Actor, const FTransform& SpawnTransform)
{
static auto FinishSpawningActorFn = FindObject<UFunction>("/Script/Engine.GameplayStatics.FinishSpawningActor");
struct
{
AActor* Actor; // (Parm, ZeroConstructor, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
FTransform SpawnTransform; // (ConstParm, Parm, OutParm, ReferenceParm, IsPlainOldData, NoDestructor, NativeAccessSpecifierPublic)
AActor* ReturnValue; // (Parm, OutParm, ZeroConstructor, ReturnParm, IsPlainOldData, NoDestructor, HasGetValueTypeHash, NativeAccessSpecifierPublic)
} UGameplayStatics_FinishSpawningActor_Params{ Actor, SpawnTransform };
static auto defaultObj = StaticClass();
defaultObj->ProcessEvent(FinishSpawningActorFn, &UGameplayStatics_FinishSpawningActor_Params);
return UGameplayStatics_FinishSpawningActor_Params.ReturnValue;
}
void UGameplayStatics::LoadStreamLevel(UObject* WorldContextObject, FName LevelName, bool bMakeVisibleAfterLoad, bool bShouldBlockOnLoad, const FLatentActionInfo& LatentInfo)
{
static auto LoadStreamLevelFn = FindObject<UFunction>("/Script/Engine.GameplayStatics.LoadStreamLevel");

View File

@@ -4,6 +4,7 @@
#include "Array.h"
#include "Actor.h"
#include "LatentActionManager.h"
#include "EngineTypes.h"
class UGameplayStatics : public UObject
{
@@ -22,6 +23,8 @@ public:
// static void OpenLevel(UObject* WorldContextObject, FName LevelName, bool bAbsolute, const FString& Options);
static void RemovePlayer(class APlayerController* Player, bool bDestroyPawn);
static AActor* FinishSpawningActor(AActor* Actor, const FTransform& SpawnTransform);
static AActor* BeginDeferredActorSpawnFromClass(const UObject* WorldContextObject, UClass* ActorClass, const FTransform& SpawnTransform, ESpawnActorCollisionHandlingMethod CollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined, AActor* Owner = nullptr);
static void LoadStreamLevel(UObject* WorldContextObject, FName LevelName, bool bMakeVisibleAfterLoad, bool bShouldBlockOnLoad, const FLatentActionInfo& LatentInfo);
static void UnloadStreamLevel(UObject* WorldContextObject, FName LevelName, const FLatentActionInfo& LatentInfo, bool bShouldBlockOnUnload);

View File

@@ -178,6 +178,7 @@
<ClCompile Include="addresses.cpp" />
<ClCompile Include="AthenaMarkerComponent.cpp" />
<ClCompile Include="BuildingActor.cpp" />
<ClCompile Include="BuildingContainer.cpp" />
<ClCompile Include="BuildingFoundation.cpp" />
<ClCompile Include="BuildingSMActor.cpp" />
<ClCompile Include="BuildingStructuralSupportSystem.cpp" />
@@ -313,6 +314,8 @@
<ClInclude Include="FortAthenaMutator_InventoryOverride.h" />
<ClInclude Include="FortAthenaMutator_InventoryOverride_Bucket.h" />
<ClInclude Include="FortAthenaMutator_ItemDropOnDeath.h" />
<ClInclude Include="FortAthenaMutator_LoadoutSwap.h" />
<ClInclude Include="FortAthenaMutator_TDM.h" />
<ClInclude Include="FortAthenaSKPushCannon.h" />
<ClInclude Include="FortAthenaSupplyDrop.h" />
<ClInclude Include="FortAthenaVehicle.h" />

View File

@@ -262,6 +262,9 @@
<ClCompile Include="FortAthenaVehicleSpawner.cpp">
<Filter>FortniteGame\Source\FortniteGame\Private\Vehicles</Filter>
</ClCompile>
<ClCompile Include="BuildingContainer.cpp">
<Filter>FortniteGame\Source\FortniteGame\Private\Building</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="log.h" />
@@ -832,6 +835,12 @@
<ClInclude Include="FortAthenaVehicleSpawner.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Athena\Vehicle</Filter>
</ClInclude>
<ClInclude Include="FortAthenaMutator_TDM.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Mutators</Filter>
</ClInclude>
<ClInclude Include="FortAthenaMutator_LoadoutSwap.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Mutators</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Engine">

View File

@@ -279,9 +279,6 @@ void Addresses::FindAll()
LOG_INFO(LogDev, "Finding FreeArrayOfEntries");
Addresses::FreeArrayOfEntries = FindFreeArrayOfEntries();
LOG_INFO(LogDev, "Finding ApplyHomebaseEffectsOnPlayerSetup");
Addresses::FreeArrayOfEntries = FindApplyHomebaseEffectsOnPlayerSetup();
LOG_INFO(LogDev, "Finished finding!");
}
@@ -344,7 +341,6 @@ 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, "ApplyHomebaseEffectsOnPlayerSetup: 0x{:x}", ApplyHomebaseEffectsOnPlayerSetup - Base);
}
void Offsets::FindAll()

View File

@@ -65,7 +65,6 @@ namespace Addresses
extern inline uint64 PickupInitialize = 0;
extern inline uint64 FreeEntry = 0;
extern inline uint64 FreeArrayOfEntries = 0;
extern inline uint64 ApplyHomebaseEffectsOnPlayerSetup = 0;
void SetupVersion(); // Finds Engine Version
void FindAll();

View File

@@ -314,7 +314,8 @@ void ProcessEventHook(UObject* Object, UFunction* Function, void* Parameters)
!strstr(FunctionFullName.c_str(), "Primitive_Structure_AmbAudioComponent") &&
!strstr(FunctionName.c_str(), "ServerTriggerCombatEvent") &&
!strstr(FunctionName.c_str(), "SpinCubeTimeline__UpdateFunc") &&
!strstr(ObjectName.c_str(), "FortPhysicsObjectComponent"))
!strstr(ObjectName.c_str(), "FortPhysicsObjectComponent") &&
!strstr(FunctionName.c_str(), "GetTextValue"))
{
LOG_INFO(LogDev, "Function called: {} with {}", FunctionFullName, ObjectName);
}

View File

@@ -720,7 +720,7 @@ DWORD WINAPI Main(LPVOID)
uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0;
if (Engine_Version >= 419) // Dude idk why but its getting the second ref kms
// if (Engine_Version >= 419)
{
std::vector<uint8_t> ServerRemoveInventoryItemCallFunctionStarts = Engine_Version == 416
? std::vector<uint8_t>{ 0x44, 0x88, 0x4C }
@@ -729,14 +729,13 @@ DWORD WINAPI Main(LPVOID)
: std::vector<uint8_t>{ 0x48, 0x89, 0x5C };
auto ServerRemoveInventoryItemCallFunctionCall = FindFunctionCall(L"ServerRemoveInventoryItem", ServerRemoveInventoryItemCallFunctionStarts);
auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)ServerRemoveInventoryItemCallFunctionCall, true);
auto ServerRemoveInventoryItemFunctionCallRef = Memcury::Scanner::FindPointerRef((PVOID)ServerRemoveInventoryItemCallFunctionCall, 0, true);
LOG_INFO(LogDev, "ServerRemoveInventoryItemFunctionCallRef: 0x{:x}", ServerRemoveInventoryItemFunctionCallRef.Get() - __int64(GetModuleHandleW(0)));
uint64 ServerRemoveInventoryItemFunctionCallBeginFunctionAddr = 0;
for (int i = 0; i < 400; i++)
{
// LOG_INFO(LogDev, "[{}] Bugha: 0x{:x}", i, (int)(*(uint8_t*)ServerRemoveInventoryItemFunctionCallRef.Get() - i));
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;
@@ -750,10 +749,6 @@ DWORD WINAPI Main(LPVOID)
}
}
}
else
{
}
Hooking::MinHook::Hook(Memcury::Scanner(ServerRemoveInventoryItemFunctionCallBeginFunctionAddr).GetAs<PVOID>(), UFortInventoryInterface::RemoveInventoryItemHook);
@@ -767,11 +762,12 @@ DWORD WINAPI Main(LPVOID)
AddVehicleHook();
if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11)
// 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, "Test: 0x{:x}", FindFunctionCall(L"ClientOnPawnDied") - __int64(GetModuleHandleW(0)));
Hooking::MinHook::Hook((PVOID)FindFunctionCall(L"ClientOnPawnDied"), AFortPlayerController::ClientOnPawnDiedHook, (PVOID*)&AFortPlayerController::ClientOnPawnDiedOriginal);
LOG_INFO(LogDev, "ClientOnPawnDiedCallAddr: 0x{:x}", ClientOnPawnDiedCallAddr - __int64(GetModuleHandleW(0)));
Hooking::MinHook::Hook((PVOID)ClientOnPawnDiedCallAddr, AFortPlayerController::ClientOnPawnDiedHook, (PVOID*)&AFortPlayerController::ClientOnPawnDiedOriginal);
}
LOG_INFO(LogDev, "PredictionKeySize: 0x{:x} {}", PredictionKeySize, PredictionKeySize);
@@ -793,8 +789,8 @@ DWORD WINAPI Main(LPVOID)
MemberOffsets::FortPlayerPawnAthena::LastFallDistance = FindOffsetStruct("/Script/FortniteGame.FortPlayerPawnAthena", "LastFallDistance", false);
MemberOffsets::FortPlayerStateAthena::DeathInfo = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "DeathInfo");
MemberOffsets::FortPlayerStateAthena::KillScore = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "KillScore");
MemberOffsets::FortPlayerStateAthena::TeamKillScore = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "TeamKillScore");
MemberOffsets::FortPlayerStateAthena::KillScore = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "KillScore", false);
MemberOffsets::FortPlayerStateAthena::TeamKillScore = FindOffsetStruct("/Script/FortniteGame.FortPlayerStateAthena", "TeamKillScore", false);
MemberOffsets::DeathInfo::bDBNO = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "bDBNO");
MemberOffsets::DeathInfo::DeathCause = FindOffsetStruct("/Script/FortniteGame.DeathInfo", "DeathCause");

View File

@@ -414,11 +414,6 @@ static inline uint64 FindIsNetRelevantForOffset()
return 0;
}
static inline uint64 FindApplyHomebaseEffectsOnPlayerSetup()
{
return 0;
}
static inline uint64 FindActorChannelClose()
{
auto StringRef = Memcury::Scanner::FindStringRef(L"UActorChannel::Close: ChIndex: %d, Actor: %s");
@@ -1450,7 +1445,14 @@ static inline uint64 FindCanActivateAbility()
static inline uint64 FindGiveAbilityAndActivateOnce()
{
if (Engine_Version == 426)
return Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 40 49 8B 40 10 49 8B D8 48 8B FA 48 8B F1").Get();
{
auto sig1 = 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", false).Get();
if (!sig1)
sig1 = Memcury::Scanner::FindPattern("48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 48 83 EC 40 49 8B 40 10 49").Get(); // 15.50
return sig1;
}
auto Addrr = Memcury::Scanner::FindStringRef(L"GiveAbilityAndActivateOnce called on ability %s on the client, not allowed!", true, 0, Engine_Version >= 500).Get();
@@ -1602,6 +1604,9 @@ static inline uint64 FindClearAbility()
{
auto GiveAbilityAndActivateOnce = FindGiveAbilityAndActivateOnce();
if (!GiveAbilityAndActivateOnce)
return 0;
return Memcury::Scanner(GiveAbilityAndActivateOnce).ScanFor({ 0xE8 }, true, 4).RelativeOffset(1).Get();
if (Engine_Version == 416)

View File

@@ -843,9 +843,12 @@ static inline void MainUI()
else if (Tab == DEVELOPER_TAB)
{
static std::string ClassNameToDump;
static std::string FunctionNameToDump;
ImGui::InputText("Class Name to mess with", &ClassNameToDump);
ImGui::InputText("Function Name to mess with", &FunctionNameToDump);
if (ImGui::Button("Print Class VFT"))
{
auto Class = FindObject<UClass>(ClassNameToDump);
@@ -861,6 +864,16 @@ static inline void MainUI()
}
}
if (ImGui::Button("Print Function Exec Addy"))
{
auto Function = FindObject<UFunction>(FunctionNameToDump);
if (Function)
{
LOG_INFO(LogDev, "{} Exec: 0x{:x}", Function->GetName(), __int64(Function->GetFunc()) - __int64(GetModuleHandleW(0)));
}
}
/* if (ImGui::Button("Load BGA Class (and spawn so no GC)"))
{
static auto BGAClass = FindObject<UClass>("/Script/Engine.BlueprintGeneratedClass");

View File

@@ -54,5 +54,5 @@ inline bool AreVehicleWeaponsEnabled()
inline bool IsRestartingSupported()
{
return Engine_Version < 424;
return Engine_Version >= 419 && Engine_Version < 424;
}

9
vendor/memcury.h vendored
View File

@@ -777,6 +777,8 @@
{
add = PE::Address(&scanBytes[i]);
// LOG_INFO(LogDev, "2add: 0x{:x}", add.Get() - __int64(GetModuleHandleW(0)));
if (bUseFirstResult)
return Scanner(add);
@@ -791,6 +793,8 @@
{
add = PE::Address(&scanBytes[i]);
// LOG_INFO(LogDev, "1add: 0x{:x}", add.Get() - __int64(GetModuleHandleW(0)));
if (bUseFirstResult)
return Scanner(add);
@@ -847,7 +851,8 @@
{
if constexpr (!bIsPtr)
{
typedef T::value_type char_type;
// typedef T::value_type char_type;
using char_type = std::decay_t<std::remove_pointer_t<T>>;
auto lea = stringAdd.GetAs<char_type*>();
@@ -1404,7 +1409,7 @@
}
// Finds a string ref, then goes searches xref of the function that it's in and returns that address.
inline uintptr_t FindFunctionCall(const wchar_t* Name, const std::vector<uint8_t>& Bytes = { 0x48, 0x89, 0x5C }, int skip = 0) // credit ender & me
inline uintptr_t FindFunctionCall(const wchar_t* Name, const std::vector<uint8_t>& Bytes = std::vector<uint8_t>{ 0x48, 0x89, 0x5C }, int skip = 0) // credit ender & me
{
auto FunctionPtr = Memcury::Scanner::FindStringRef(Name, true, skip).ScanFor({ 0x48, 0x8D, 0x0D }).RelativeOffset(3).GetAs<void*>();