This commit is contained in:
Milxnor
2023-05-19 23:18:56 -04:00
parent 42f4e637e7
commit bb5a5620e8
16 changed files with 225 additions and 22 deletions

View File

@@ -15,9 +15,21 @@ struct PadHexB0 { char Pad[0xB0]; };
// using FPredictionKey = PadHex10;
using FGameplayEventData = PadHexB0;
using FPredictionKey = __int64;
// using FGameplayEventData = __int64;
struct FPredictionKey // todo move
{
// __int64 real;
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/GameplayAbilities.PredictionKey");
return Struct;
}
static int GetStructSize() { return GetStruct()->GetPropertiesSize(); }
};
struct FGameplayEffectContextHandle
{
unsigned char UnknownData00[0x18]; // 0x0000(0x0018) MISSED OFFSET
@@ -72,6 +84,9 @@ public:
return Subobject;
}
void ServerEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo* ActivationInfo, FPredictionKey* PredictionKey);
void ClientEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo* ActivationInfo);
void ClientCancelAbility(FGameplayAbilitySpecHandle AbilityToCancel, FGameplayAbilityActivationInfo* ActivationInfo);
bool HasAbility(UObject* DefaultAbility);
FActiveGameplayEffectHandle ApplyGameplayEffectToSelf(UClass* GameplayEffectClass, float Level, const FGameplayEffectContextHandle& EffectContext = FGameplayEffectContextHandle());
// FGameplayEffectContextHandle MakeEffectContext();
@@ -83,4 +98,6 @@ public:
void ClearAbility(const FGameplayAbilitySpecHandle& Handle);
static void InternalServerTryActivateAbilityHook(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle, bool InputPressed, const FPredictionKey* PredictionKey, const FGameplayEventData* TriggerEventData);
};
};
void LoopSpecs(UAbilitySystemComponent* AbilitySystemComponent, std::function<void(FGameplayAbilitySpec*)> func);

View File

@@ -50,6 +50,56 @@ FActiveGameplayEffectHandle UAbilitySystemComponent::ApplyGameplayEffectToSelf(U
return ContextHandle;
} */
void UAbilitySystemComponent::ServerEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo* ActivationInfo, FPredictionKey* PredictionKey)
{
static auto ServerEndAbilityFn = FindObject<UFunction>(L"/Script/GameplayAbilities.AbilitySystemComponent.ServerEndAbility");
auto Params = Alloc<void>(ServerEndAbilityFn->GetPropertiesSize());
if (!Params)
return;
static auto AbilityToEndOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ServerEndAbility", "AbilityToEnd");
static auto ActivationInfoOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ServerEndAbility", "ActivationInfo");
static auto PredictionKeyOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ServerEndAbility", "PredictionKey");
*(FGameplayAbilitySpecHandle*)(__int64(Params) + AbilityToEndOffset) = AbilityToEnd;
CopyStruct((FGameplayAbilityActivationInfo*)(__int64(Params) + ActivationInfoOffset), ActivationInfo, FGameplayAbilityActivationInfo::GetStructSize());
CopyStruct((FPredictionKey*)(__int64(Params) + PredictionKeyOffset), PredictionKey, FPredictionKey::GetStructSize());
this->ProcessEvent(ServerEndAbilityFn, Params);
}
void UAbilitySystemComponent::ClientEndAbility(FGameplayAbilitySpecHandle AbilityToEnd, FGameplayAbilityActivationInfo* ActivationInfo)
{
static auto ClientEndAbilityFn = FindObject<UFunction>("/Script/GameplayAbilities.AbilitySystemComponent.ClientEndAbility");
auto Params = Alloc(ClientEndAbilityFn->GetPropertiesSize());
static auto AbilityToEndOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ClientEndAbility", "AbilityToEnd");
static auto ActivationInfoOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ClientEndAbility", "ActivationInfo");
*(FGameplayAbilitySpecHandle*)(__int64(Params) + AbilityToEndOffset) = AbilityToEnd;
CopyStruct((FGameplayAbilityActivationInfo*)(__int64(Params) + ActivationInfoOffset), ActivationInfo, FGameplayAbilityActivationInfo::GetStructSize());
this->ProcessEvent(ClientEndAbilityFn, Params);
}
void UAbilitySystemComponent::ClientCancelAbility(FGameplayAbilitySpecHandle AbilityToCancel, FGameplayAbilityActivationInfo* ActivationInfo)
{
static auto ClientCancelAbilityFn = FindObject<UFunction>(L"/Script/GameplayAbilities.AbilitySystemComponent.ClientCancelAbility");
auto Params = Alloc(ClientCancelAbilityFn->GetPropertiesSize());
static auto AbilityToCancelOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ClientCancelAbility", "AbilityToCancel");
static auto ActivationInfoOffset = FindOffsetStruct("/Script/GameplayAbilities.AbilitySystemComponent.ClientCancelAbility", "ActivationInfo");
*(FGameplayAbilitySpecHandle*)(__int64(Params) + AbilityToCancelOffset) = AbilityToCancel;
CopyStruct((FGameplayAbilityActivationInfo*)(__int64(Params) + ActivationInfoOffset), ActivationInfo, FGameplayAbilityActivationInfo::GetStructSize());
this->ProcessEvent(ClientCancelAbilityFn, Params);
}
bool UAbilitySystemComponent::HasAbility(UObject* DefaultAbility)
{
auto ActivatableAbilities = GetActivatableAbilities();

View File

@@ -22,7 +22,7 @@ bool ABuildingContainer::SpawnLoot(AFortPawn* Pawn)
{
auto& lootDrop = LootDrops.at(i);
PickupCreateData CreateData{};
PickupCreateData CreateData;
CreateData.bToss = true;
// CreateData.PawnOwner = Pawn;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(lootDrop->GetItemDefinition(), lootDrop->GetCount(), lootDrop->GetLoadedAmmo());

View File

@@ -1129,7 +1129,7 @@ void AFortGameModeAthena::Athena_HandleStartingNewPlayerHook(AFortGameModeAthena
for (auto& LootDrop : LootDrops)
{
PickupCreateData CreateData{};
PickupCreateData CreateData;
CreateData.bToss = true;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(LootDrop->GetItemDefinition(), LootDrop->GetCount(), LootDrop->GetLoadedAmmo());
CreateData.SpawnLocation = Location;

View File

@@ -137,7 +137,7 @@ void UFortKismetLibrary::SpawnItemVariantPickupInWorldHook(UObject* Context, FFr
LOG_INFO(LogDev, "{} {} {}", Position.X, Position.Y, Position.Z);
PickupCreateData CreateData{};
PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, ParamsPtr->GetNumberToSpawn(), -1);
CreateData.SourceType = ParamsPtr->GetSourceType();
CreateData.Source = ParamsPtr->GetSource();
@@ -508,7 +508,7 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldWithClassHook(UObject* Con
LOG_INFO(LogDev, __FUNCTION__);
PickupCreateData CreateData{};
PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.Source = Source;
CreateData.SourceType = SourceType;
@@ -591,7 +591,7 @@ AFortPickup* UFortKismetLibrary::K2_SpawnPickupInWorldHook(UObject* Context, FFr
auto Pawn = OptionalOwnerPC ? OptionalOwnerPC->GetMyFortPawn() : nullptr;
PickupCreateData CreateData{};
PickupCreateData CreateData;
CreateData.ItemEntry = FFortItemEntry::MakeItemEntry(ItemDefinition, NumberToSpawn, -1);
CreateData.SpawnLocation = Position;
CreateData.bToss = bToss;

View File

@@ -5,7 +5,7 @@
AFortWeapon* AFortPawn::EquipWeaponDefinition(UFortWeaponItemDefinition* WeaponData, const FGuid& ItemEntryGuid)
{
static auto EquipWeaponDefinitionFn = FindObject<UFunction>("/Script/FortniteGame.FortPawn.EquipWeaponDefinition");
static auto EquipWeaponDefinitionFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPawn.EquipWeaponDefinition");
FGuid TrackerGuid{};
@@ -40,6 +40,12 @@ bool AFortPawn::PickUpActor(AActor* PickupTarget, UFortDecoItemDefinition* Place
return AFortPawn_PickUpActor_Params.ReturnValue;
}
void AFortPawn::OnRep_IsDBNO()
{
static auto OnRep_IsDBNOFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPawn.OnRep_IsDBNO");
this->ProcessEvent(OnRep_IsDBNOFn);
}
float AFortPawn::GetShield()
{
float Shield = 0;

View File

@@ -27,6 +27,23 @@ public:
return ReadBitfieldValue(bIsDBNOOffset, bIsDBNOFieldMask);
}
void SetDBNO(bool IsDBNO)
{
static auto bIsDBNOFieldMask = GetFieldMask(GetProperty("bIsDBNO"));
static auto bIsDBNOOffset = GetOffset("bIsDBNO");
this->SetBitfieldValue(bIsDBNOOffset, bIsDBNOFieldMask, IsDBNO);
}
void SetHasPlayedDying(bool NewValue)
{
static auto bPlayedDyingFieldMask = GetFieldMask(GetProperty("bPlayedDying"));
static auto bPlayedDyingOffset = GetOffset("bPlayedDying");
this->SetBitfieldValue(bPlayedDyingOffset, bPlayedDyingFieldMask, NewValue);
}
void OnRep_IsDBNO();
float GetShield();
float GetHealth();
void SetHealth(float NewHealth);

View File

@@ -42,7 +42,7 @@ AFortPickup* AFortPickup::SpawnPickup(PickupCreateData& PickupData)
} */
static auto FortPickupAthenaClass = FindObject<UClass>(L"/Script/FortniteGame.FortPickupAthena");
auto PlayerState = PickupData.PawnOwner->IsValidLowLevel() ? Cast<AFortPlayerState>(PickupData.PawnOwner->GetPlayerState()) : nullptr;
auto PlayerState = PickupData.PawnOwner ? Cast<AFortPlayerState>(PickupData.PawnOwner->GetPlayerState()) : nullptr;
FActorSpawnParameters SpawnParameters{};
// SpawnParameters.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn;

View File

@@ -197,6 +197,12 @@ public:
}
}
void ClientOnPawnRevived(AController* EventInstigator)
{
static auto ClientOnPawnRevivedFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerZone.ClientOnPawnRevived");
this->ProcessEvent(ClientOnPawnRevivedFn, &EventInstigator);
}
bool& IsMarkedAlive()
{
static auto bMarkedAliveOffset = GetOffset("bMarkedAlive");

View File

@@ -17,9 +17,97 @@ FFortAthenaLoadout* AFortPlayerPawn::GetCosmeticLoadout()
return GetPtr<FFortAthenaLoadout>(CosmeticLoadoutOffset);
}
void AFortPlayerPawn::ServerReviveFromDBNOHook(AController* EventInstigator)
bool DBNOCheck(AFortPlayerPawn* Pawn, AController* EventInstigator)
{
bool res = false;
if (Pawn->IsDBNO())
{
if (EventInstigator)
{
// idk what this does but this is my interpretation
auto PlayerState = Cast<AFortPlayerStateAthena>(Pawn->GetPlayerState());
auto InstigatorPlayerState = Cast<AFortPlayerStateAthena>(EventInstigator->GetPlayerState());
if (PlayerState && InstigatorPlayerState)
{
if (PlayerState->GetTeamIndex() == InstigatorPlayerState->GetTeamIndex())
{
res = true;
}
}
}
}
return res;
}
void AFortPlayerPawn::ServerReviveFromDBNOHook(AFortPlayerPawn* Pawn, AController* EventInstigator)
{
LOG_INFO(LogDev, "ServerReviveFromDBNOHook!");
if (!DBNOCheck(Pawn, EventInstigator))
return;
auto PlayerController = Cast<AFortPlayerControllerAthena>(Pawn->GetController());
if (!PlayerController)
return;
auto PlayerState = Cast<AFortPlayerState>(PlayerController->GetPlayerState());
if (!PlayerState)
return;
bool IsRevivingSelf = EventInstigator == PlayerController;
/*
UObject* ReviveGameplayEffect = nullptr;
if (IsRevivingSelf)
else
*/
static auto GAB_AthenaDBNOClass = FindObject<UClass>(L"/Game/Abilities/NPC/Generic/GAB_AthenaDBNO.Default__GAB_AthenaDBNO_C");
auto DBNOPawnASC = PlayerState->GetAbilitySystemComponent();
if (!DBNOPawnASC)
return;
FGameplayAbilitySpec* DBNOSpec = nullptr;
UObject* ClassToFind = GAB_AthenaDBNOClass->ClassPrivate;
auto compareAbilities = [&DBNOSpec, &ClassToFind](FGameplayAbilitySpec* Spec) {
auto CurrentAbility = Spec->GetAbility();
if (CurrentAbility->ClassPrivate == ClassToFind)
{
DBNOSpec = Spec;
return;
}
};
LoopSpecs(DBNOPawnASC, compareAbilities);
if (!DBNOSpec)
return;
DBNOPawnASC->ClientCancelAbility(DBNOSpec->GetHandle(), DBNOSpec->GetActivationInfo());
DBNOPawnASC->ClientEndAbility(DBNOSpec->GetHandle(), DBNOSpec->GetActivationInfo());
DBNOPawnASC->ServerEndAbility(DBNOSpec->GetHandle(), DBNOSpec->GetActivationInfo(), nullptr);
Pawn->SetDBNO(false);
Pawn->SetHasPlayedDying(false);
Pawn->SetHealth(30); // TODO Get value from SetByCallerReviveHealth?
Pawn->OnRep_IsDBNO();
PlayerController->ClientOnPawnRevived(EventInstigator); // We should call the function that calls this.
PlayerController->RespawnPlayerAfterDeath(false); // nooo
}
void AFortPlayerPawn::ServerHandlePickupWithRequestedSwapHook(UObject* Context, FFrame* Stack, void* Ret)

View File

@@ -44,7 +44,7 @@ public:
UFortWeaponItemDefinition* GetVehicleWeaponDefinition(AFortAthenaVehicle* Vehicle);
void UnEquipVehicleWeaponDefinition(UFortWeaponItemDefinition* VehicleWeaponDefinition);
static void ServerReviveFromDBNOHook(AController* EventInstigator);
static void ServerReviveFromDBNOHook(AFortPlayerPawn* Pawn, AController* EventInstigator);
static void ServerHandlePickupWithRequestedSwapHook(UObject* Context, FFrame* Stack, void* Ret); // we could native hook this but idk
static void StartGhostModeExitHook(UObject* Context, FFrame* Stack, void* Ret); // we could native hook this but eh
static AActor* ServerOnExitVehicleHook(AFortPlayerPawn* Pawn, ETryExitVehicleBehavior ExitForceBehavior); // actually returns AFortAthenaVehicle

View File

@@ -23,6 +23,17 @@ struct FGameplayAbilitySpecHandle
} */
};
struct FGameplayAbilityActivationInfo // TODO Move
{
static UStruct* GetStruct()
{
static auto Struct = FindObject<UStruct>("/Script/GameplayAbilities.GameplayAbilityActivationInfo");
return Struct;
}
static int GetStructSize() { return GetStruct()->GetPropertiesSize(); }
};
struct FGameplayAbilitySpec : FFastArraySerializerItem
{
static int GetStructSize()
@@ -45,6 +56,12 @@ struct FGameplayAbilitySpec : FFastArraySerializerItem
static auto HandleOffset = FindOffsetStruct("/Script/GameplayAbilities.GameplayAbilitySpec", "Handle");
return *(FGameplayAbilitySpecHandle*)(__int64(this) + HandleOffset);
}
FGameplayAbilityActivationInfo* GetActivationInfo()
{
static auto ActivationInfoOffset = FindOffsetStruct("/Script/GameplayAbilities.GameplayAbilitySpec", "ActivationInfo");
return (FGameplayAbilityActivationInfo*)(__int64(this) + ActivationInfoOffset);
}
};
static FGameplayAbilitySpec* MakeNewSpec(UClass* GameplayAbilityClass, UObject* SourceObject = nullptr, bool bAlreadyIsDefault = false)

View File

@@ -208,15 +208,15 @@ void UObject::AddToRoot()
bool UObject::IsValidLowLevel()
{
if (std::floor(Fortnite_Version) == 5) // real 1:1
return true;
if (std::floor(Fortnite_Version) == 5) // real 1:1 // todo (milxnor) try without this
return !IsBadReadPtr(this, 8);
if (this == nullptr)
{
// UE_LOG(LogUObjectBase, Warning, TEXT("NULL object"));
return false;
}
if (IsBadReadPtr(this, 8)) // needed?
if (IsBadReadPtr(this, 8)) // needed? (milxnor)
{
return false;
}

View File

@@ -291,7 +291,7 @@ DWORD WINAPI Main(LPVOID)
}
bSwitchedInitialLevel = true;
Globals::bAutoRestart = IsRestartingSupported();
// Globals::bAutoRestart = IsRestartingSupported();
static auto GameModeDefault = FindObject<AFortGameModeAthena>(L"/Script/FortniteGame.Default__FortGameModeAthena");
static auto FortPlayerControllerZoneDefault = FindObject<AFortPlayerController>(L"/Script/FortniteGame.Default__FortPlayerControllerZone");

View File

@@ -278,13 +278,10 @@ static inline void StaticUI()
{
// ImGui::Checkbox("Auto Restart", &Globals::bAutoRestart);
if (false)
if (Globals::bAutoRestart)
{
if (Globals::bAutoRestart)
{
ImGui::InputFloat(std::format("How long after {} players join the bus will start", NumRequiredPlayersToStart).c_str(), &AutoBusStartSeconds);
ImGui::InputInt("Num Players required for bus auto timer", &NumRequiredPlayersToStart);
}
ImGui::InputFloat(std::format("How long after {} players join the bus will start", NumRequiredPlayersToStart).c_str(), &AutoBusStartSeconds);
ImGui::InputInt("Num Players required for bus auto timer", &NumRequiredPlayersToStart);
}
}

View File

@@ -371,6 +371,9 @@ inline int FindOffsetStruct(const std::string& StructName, const std::string& Me
// template <typename T>
static void CopyStruct(void* Dest, void* Src, size_t Size, UStruct* Struct = nullptr)
{
if (!Src)
return;
memcpy_s(Dest, Size, Src, Size);
if (Struct)
@@ -394,7 +397,9 @@ public:
template <typename T = __int64>
static T* Alloc(size_t Size = sizeof(T), bool bUseFMemoryRealloc = false)
{
return bUseFMemoryRealloc ? (T*)FMemory::Realloc(0, Size, 0) : (T*)VirtualAlloc(0, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
auto mem = bUseFMemoryRealloc ? (T*)FMemory::Realloc(0, Size, 0) : (T*)VirtualAlloc(0, Size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
// RtlSecureZeroMemory(mem, Size);
return mem;
}
namespace MemberOffsets