respawning on older versions

fixed respawning on pre s6, fixed a crash for some s5 builds, work on ai a bit, start on blueprint decompiler
This commit is contained in:
Milxnor
2023-05-20 10:22:47 -04:00
parent bb5a5620e8
commit 33433ea9de
30 changed files with 2082 additions and 77 deletions

View File

@@ -0,0 +1,14 @@
#pragma once
#include "BuildingGameplayActor.h"
class ABuildingItemWeaponUpgradeActor : public ABuildingGameplayActor // ABuildingItemCollectorActor
{
public:
static class UClass* StaticClass()
{
static UClass* Class = FindObject<UClass>(L"/Script/FortniteGame.BuildingItemWeaponUpgradeActor");
return Class;
}
};

View File

@@ -16,13 +16,16 @@ class UStruct : public UField
{ {
public: public:
int GetPropertiesSize(); int GetPropertiesSize();
UStruct* GetSuperStruct() { return *(UStruct**)(__int64(this) + Offsets::SuperStruct); } // idk if this is in UStruct
TArray<uint8_t> GetScript() { return *(TArray<uint8_t>*)(__int64(this) + Offsets::Script); }
}; };
class UClass : public UStruct class UClass : public UStruct
{ {
public: public:
UObject* CreateDefaultObject(); UObject* CreateDefaultObject();
UClass* GetSuperStruct() { return *(UClass**)(__int64(this) + Offsets::SuperStruct); } // idk if this is in UStruct
}; };
class UFunction : public UStruct class UFunction : public UStruct

View File

@@ -0,0 +1 @@
#pragma once

View File

@@ -0,0 +1,13 @@
#pragma once
#include "reboot.h"
class UFortAthenaAIBotCustomizationData : public UObject // UPrimaryDataAsset
{
public:
static UClass* StaticClass()
{
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortAthenaAIBotCustomizationData");
return Class;
}
};

View File

@@ -0,0 +1,36 @@
#pragma once
#include "reboot.h"
#include "Text.h"
enum class EBotNamingMode : uint8 // idk if this changes
{
RealName = 0,
SkinName = 1,
Anonymous = 2,
Custom = 3,
EBotNamingMode_MAX = 4,
};
class UFortBotNameSettings : public UObject
{
public:
EBotNamingMode& GetNamingMode()
{
static auto NamingModeOffset = GetOffset("NamingMode");
return Get<EBotNamingMode>(NamingModeOffset);
}
FText& GetOverrideName()
{
static auto OverrideNameOffset = GetOffset("OverrideName");
return Get<FText>(OverrideNameOffset);
}
bool ShouldAddPlayerIDSuffix()
{
static auto bAddPlayerIDSuffixOffset = GetOffset("bAddPlayerIDSuffix");
return Get<bool>(bAddPlayerIDSuffixOffset);
}
};

View File

@@ -976,17 +976,22 @@ int AFortGameModeAthena::Athena_PickTeamHook(AFortGameModeAthena* GameMode, uint
CurrentTeamMembers++; CurrentTeamMembers++;
auto PlayerStateObjectItem = GetItemByIndex(PlayerState->InternalIndex);
TWeakObjectPtr<AFortPlayerStateAthena> WeakPlayerState{}; TWeakObjectPtr<AFortPlayerStateAthena> WeakPlayerState{};
WeakPlayerState.ObjectIndex = PlayerState->InternalIndex; WeakPlayerState.ObjectIndex = PlayerState->InternalIndex;
WeakPlayerState.ObjectSerialNumber = GetItemByIndex(PlayerState->InternalIndex)->SerialNumber; WeakPlayerState.ObjectSerialNumber = PlayerStateObjectItem ? PlayerStateObjectItem->SerialNumber : 0;
if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer()) if (PlayerStateObjectItem)
{ {
auto& TeamArray = TeamsArrayContainer->TeamsArray.at(NextTeamIndex); if (auto TeamsArrayContainer = GameState->GetTeamsArrayContainer())
LOG_INFO(LogDev, "TeamsArrayContainer->TeamsArray.Num(): {}", TeamsArrayContainer->TeamsArray.Num()); {
LOG_INFO(LogDev, "TeamArray.Num(): {}", TeamArray.Num()); auto& TeamArray = TeamsArrayContainer->TeamsArray.at(NextTeamIndex);
LOG_INFO(LogDev, "TeamsArrayContainer->TeamsArray.Num(): {}", TeamsArrayContainer->TeamsArray.Num());
LOG_INFO(LogDev, "TeamArray.Num(): {}", TeamArray.Num());
TeamArray.Add(WeakPlayerState); TeamArray.Add(WeakPlayerState);
}
} }
return NextTeamIndex; return NextTeamIndex;

View File

@@ -1206,9 +1206,6 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
if (!DeadPawn || !GameState || !DeadPlayerState) if (!DeadPawn || !GameState || !DeadPlayerState)
return ClientOnPawnDiedOriginal(PlayerController, DeathReport); return ClientOnPawnDiedOriginal(PlayerController, DeathReport);
static auto DeathInfoStruct = FindObject<UStruct>(L"/Script/FortniteGame.DeathInfo");
static auto DeathInfoStructSize = DeathInfoStruct->GetPropertiesSize();
auto DeathLocation = DeadPawn->GetActorLocation(); auto DeathLocation = DeadPawn->GetActorLocation();
static auto FallDamageEnumValue = 1; static auto FallDamageEnumValue = 1;
@@ -1217,8 +1214,8 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11) if (Fortnite_Version > 1.8 || Fortnite_Version == 1.11)
{ {
auto DeathInfo = (void*)(__int64(DeadPlayerState) + MemberOffsets::FortPlayerStateAthena::DeathInfo); // Alloc<void>(DeathInfoStructSize); auto DeathInfo = DeadPlayerState->GetDeathInfo(); // Alloc<void>(DeathInfoStructSize);
RtlSecureZeroMemory(DeathInfo, DeathInfoStructSize); // TODO FREE THE DEATHTAGS DeadPlayerState->ClearDeathInfo();
auto/*&*/ Tags = MemberOffsets::FortPlayerPawn::CorrectTags == 0 ? FGameplayTagContainer() auto/*&*/ Tags = MemberOffsets::FortPlayerPawn::CorrectTags == 0 ? FGameplayTagContainer()
: DeadPawn->Get<FGameplayTagContainer>(MemberOffsets::FortPlayerPawn::CorrectTags); : DeadPawn->Get<FGameplayTagContainer>(MemberOffsets::FortPlayerPawn::CorrectTags);
@@ -1425,13 +1422,13 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
{ {
if (DamageCauser->IsA(FortProjectileBaseClass)) if (DamageCauser->IsA(FortProjectileBaseClass))
{ {
LOG_INFO(LogDev, "From a projectile!"); // LOG_INFO(LogDev, "From a projectile!");
auto Owner = Cast<AFortWeapon>(DamageCauser->GetOwner()); auto Owner = Cast<AFortWeapon>(DamageCauser->GetOwner());
KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys? KillerWeaponDef = Owner->IsValidLowLevel() ? Owner->GetWeaponData() : nullptr; // I just added the IsValidLowLevel check because what if the weapon destroys?
} }
if (auto Weapon = Cast<AFortWeapon>(DamageCauser)) if (auto Weapon = Cast<AFortWeapon>(DamageCauser))
{ {
LOG_INFO(LogDev, "From a weapon!"); // LOG_INFO(LogDev, "From a weapon!");
KillerWeaponDef = Weapon->GetWeaponData(); KillerWeaponDef = Weapon->GetWeaponData();
} }
} }
@@ -1517,6 +1514,8 @@ void AFortPlayerController::ClientOnPawnDiedHook(AFortPlayerController* PlayerCo
// AllPlayerBotsToTick.remov3lbah // AllPlayerBotsToTick.remov3lbah
} }
DeadPlayerState->EndDBNOAbilities();
return ClientOnPawnDiedOriginal(PlayerController, DeathReport); return ClientOnPawnDiedOriginal(PlayerController, DeathReport);
} }

View File

@@ -71,6 +71,14 @@ static bool ApplyCID(AFortPlayerPawn* Pawn, UObject* CID, bool bUseServerChooseP
if (!PlayerController) if (!PlayerController)
return false; return false;
if (bUseServerChoosePart)
{
if (Pawn)
{
}
}
/* auto PCCosmeticLoadout = PlayerController->GetCosmeticLoadout(); /* auto PCCosmeticLoadout = PlayerController->GetCosmeticLoadout();
if (!PCCosmeticLoadout) if (!PCCosmeticLoadout)
@@ -197,9 +205,9 @@ public:
} }
} }
void ClientOnPawnRevived(AController* EventInstigator) void ClientOnPawnRevived(AController* EventInstigator) // actually zone // idk what this actually does but i call it
{ {
static auto ClientOnPawnRevivedFn = FindObject<UFunction>("/Script/FortniteGame.FortPlayerControllerZone.ClientOnPawnRevived"); static auto ClientOnPawnRevivedFn = FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerControllerZone.ClientOnPawnRevived");
this->ProcessEvent(ClientOnPawnRevivedFn, &EventInstigator); this->ProcessEvent(ClientOnPawnRevivedFn, &EventInstigator);
} }

View File

@@ -3,6 +3,7 @@
#include "FortPlayerController.h" #include "FortPlayerController.h"
#include "FortGadgetItemDefinition.h" #include "FortGadgetItemDefinition.h"
#include "FortPlayerControllerAthena.h" #include "FortPlayerControllerAthena.h"
#include "FortPlayerPawnAthena.h"
FFortAthenaLoadout* AFortPlayerPawn::GetCosmeticLoadout() FFortAthenaLoadout* AFortPlayerPawn::GetCosmeticLoadout()
{ {
@@ -69,35 +70,7 @@ void AFortPlayerPawn::ServerReviveFromDBNOHook(AFortPlayerPawn* Pawn, AControlle
else else
*/ */
static auto GAB_AthenaDBNOClass = FindObject<UClass>(L"/Game/Abilities/NPC/Generic/GAB_AthenaDBNO.Default__GAB_AthenaDBNO_C"); PlayerState->EndDBNOAbilities();
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->SetDBNO(false);
Pawn->SetHasPlayedDying(false); Pawn->SetHasPlayedDying(false);
@@ -108,6 +81,14 @@ void AFortPlayerPawn::ServerReviveFromDBNOHook(AFortPlayerPawn* Pawn, AControlle
PlayerController->ClientOnPawnRevived(EventInstigator); // We should call the function that calls this. PlayerController->ClientOnPawnRevived(EventInstigator); // We should call the function that calls this.
PlayerController->RespawnPlayerAfterDeath(false); // nooo PlayerController->RespawnPlayerAfterDeath(false); // nooo
if (auto PawnAthena = Cast<AFortPlayerPawnAthena>(Pawn)) // im too lazy to make another hook for fortplayerpawnathena
{
if (!PawnAthena->IsDBNO())
{
PawnAthena->GetDBNORevivalStacking() = 0;
}
}
} }
void AFortPlayerPawn::ServerHandlePickupWithRequestedSwapHook(UObject* Context, FFrame* Stack, void* Ret) void AFortPlayerPawn::ServerHandlePickupWithRequestedSwapHook(UObject* Context, FFrame* Stack, void* Ret)

View File

@@ -7,5 +7,11 @@ class AFortPlayerPawnAthena : public AFortPlayerPawn
public: public:
static inline void (*OnCapsuleBeginOverlapOriginal)(UObject* Context, FFrame* Stack, void* Ret); static inline void (*OnCapsuleBeginOverlapOriginal)(UObject* Context, FFrame* Stack, void* Ret);
uint8& GetDBNORevivalStacking()
{
static auto DBNORevivalStackingOffset = GetOffset("DBNORevivalStacking");
return Get<uint8>(DBNORevivalStackingOffset);
}
static void OnCapsuleBeginOverlapHook(UObject* Context, FFrame* Stack, void* Ret); static void OnCapsuleBeginOverlapHook(UObject* Context, FFrame* Stack, void* Ret);
}; };

View File

@@ -1,5 +1,38 @@
#include "FortPlayerState.h" #include "FortPlayerState.h"
void AFortPlayerState::EndDBNOAbilities()
{
static auto GAB_AthenaDBNOClass = FindObject<UClass>(L"/Game/Abilities/NPC/Generic/GAB_AthenaDBNO.Default__GAB_AthenaDBNO_C");
auto ASC = this->GetAbilitySystemComponent();
if (!ASC)
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(ASC, compareAbilities);
if (!DBNOSpec)
return;
ASC->ClientCancelAbility(DBNOSpec->GetHandle(), DBNOSpec->GetActivationInfo());
ASC->ClientEndAbility(DBNOSpec->GetHandle(), DBNOSpec->GetActivationInfo());
ASC->ServerEndAbility(DBNOSpec->GetHandle(), DBNOSpec->GetActivationInfo(), nullptr);
}
bool AFortPlayerState::AreUniqueIDsIdentical(FUniqueNetIdRepl* A, FUniqueNetIdRepl* B) bool AFortPlayerState::AreUniqueIDsIdentical(FUniqueNetIdRepl* A, FUniqueNetIdRepl* B)
{ {
return A->IsIdentical(B); return A->IsIdentical(B);

View File

@@ -19,11 +19,13 @@ public:
return this->Get<int>(WorldPlayerIdOffset); return this->Get<int>(WorldPlayerIdOffset);
} }
void EndDBNOAbilities();
static bool AreUniqueIDsIdentical(FUniqueNetIdRepl* A, FUniqueNetIdRepl* B); static bool AreUniqueIDsIdentical(FUniqueNetIdRepl* A, FUniqueNetIdRepl* B);
static UClass* StaticClass() static UClass* StaticClass()
{ {
static auto Class = FindObject<UClass>("/Script/FortniteGame.FortPlayerState"); static auto Class = FindObject<UClass>(L"/Script/FortniteGame.FortPlayerState");
return Class; return Class;
} }
}; };

View File

@@ -123,6 +123,11 @@ public:
return GetPtr<FDeathInfo>(MemberOffsets::FortPlayerStateAthena::DeathInfo); return GetPtr<FDeathInfo>(MemberOffsets::FortPlayerStateAthena::DeathInfo);
} }
void ClearDeathInfo()
{
RtlSecureZeroMemory(GetDeathInfo(), FDeathInfo::GetStructSize()); // TODO FREE THE DEATHTAGS
}
static void ServerSetInAircraftHook(UObject* Context, FFrame& Stack, void* Ret); static void ServerSetInAircraftHook(UObject* Context, FFrame& Stack, void* Ret);
static UClass* StaticClass() static UClass* StaticClass()

View File

@@ -148,7 +148,7 @@ APawn* AGameModeBase::SpawnDefaultPawnForHook(AGameModeBase* GameMode, AControll
/* auto DeathInfo = (void*)(__int64(PlayerStateAthena) + MemberOffsets::FortPlayerStateAthena::DeathInfo); /* auto DeathInfo = (void*)(__int64(PlayerStateAthena) + MemberOffsets::FortPlayerStateAthena::DeathInfo);
FVector DeathLocation = MemberOffsets::DeathInfo::DeathLocation != -1 ? *(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) : FVector(0, 0, 0); FVector DeathLocation = MemberOffsets::DeathInfo::DeathLocation != -1 ? *(FVector*)(__int64(DeathInfo) + MemberOffsets::DeathInfo::DeathLocation) : FVector(0, 0, 0);
bIsRespawning = !(DeathLocation == FVector(0, 0, 0)); // bro kms */ bIsRespawning = !(DeathLocation.CompareVectors(FVector(0, 0, 0))); // bro kms */
auto ASC = PlayerStateAthena->GetAbilitySystemComponent(); auto ASC = PlayerStateAthena->GetAbilitySystemComponent();
auto GameState = ((AFortGameModeAthena*)GameMode)->GetGameStateAthena(); auto GameState = ((AFortGameModeAthena*)GameMode)->GetGameStateAthena();

View File

@@ -9,6 +9,8 @@
#include <random> #include <random>
#include "Package.h"S #include "Package.h"S
#include "AssertionMacros.h" #include "AssertionMacros.h"
#include "bots.h"
#include "gui.h"
FNetworkObjectList& UNetDriver::GetNetworkObjectList() FNetworkObjectList& UNetDriver::GetNetworkObjectList()
{ {
@@ -24,6 +26,11 @@ void UNetDriver::RemoveNetworkActor(AActor* Actor)
void UNetDriver::TickFlushHook(UNetDriver* NetDriver) void UNetDriver::TickFlushHook(UNetDriver* NetDriver)
{ {
/* if (bEnableBotTick)
{
Bots::Tick();
} */
if (Globals::bStartedListening) if (Globals::bStartedListening)
{ {
static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver", false); static auto ReplicationDriverOffset = NetDriver->GetOffset("ReplicationDriver", false);

View File

@@ -157,14 +157,14 @@ UPackage* UObject::GetOutermost() const
bool UObject::IsA(UStruct* otherClass) bool UObject::IsA(UStruct* otherClass)
{ {
UClass* super = ClassPrivate; UStruct* super = ClassPrivate;
while (super) while (super)
{ {
if (otherClass == super) if (otherClass == super)
return true; return true;
super = *(UClass**)(__int64(super) + Offsets::SuperStruct); super = super->GetSuperStruct();
} }
return false; return false;
@@ -174,7 +174,7 @@ UFunction* UObject::FindFunction(const std::string& ShortFunctionName)
{ {
// We could also loop through children. // We could also loop through children.
UClass* super = ClassPrivate; UStruct* super = ClassPrivate;
while (super) while (super)
{ {

View File

@@ -5,7 +5,7 @@
void APlayerController::ServerChangeName(FString& S) void APlayerController::ServerChangeName(FString& S)
{ {
static auto ServerChangeNameFn = FindObject<UFunction>("/Script/Engine.PlayerController.ServerChangeName"); static auto ServerChangeNameFn = FindObject<UFunction>(L"/Script/Engine.PlayerController.ServerChangeName");
this->ProcessEvent(ServerChangeNameFn, &S); this->ProcessEvent(ServerChangeNameFn, &S);
} }

View File

@@ -256,6 +256,7 @@
<ClCompile Include="PlayerState.cpp" /> <ClCompile Include="PlayerState.cpp" />
<ClCompile Include="reboot.cpp" /> <ClCompile Include="reboot.cpp" />
<ClCompile Include="SavePackage.cpp" /> <ClCompile Include="SavePackage.cpp" />
<ClCompile Include="ScriptDisassembler.cpp" />
<ClCompile Include="UnrealMath.cpp" /> <ClCompile Include="UnrealMath.cpp" />
<ClCompile Include="UnrealNames.cpp" /> <ClCompile Include="UnrealNames.cpp" />
<ClCompile Include="UObjectGlobals.cpp" /> <ClCompile Include="UObjectGlobals.cpp" />
@@ -289,6 +290,7 @@
<ClInclude Include="BuildingFoundation.h" /> <ClInclude Include="BuildingFoundation.h" />
<ClInclude Include="BuildingGameplayActor.h" /> <ClInclude Include="BuildingGameplayActor.h" />
<ClInclude Include="BuildingGameplayActorSpawnMachine.h" /> <ClInclude Include="BuildingGameplayActorSpawnMachine.h" />
<ClInclude Include="BuildingItemWeaponUpgradeActor.h" />
<ClInclude Include="BuildingRift.h" /> <ClInclude Include="BuildingRift.h" />
<ClInclude Include="BuildingSMActor.h" /> <ClInclude Include="BuildingSMActor.h" />
<ClInclude Include="BuildingStructuralSupportSystem.h" /> <ClInclude Include="BuildingStructuralSupportSystem.h" />
@@ -319,6 +321,8 @@
<ClInclude Include="finder.h" /> <ClInclude Include="finder.h" />
<ClInclude Include="FortAbilitySet.h" /> <ClInclude Include="FortAbilitySet.h" />
<ClInclude Include="FortAIEncounterInfo.h" /> <ClInclude Include="FortAIEncounterInfo.h" />
<ClInclude Include="FortAthenaAIBotCharacterCustomization.h" />
<ClInclude Include="FortAthenaAIBotCustomizationData.h" />
<ClInclude Include="FortAthenaCreativePortal.h" /> <ClInclude Include="FortAthenaCreativePortal.h" />
<ClInclude Include="FortAthenaMapInfo.h" /> <ClInclude Include="FortAthenaMapInfo.h" />
<ClInclude Include="FortAthenaMutator.h" /> <ClInclude Include="FortAthenaMutator.h" />
@@ -339,6 +343,7 @@
<ClInclude Include="FortAthenaSupplyDrop.h" /> <ClInclude Include="FortAthenaSupplyDrop.h" />
<ClInclude Include="FortAthenaVehicle.h" /> <ClInclude Include="FortAthenaVehicle.h" />
<ClInclude Include="FortAthenaVehicleSpawner.h" /> <ClInclude Include="FortAthenaVehicleSpawner.h" />
<ClInclude Include="FortBotNameSettings.h" />
<ClInclude Include="FortDecoItemDefinition.h" /> <ClInclude Include="FortDecoItemDefinition.h" />
<ClInclude Include="FortGadgetItemDefinition.h" /> <ClInclude Include="FortGadgetItemDefinition.h" />
<ClInclude Include="FortGameMode.h" /> <ClInclude Include="FortGameMode.h" />
@@ -442,6 +447,7 @@
<ClInclude Include="ReversePredicate.h" /> <ClInclude Include="ReversePredicate.h" />
<ClInclude Include="Rotator.h" /> <ClInclude Include="Rotator.h" />
<ClInclude Include="ScriptDelegates.h" /> <ClInclude Include="ScriptDelegates.h" />
<ClInclude Include="ScriptDisassembler.h" />
<ClInclude Include="ScriptInterface.h" /> <ClInclude Include="ScriptInterface.h" />
<ClInclude Include="Set.h" /> <ClInclude Include="Set.h" />
<ClInclude Include="SharedPointer.h" /> <ClInclude Include="SharedPointer.h" />

View File

@@ -289,6 +289,9 @@
<ClCompile Include="FortPawn.cpp"> <ClCompile Include="FortPawn.cpp">
<Filter>FortniteGame\Source\FortniteGame\Private\Player</Filter> <Filter>FortniteGame\Source\FortniteGame\Private\Player</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ScriptDisassembler.cpp">
<Filter>Engine\Source\Developer\ScriptDisassembler\Private</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="log.h" /> <ClInclude Include="log.h" />
@@ -913,6 +916,21 @@
<ClInclude Include="EnvQueryTypes.h"> <ClInclude Include="EnvQueryTypes.h">
<Filter>Engine\Source\Runtime\AIModule\Classes\EnvironmentQuery</Filter> <Filter>Engine\Source\Runtime\AIModule\Classes\EnvironmentQuery</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="ScriptDisassembler.h">
<Filter>Engine\Source\Developer\ScriptDisassembler\Public</Filter>
</ClInclude>
<ClInclude Include="FortBotNameSettings.h">
<Filter>FortniteGame\Source\FortniteGame\Public\AI</Filter>
</ClInclude>
<ClInclude Include="FortAthenaAIBotCharacterCustomization.h">
<Filter>FortniteGame\Source\FortniteGame\Public\AI</Filter>
</ClInclude>
<ClInclude Include="FortAthenaAIBotCustomizationData.h">
<Filter>FortniteGame\Source\FortniteGame\Public\AI</Filter>
</ClInclude>
<ClInclude Include="BuildingItemWeaponUpgradeActor.h">
<Filter>FortniteGame\Source\FortniteGame\Public\Building\GameplayActors</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Filter Include="Engine"> <Filter Include="Engine">
@@ -1167,6 +1185,18 @@
<Filter Include="Engine\Source\Runtime\AIModule\Classes\EnvironmentQuery"> <Filter Include="Engine\Source\Runtime\AIModule\Classes\EnvironmentQuery">
<UniqueIdentifier>{9b5483b5-3984-4fe1-96d2-e37d72642efd}</UniqueIdentifier> <UniqueIdentifier>{9b5483b5-3984-4fe1-96d2-e37d72642efd}</UniqueIdentifier>
</Filter> </Filter>
<Filter Include="Engine\Source\Developer">
<UniqueIdentifier>{4c658de2-f9aa-4a42-9d7c-21014cb29b3d}</UniqueIdentifier>
</Filter>
<Filter Include="Engine\Source\Developer\ScriptDisassembler">
<UniqueIdentifier>{f64d3dc0-39df-46a5-a451-2f9011ecbad1}</UniqueIdentifier>
</Filter>
<Filter Include="Engine\Source\Developer\ScriptDisassembler\Public">
<UniqueIdentifier>{1df3fb86-ba8f-446d-be0c-cfeb7ec94137}</UniqueIdentifier>
</Filter>
<Filter Include="Engine\Source\Developer\ScriptDisassembler\Private">
<UniqueIdentifier>{45f601de-1a88-490c-a74a-5cf729b16dfb}</UniqueIdentifier>
</Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="UnrealEngine.cpp"> <None Include="UnrealEngine.cpp">

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,50 @@
#pragma once
#include "Array.h"
#include <fstream>
#include "reboot.h"
class FKismetBytecodeDisassembler
{
private:
std::vector<uint8> Script;
std::string Indents;
std::ofstream Stream;
public:
void DisassembleStructure(UFunction* Source);
int32 ReadINT(int32& ScriptIndex);
uint64 ReadQWORD(int32& ScriptIndex);
uint8 ReadBYTE(int32& ScriptIndex);
std::string ReadName(int32& ScriptIndex);
uint16 ReadWORD(int32& ScriptIndex);
float ReadFLOAT(int32& ScriptIndex);
CodeSkipSizeType ReadSkipCount(int32& ScriptIndex);
std::string ReadString(int32& ScriptIndex);
std::string ReadString8(int32& ScriptIndex);
std::string ReadString16(int32& ScriptIndex);
uint8 SerializeExpr(int32& ScriptIndex);
void ProcessCastByte(int32 CastType, int32& ScriptIndex);
void ProcessCommon(int32& ScriptIndex, uint8 Opcode);
void AddIndent()
{
Indents += (" ");
}
void DropIndent()
{
// Blah, this is awful
// Indents.LeftInline(Indents.Len() - 2);
Indents = Indents.substr(2);
}
template <typename T>
T* ReadPointer(int32& ScriptIndex)
{
return (T*)ReadQWORD(ScriptIndex);
}
};

View File

@@ -457,6 +457,7 @@ void Offsets::FindAll()
} }
Offsets::IsNetRelevantFor = FindIsNetRelevantForOffset(); Offsets::IsNetRelevantFor = FindIsNetRelevantForOffset();
Offsets::Script = Offsets::Children + 8 + 4 + 4;
} }
void Offsets::Print() void Offsets::Print()
@@ -468,7 +469,7 @@ void Offsets::Print()
LOG_INFO(LogDev, "Func: 0x{:x}", Func); LOG_INFO(LogDev, "Func: 0x{:x}", Func);
LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors); LOG_INFO(LogDev, "ServerReplicateActors: 0x{:x}", ServerReplicateActors);
LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame); LOG_INFO(LogDev, "ReplicationFrame: 0x{:x}", ReplicationFrame);
LOG_INFO(LogDev, "IsNetRelevantFor: 0x{:x}", IsNetRelevantFor); LOG_INFO(LogDev, "Script: 0x{:x}", Script);
} }
void Addresses::Init() void Addresses::Init()

View File

@@ -95,6 +95,7 @@ namespace Offsets
extern inline uint64 IsNetRelevantFor = 0; extern inline uint64 IsNetRelevantFor = 0;
extern inline uint64 NetworkObjectList = 0; extern inline uint64 NetworkObjectList = 0;
extern inline uint64 ClientWorldPackageName = 0; extern inline uint64 ClientWorldPackageName = 0;
extern inline uint64 Script = 0;
void FindAll(); void FindAll();
void Print(); void Print();

View File

@@ -11,6 +11,9 @@
#include "FortGameModeAthena.h" #include "FortGameModeAthena.h"
#include "FortGameStateAthena.h" #include "FortGameStateAthena.h"
#include "FortPlayerControllerAthena.h" #include "FortPlayerControllerAthena.h"
#include "FortBotNameSettings.h"
#include "KismetTextLibrary.h"
#include "FortAthenaAIBotCustomizationData.h"
using UNavigationSystemV1 = UObject; using UNavigationSystemV1 = UObject;
using UNavigationSystemConfig = UObject; using UNavigationSystemConfig = UObject;
@@ -229,7 +232,7 @@ static void SetupNavConfig(const FName& AgentName)
SetNavigationSystem(NavSystemOverride); SetNavigationSystem(NavSystemOverride);
} }
static AFortPlayerPawn* SpawnAIFromCustomizationData(const FVector& Location, UObject* CustomizationData) static AFortPlayerPawn* SpawnAIFromCustomizationData(const FVector& Location, UFortAthenaAIBotCustomizationData* CustomizationData)
{ {
static auto PawnClassOffset = CustomizationData->GetOffset("PawnClass"); static auto PawnClassOffset = CustomizationData->GetOffset("PawnClass");
auto PawnClass = CustomizationData->Get<UClass*>(PawnClassOffset); auto PawnClass = CustomizationData->Get<UClass*>(PawnClassOffset);
@@ -242,12 +245,38 @@ static AFortPlayerPawn* SpawnAIFromCustomizationData(const FVector& Location, UO
auto Pawn = GetWorld()->SpawnActor<AFortPlayerPawn>(PawnClass, Location); auto Pawn = GetWorld()->SpawnActor<AFortPlayerPawn>(PawnClass, Location);
if (!Pawn)
{
LOG_INFO(LogAI, "Failed to spawn pawn!");
return nullptr;
}
auto Controller = Pawn->GetController();
if (!Controller)
{
LOG_INFO(LogAI, "No controller!");
Pawn->K2_DestroyActor();
return nullptr;
}
auto PlayerState = Controller->GetPlayerState();
if (!PlayerState)
{
LOG_INFO(LogAI, "No PlayerState!");
Controller->K2_DestroyActor();
Pawn->K2_DestroyActor();
return nullptr;
}
static auto CharacterCustomizationOffset = CustomizationData->GetOffset("CharacterCustomization"); static auto CharacterCustomizationOffset = CustomizationData->GetOffset("CharacterCustomization");
auto CharacterCustomization = CustomizationData->Get(CharacterCustomizationOffset); auto CharacterCustomization = CustomizationData->Get(CharacterCustomizationOffset);
auto CharacterCustomizationLoadoutOffset = CharacterCustomization->GetOffset("CustomizationLoadout"); auto CharacterCustomizationLoadoutOffset = CharacterCustomization->GetOffset("CustomizationLoadout");
auto CharacterCustomizationLoadout = CharacterCustomization->GetPtr<FFortAthenaLoadout>(CharacterCustomizationLoadoutOffset); auto CharacterCustomizationLoadout = CharacterCustomization->GetPtr<FFortAthenaLoadout>(CharacterCustomizationLoadoutOffset);
auto CharacterToApply = CharacterCustomizationLoadout->GetCharacter();
ApplyCID(Pawn, CharacterCustomizationLoadout->GetCharacter()); ApplyCID(Pawn, CharacterToApply, true); // bruhh
struct FItemAndCount struct FItemAndCount
{ {
@@ -259,30 +288,77 @@ static AFortPlayerPawn* SpawnAIFromCustomizationData(const FVector& Location, UO
static auto StartupInventoryOffset = CustomizationData->GetOffset("StartupInventory"); static auto StartupInventoryOffset = CustomizationData->GetOffset("StartupInventory");
auto StartupInventory = CustomizationData->Get(StartupInventoryOffset); auto StartupInventory = CustomizationData->Get(StartupInventoryOffset);
static auto StartupInventoryItemsOffset = StartupInventory->GetOffset("Items"); static auto StartupInventoryItemsOffset = StartupInventory->GetOffset("Items");
auto& StartupInventoryItems = StartupInventory->Get<TArray<FItemAndCount>>(StartupInventoryItemsOffset);
auto Controller = Pawn->GetController(); std::vector<std::pair<UFortItemDefinition*, int>> ItemsToGrant;
LOG_INFO(LogDev, "Controller: {} StartupInventoryItems.Num: {}", Controller ? Controller->GetFullName() : "InvalidObject", StartupInventoryItems.Num());
if (Controller) if (Fortnite_Version < 13)
{ {
/* static auto InventoryOffset = Controller->GetOffset("Inventory"); auto& StartupInventoryItems = StartupInventory->Get<TArray<UFortItemDefinition*>>(StartupInventoryItemsOffset);
auto Inventory = Controller->Get<AFortInventory*>(InventoryOffset);
for (int i = 0; i < StartupInventoryItems.Num(); i++) for (int i = 0; i < StartupInventoryItems.Num(); i++)
{ {
auto pair = Inventory->AddItem(StartupInventoryItems.at(i).Item, nullptr, StartupInventoryItems.at(i).Count); ItemsToGrant.push_back({ StartupInventoryItems.at(i), 1 });
}
}
else
{
auto& StartupInventoryItems = StartupInventory->Get<TArray<FItemAndCount>>(StartupInventoryItemsOffset);
for (int i = 0; i < StartupInventoryItems.Num(); i++)
{
ItemsToGrant.push_back({ StartupInventoryItems.at(i).Item, StartupInventoryItems.at(i).Count });
}
}
static auto InventoryOffset = Controller->GetOffset("Inventory");
auto Inventory = Controller->Get<AFortInventory*>(InventoryOffset);
if (Inventory)
{
for (int i = 0; i < ItemsToGrant.size(); i++)
{
auto pair = Inventory->AddItem(ItemsToGrant.at(i).first, nullptr, ItemsToGrant.at(i).second);
LOG_INFO(LogDev, "pair.first.size(): {}", pair.first.size()); LOG_INFO(LogDev, "pair.first.size(): {}", pair.first.size());
if (pair.first.size() > 0) if (pair.first.size() > 0)
{ {
if (auto weaponDef = Cast<UFortWeaponItemDefinition>(StartupInventoryItems.at(i).Item)) if (auto weaponDef = Cast<UFortWeaponItemDefinition>(ItemsToGrant.at(i).first))
Pawn->EquipWeaponDefinition(weaponDef, pair.first.at(0)->GetItemEntry()->GetItemGuid()); Pawn->EquipWeaponDefinition(weaponDef, pair.first.at(0)->GetItemEntry()->GetItemGuid());
} }
} */ }
// Inventory->Update(); // crashes idk why Inventory->Update();
}
static auto BotNameSettingsOffset = CustomizationData->GetOffset("BotNameSettings");
auto BotNameSettings = CustomizationData->Get<UFortBotNameSettings*>(BotNameSettingsOffset);
FString Name;
if (BotNameSettings)
{
static int CurrentId = 0; // scuffed!
static auto DisplayNameOffset = FindOffsetStruct("/Script/FortniteGame.FortItemDefinition", "DisplayName");
switch (BotNameSettings->GetNamingMode())
{
case EBotNamingMode::Custom:
Name = UKismetTextLibrary::Conv_TextToString(BotNameSettings->GetOverrideName());
break;
case EBotNamingMode::SkinName:
Name = CharacterToApply ? UKismetTextLibrary::Conv_TextToString(*(FText*)(__int64(CharacterCustomizationLoadout->GetCharacter()) + DisplayNameOffset)) : L"InvalidCharacter";
Name.Set((std::wstring(Name.Data.Data) += std::to_wstring(CurrentId++)).c_str());
break;
default:
Name = L"Unknown";
break;
}
}
if (Name.Data.Data && Name.Data.Num() > 0)
{
Controller->ServerChangeName(Name);
} }
return Pawn; return Pawn;

View File

@@ -252,6 +252,9 @@ namespace Bots
static void Tick() static void Tick()
{ {
if (AllPlayerBotsToTick.size() == 0)
return;
auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState()); auto GameState = Cast<AFortGameStateAthena>(GetWorld()->GetGameState());
auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode()); auto GameMode = Cast<AFortGameModeAthena>(GetWorld()->GetGameMode());
@@ -311,3 +314,8 @@ namespace Bots
// AllBuildingContainers.Free(); // AllBuildingContainers.Free();
} }
} }
namespace Bosses
{
}

View File

@@ -10,6 +10,7 @@
#include "FortLootPackage.h" #include "FortLootPackage.h"
#include "bots.h" #include "bots.h"
#include "FortAthenaMutator_Bots.h" #include "FortAthenaMutator_Bots.h"
#include "ai.h"
bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController) bool IsOperator(APlayerState* PlayerState, AFortPlayerController* PlayerController)
{ {
@@ -646,6 +647,43 @@ void ServerCheatHook(AFortPlayerControllerAthena* PlayerController, FString Msg)
SendMessageToConsole(PlayerController, L"Not a valid class!"); SendMessageToConsole(PlayerController, L"Not a valid class!");
} }
} }
else if (Command == "spawnbottest")
{
// /Game/Athena/AI/MANG/BotData/
if (NumArgs < 1)
{
SendMessageToConsole(PlayerController, L"Please provide a customization object!");
return;
}
auto Pawn = ReceivingController->GetPawn();
if (!Pawn)
{
SendMessageToConsole(PlayerController, L"No pawn to spawn bot at!");
return;
}
auto CustomizationData = LoadObject<UFortAthenaAIBotCustomizationData>(Arguments[1], UFortAthenaAIBotCustomizationData::StaticClass());
if (!CustomizationData)
{
SendMessageToConsole(PlayerController, L"Invalid CustomizationData!");
return;
}
auto NewPawn = SpawnAIFromCustomizationData(Pawn->GetActorLocation(), CustomizationData);
if (NewPawn)
{
SendMessageToConsole(PlayerController, L"Spawned!");
}
else
{
SendMessageToConsole(PlayerController, L"Failed to spawn!");
}
}
else if (Command == "spawnbot") else if (Command == "spawnbot")
{ {
auto Pawn = ReceivingController->GetPawn(); auto Pawn = ReceivingController->GetPawn();

View File

@@ -179,11 +179,6 @@ void ProcessEventHook(UObject* Object, UFunction* Function, void* Parameters)
if (!Object || !Function) if (!Object || !Function)
return; return;
if (bEnableBotTick)
{
Bots::Tick();
}
if (Globals::bLogProcessEvent) if (Globals::bLogProcessEvent)
{ {
auto FunctionName = Function->GetName(); // UKismetSystemLibrary::GetPathName(Function).ToString(); auto FunctionName = Function->GetName(); // UKismetSystemLibrary::GetPathName(Function).ToString();

View File

@@ -761,6 +761,11 @@ DWORD WINAPI Main(LPVOID)
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"), Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerSendZiplineState"),
AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false); AFortPlayerPawn::ServerSendZiplineStateHook, nullptr, false);
Hooking::MinHook::Hook((PVOID)GetFunctionIdxOrPtr(FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerOnExitVehicle"), true), AFortPlayerPawn::ServerOnExitVehicleHook, (PVOID*)&AFortPlayerPawn::ServerOnExitVehicleOriginal); Hooking::MinHook::Hook((PVOID)GetFunctionIdxOrPtr(FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerOnExitVehicle"), true), AFortPlayerPawn::ServerOnExitVehicleHook, (PVOID*)&AFortPlayerPawn::ServerOnExitVehicleOriginal);
if (Fortnite_Version == 1.11 || Fortnite_Version > 1.8)
{
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerReviveFromDBNO"),
AFortPlayerPawn::ServerReviveFromDBNOHook, nullptr, false);
}
static auto FortGameplayAbilityAthena_PeriodicItemGrantDefault = FindObject<UFortGameplayAbilityAthena_PeriodicItemGrant>(L"/Script/FortniteGame.Default__FortGameplayAbilityAthena_PeriodicItemGrant"); static auto FortGameplayAbilityAthena_PeriodicItemGrantDefault = FindObject<UFortGameplayAbilityAthena_PeriodicItemGrant>(L"/Script/FortniteGame.Default__FortGameplayAbilityAthena_PeriodicItemGrant");
@@ -1008,12 +1013,6 @@ DWORD WINAPI Main(LPVOID)
static auto GameplayEventDataSize = FindObject<UStruct>(L"/Script/GameplayAbilities.GameplayEventData")->GetPropertiesSize(); static auto GameplayEventDataSize = FindObject<UStruct>(L"/Script/GameplayAbilities.GameplayEventData")->GetPropertiesSize();
LOG_INFO(LogDev, "GameplayEventDataSize: 0x{:x} {}", GameplayEventDataSize, GameplayEventDataSize); LOG_INFO(LogDev, "GameplayEventDataSize: 0x{:x} {}", GameplayEventDataSize, GameplayEventDataSize);
if (Fortnite_Version == 1.11 || Fortnite_Version > 1.8)
{
Hooking::MinHook::Hook(FortPlayerPawnAthenaDefault, FindObject<UFunction>(L"/Script/FortniteGame.FortPlayerPawn.ServerReviveFromDBNO"),
AFortPlayerPawn::ServerReviveFromDBNOHook, nullptr, false);
}
{ {
int increaseOffset = 0x10; int increaseOffset = 0x10;

View File

@@ -12,6 +12,8 @@ typedef short int16;
typedef int int32; typedef int int32;
typedef __int64 int64; typedef __int64 int64;
typedef unsigned int uint32; typedef unsigned int uint32;
typedef char ANSICHAR;
typedef uint32_t CodeSkipSizeType;
typedef unsigned __int64 uint64; typedef unsigned __int64 uint64;
extern inline int Engine_Version = 0; // For example, 420, 421, etc. // Prevent using this when possible. extern inline int Engine_Version = 0; // For example, 420, 421, etc. // Prevent using this when possible.