All I cba doing, does not work atm.

This commit is contained in:
Nax
2025-03-28 21:33:12 +00:00
parent 80969a55c0
commit 730d404c56
16 changed files with 52 additions and 7136 deletions
-315
View File
@@ -1,315 +0,0 @@
#pragma once
#include "framework.h"
namespace AI
{
static vector<FString> BotNames{
L"SuperNax89", L"BlackSoy79", L"BlackHole9", L"GameMaster45", L"AthenaBot1", L"JimmyJim3"
};
FString GetRandomBotName()
{
if (!BotNames.empty())
return BotNames[rand() % BotNames.size()];
return L"Bot";
}
UAthenaPickaxeItemDefinition* GetRandomPickaxe()
{
static vector<UAthenaPickaxeItemDefinition*> Pickaxes{};
if (Pickaxes.empty())
{
for (int i = 0; i < UObject::GObjects.GetTypedPtr()->Num(); i++)
{
UObject* Object = UObject::GObjects.GetTypedPtr()->GetByIndex(i);
if (!Object)
continue;
if (Object->IsA(UAthenaPickaxeItemDefinition::StaticClass()))
{
auto Pickaxe = reinterpret_cast<UAthenaPickaxeItemDefinition*>(Object);
if (Pickaxe->GetName().contains("Dev"))
continue;
Pickaxes.push_back(Pickaxe);
}
}
}
return Pickaxes[rand() % Pickaxes.size()];
}
UAthenaDanceItemDefinition* GetRandomEmote()
{
static vector<UAthenaDanceItemDefinition*> Emotes{};
if (Emotes.empty())
{
for (int i = 0; i < UObject::GObjects.GetTypedPtr()->Num(); i++)
{
UObject* Object = UObject::GObjects.GetTypedPtr()->GetByIndex(i);
if (!Object)
continue;
if (Object->IsA(UAthenaDanceItemDefinition::StaticClass()))
{
auto Emote = reinterpret_cast<UAthenaDanceItemDefinition*>(Object);
Emotes.push_back(Emote);
}
}
}
return Emotes[rand() % Emotes.size()];
}
struct AthenaBotLoadout
{
public:
UFortHeroType* HeroType = nullptr;
UAthenaPickaxeItemDefinition* PickaxeID = nullptr;
UAthenaDanceItemDefinition* AssignedEmote = nullptr;
};
class AthenaBot
{
public:
FVector SpawnLocation;
FString DisplayName;
AthenaBotLoadout Loadout;
APlayerPawn_Athena_C* Pawn;
AAthena_PlayerController_C* PlayerController;
AFortPlayerStateAthena* PlayerState;
bool bIsDead = false;
EFortMovementStyle MovementStyle = EFortMovementStyle::Charging;
public:
AthenaBot(FVector spawnLocation, FString displayName, UFortHeroType* heroType, UAthenaPickaxeItemDefinition* pickaxeID = GetRandomPickaxe(), UAthenaDanceItemDefinition* assignedEmote = GetRandomEmote())
{
SpawnLocation = spawnLocation;
DisplayName = displayName;
Loadout.HeroType = heroType;
Loadout.AssignedEmote = assignedEmote;
Loadout.PickaxeID = pickaxeID;
Pawn = Spawner::SpawnActor<APlayerPawn_Athena_C>(APlayerPawn_Athena_C::StaticClass(), SpawnLocation);
if (!Pawn)
{
Logging::Log(ELogEvent::Warning, ELogType::Bot, "Failed to spawn bot.");
return;
}
PlayerController = Spawner::SpawnActor<AAthena_PlayerController_C>(AAthena_PlayerController_C::StaticClass(), SpawnLocation);
PlayerState = Spawner::SpawnActor<AFortPlayerStateAthena>(AFortPlayerStateAthena::StaticClass(), SpawnLocation);
PlayerController->Player = reinterpret_cast<UPlayer*>(UGameplayStatics::SpawnObject(UPlayer::StaticClass(), PlayerController));
PlayerController->PlayerState = PlayerState;
PlayerController->OnRep_PlayerState();
Pawn->PlayerState = PlayerState;
Pawn->OnRep_PlayerState();
Pawn->Controller = PlayerController;
PlayerState->HeroType = Loadout.HeroType;
PlayerState->OnRep_HeroType();
for (int i = 0; i < Loadout.HeroType->Specializations.Num(); i++)
{
auto Specialization = Loadout.HeroType->Specializations[i].Get();
Logging::Log(ELogEvent::Info, ELogType::Athena, "Specialization:AssetPathName : %s", Loadout.HeroType->Specializations[i].ObjectID.AssetPathName.ToString().c_str());
Logging::Log(ELogEvent::Info, ELogType::Athena, "Specialization:SubPathString : %s", Loadout.HeroType->Specializations[i].ObjectID.SubPathString.ToString().c_str());
if (!Specialization)
continue;
for (int j = 0; j < Specialization->CharacterParts.Num(); j++)
{
auto CharacterPart = Specialization->CharacterParts[j].Get();
Logging::Log(ELogEvent::Info, ELogType::Athena, "CharacterPart:AssetPathName : %s", Specialization->CharacterParts[j].ObjectID.AssetPathName.ToString().c_str());
if (!CharacterPart)
continue;
PlayerState->CharacterParts.Parts[j] = CharacterPart;
}
}
PlayerState->OnRep_CharacterParts();
PlayerState->bIsSpectator = false;
PlayerState->bIsABot = true;
PlayerController->Possess(Pawn);
Pawn->PawnUniqueID = rand() % 1000;
Pawn->OnRep_PawnUniqueID();
if (BotNames.empty())
{
Logging::Log(ELogEvent::Error, ELogType::Bot, "Could not spawn a bot, ran out of names.");
return;
}
PlayerController->ServerChangeName(DisplayName);
PlayerState->bHasFinishedLoading = true;
PlayerState->bHasStartedPlaying = true;
PlayerState->OnRep_bHasStartedPlaying();
PlayerController->ServerSetClientHasFinishedLoading(true);
PlayerController->ServerLoadingScreenDropped();
PlayerController->bHasInitiallySpawned = true;
PlayerController->bAssignedStartSpawn = true;
PlayerController->bReadyToStartMatch = true;
PlayerController->bClientPawnIsLoaded = true;
PlayerController->bHasClientFinishedLoading = true;
PlayerController->bHasServerFinishedLoading = true;
PlayerController->OnRep_bHasServerFinishedLoading();
Pawn->SetMaxHealth(100.f);
Pawn->SetHealth(100.f);
auto CheatManager = reinterpret_cast<UFortCheatManager*>(UGameplayStatics::SpawnObject(UFortCheatManager::StaticClass(), PlayerController));
PlayerController->CheatManager = CheatManager;
CheatManager->ToggleInfiniteAmmo();
auto PickaxeWID = Loadout.PickaxeID->WeaponDefinition;
auto WorldItem = InventoryHandler::CreateItem(PlayerController, PickaxeWID);
Pawn->EquipWeaponDefinition(PickaxeWID, WorldItem->GetItemGuid());
PlayerController->ServerAcknowledgePossession(Pawn);
EFortTeam Old = PlayerState->TeamIndex;
PlayerState->TeamIndex = EFortTeam::HumanPvP_Team1;
PlayerState->OnRep_TeamIndex(Old);
PlayerController->ServerReadyToStartMatch();
Globals::GetGameState()->PlayersLeft++;
Globals::GetGameState()->OnRep_PlayersLeft();
Globals::GetGameState()->PlayerArray.Add(PlayerState);
Globals::GetGameMode()->AlivePlayers.Add(PlayerController);
Logging::Log(ELogEvent::Info, ELogType::Bot, "Spawned bot: %s", DisplayName.ToString().c_str());
}
};
vector<AthenaBot> Bots{};
AthenaBot GetBotByDisplayName(FString DisplayName)
{
for (auto bot : Bots)
{
if (bot.DisplayName == DisplayName)
return bot;
}
}
AthenaBot GetBotByPlayerController(AAthena_PlayerController_C* PlayerController)
{
for (auto bot : Bots)
{
if (bot.PlayerController == PlayerController)
return bot;
}
}
// APlayerPawn_Athena_C
APlayerPawn_Athena_C* SpawnBot(FVector Location)
{
auto Pawn = Spawner::SpawnActor<APlayerPawn_Athena_C>(APlayerPawn_Athena_C::StaticClass(), Location);
if (!Pawn)
{
Logging::Log(ELogEvent::Warning, ELogType::Bot, "Failed to spawn bot.");
return nullptr;
}
auto PlayerController = Spawner::SpawnActor<AAthena_PlayerController_C>(AAthena_PlayerController_C::StaticClass(), Location);
auto PlayerState = Spawner::SpawnActor<AFortPlayerStateAthena>(AFortPlayerStateAthena::StaticClass(), Location);
PlayerController->Player = reinterpret_cast<UPlayer*>(UGameplayStatics::SpawnObject(UPlayer::StaticClass(), PlayerController));
PlayerController->PlayerState = PlayerState;
PlayerController->OnRep_PlayerState();
Pawn->PlayerState = PlayerState;
Pawn->OnRep_PlayerState();
Pawn->Controller = PlayerController;
if (!Pawn->CharacterMovement)
{
Logging::Log(ELogEvent::Warning, ELogType::Bot, "Wild.");
Pawn->CharacterMovement = reinterpret_cast<UCharacterMovementComponent*>(UGameplayStatics::SpawnObject(UCharacterMovementComponent::StaticClass(), Pawn));
}
static auto HeadPart = StaticFindObject<UCustomCharacterPart>(L"/Game/Characters/CharacterParts/Female/Medium/Heads/F_Med_Head1.F_Med_Head1");
static auto BodyPart = StaticFindObject<UCustomCharacterPart>(L"/Game/Characters/CharacterParts/Female/Medium/Bodies/F_Med_Soldier_01.F_Med_Soldier_01");
PlayerState->CharacterParts.Parts[0] = HeadPart;
PlayerState->CharacterParts.Parts[1] = BodyPart;
PlayerState->OnRep_CharacterParts();
PlayerState->bIsSpectator = false;
PlayerState->bIsABot = true;
PlayerController->Possess(Pawn);
Pawn->PawnUniqueID = rand() % 1000;
Pawn->OnRep_PawnUniqueID();
static vector<FString> BotNames{
L"SuperNax89", L"BlackSoy79", L"BlackHole9", L"GameMaster45", L"AthenaBot1", L"JimmyJim3"
};
if (BotNames.empty())
{
Logging::Log(ELogEvent::Error, ELogType::Bot, "Could not spawn a bot, ran out of names.");
return nullptr;
}
int index = rand() % BotNames.size();
FString BotName = BotNames[index];
PlayerController->ServerChangeName(BotName);
BotNames.erase(BotNames.begin() + index);
PlayerState->bHasFinishedLoading = true;
PlayerState->bHasStartedPlaying = true;
PlayerState->OnRep_bHasStartedPlaying();
PlayerController->ServerSetClientHasFinishedLoading(true);
PlayerController->ServerLoadingScreenDropped();
PlayerController->bHasInitiallySpawned = true;
PlayerController->bAssignedStartSpawn = true;
PlayerController->bReadyToStartMatch = true;
PlayerController->bClientPawnIsLoaded = true;
PlayerController->bHasClientFinishedLoading = true;
PlayerController->bHasServerFinishedLoading = true;
PlayerController->OnRep_bHasServerFinishedLoading();
Pawn->SetMaxHealth(100.f);
Pawn->SetHealth(100.f);
auto CheatManager = reinterpret_cast<UFortCheatManager*>(UGameplayStatics::SpawnObject(UFortCheatManager::StaticClass(), PlayerController));
PlayerController->CheatManager = CheatManager;
CheatManager->ToggleInfiniteAmmo();
static auto PickaxeWID = StaticFindObject<UFortWeaponMeleeItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01");
auto WorldItem = InventoryHandler::CreateItem(PlayerController, PickaxeWID);
Pawn->EquipWeaponDefinition(PickaxeWID, WorldItem->GetItemGuid());
PlayerController->ServerAcknowledgePossession(Pawn);
EFortTeam Old = PlayerState->TeamIndex;
PlayerState->TeamIndex = EFortTeam::HumanPvP_Team1;
PlayerState->OnRep_TeamIndex(Old);
PlayerController->ServerReadyToStartMatch();
Globals::GetGameState()->PlayersLeft++;
Globals::GetGameState()->OnRep_PlayersLeft();
Globals::GetGameState()->PlayerArray.Add(PlayerState);
Globals::GetGameMode()->AlivePlayers.Add(PlayerController);
Logging::Log(ELogEvent::Info, ELogType::Bot, "Spawned bot: %s", BotName.ToString().c_str());
return Pawn;
}
}
+5 -5
View File
@@ -3,10 +3,10 @@
namespace AbilitiesHandler // for now as a symbol with this name already exists shit
{
FGameplayAbilitySpecHandle* (*GiveAbility)(UAbilitySystemComponent* _this, FGameplayAbilitySpecHandle* outHandle, FGameplayAbilitySpec inSpec) = decltype(GiveAbility)(Memory::GetAddress(0x66cbc0));
__int64 (*oGiveAbilityAndActivateOnce)(void*, FGameplayAbilitySpecHandle*, FGameplayAbilitySpec) = decltype(oGiveAbilityAndActivateOnce)(Memory::GetAddress(0x66cce0));
bool (*InternalTryActivateAbility)(UAbilitySystemComponent* _this, FGameplayAbilitySpecHandle Handle, FPredictionKey InPredictionKey, UGameplayAbility** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, FGameplayEventData* TriggerEventData) = decltype(InternalTryActivateAbility)(Memory::GetAddress(0x66e370));
__int64 (*SpecConstructor)(FGameplayAbilitySpec* spec, UObject* Ability, int Level, int InputID, UObject* SourceObject) = decltype(SpecConstructor)(Memory::GetAddress(0x693000));
FGameplayAbilitySpecHandle* (*GiveAbility)(UAbilitySystemComponent* _this, FGameplayAbilitySpecHandle* outHandle, FGameplayAbilitySpec inSpec) = decltype(GiveAbility)(Memory::GetAddress(0x527580));
__int64 (*oGiveAbilityAndActivateOnce)(void*, FGameplayAbilitySpecHandle*, FGameplayAbilitySpec) = decltype(oGiveAbilityAndActivateOnce)(Memory::GetAddress(0x5276a0));
bool (*InternalTryActivateAbility)(UAbilitySystemComponent* _this, FGameplayAbilitySpecHandle Handle, FPredictionKey InPredictionKey, UGameplayAbility** OutInstancedAbility, void* OnGameplayAbilityEndedDelegate, FGameplayEventData* TriggerEventData) = decltype(InternalTryActivateAbility)(Memory::GetAddress(0x528b50));
__int64 (*SpecConstructor)(FGameplayAbilitySpec* spec, UObject* Ability, int Level, int InputID, UObject* SourceObject) = decltype(SpecConstructor)(Memory::GetAddress(0x103da30));
FGameplayAbilitySpec* FindAbilitySpecFromHandle(UAbilitySystemComponent* AbilitySystemComponent, FGameplayAbilitySpecHandle Handle)
{
@@ -108,7 +108,7 @@ namespace AbilitiesHandler // for now as a symbol with this name already exists
{
auto DefaultObject = UFortAbilitySystemComponentAthena::StaticClass()->DefaultObject;
Memory::VirtualHook(DefaultObject, 0xf4, hkInternalServerTryActivateAbility);
Memory::VirtualHook(DefaultObject, 0xcb, hkInternalServerTryActivateAbility);
Logging::Log(ELogEvent::Info, ELogType::Hook, "Abilities hooks initialized.");
}
+2 -2
View File
@@ -176,8 +176,8 @@ namespace ActorHandler
void Initialize()
{
MH_STATUS StatusOnDamageServer = Memory::CreateHook(Memory::GetAddress(0x14aa5f0), hkOnDamageServer, (void**)&oOnDamageServer);
MH_STATUS StatusCompletePickupAnimation = Memory::CreateHook(Memory::GetAddress(0x109d390), hkCompletePickupAnimation, (void**)&oCompletePickupAnimation);
MH_STATUS StatusOnDamageServer = Memory::CreateHook(Memory::GetAddress(0x1076ec0), hkOnDamageServer, (void**)&oOnDamageServer);
MH_STATUS StatusCompletePickupAnimation = Memory::CreateHook(Memory::GetAddress(0xd01680), hkCompletePickupAnimation, (void**)&oCompletePickupAnimation);
#ifdef LOG_HOOKSTATUS
Logging::Log(ELogEvent::Info, ELogType::Hook, "hkOnDamageServer Status: %s.", MH_StatusToString(StatusOnDamageServer));
-66
View File
@@ -1,66 +0,0 @@
#pragma once
#include "framework.h"
#define RESULT_DECL void*const RESULT_PARAM
class FOutputDevice
{
public:
bool bSuppressEventTag;
bool bAutoEmitLineTerminator;
uint8_t _Padding1[0x6];
};
class FFrame : public FOutputDevice
{
public:
void** VTable;
UFunction* Node;
UObject* Object;
uint8* Code;
uint8* Locals;
UProperty* MostRecentProperty;
uint8* MostRecentPropertyAddress;
FFrame* PreviousFrame;
UField* PropertyChainForCompiledIn;
UFunction* CurrentNativeFunction;
bool bArrayContextFailed;
public:
__forceinline void StepExplicitProperty(void* const Result, void* Property)
{
static void (*StepExplicitPropertyOriginal)(__int64 frame, void* const Result, void* Property) = decltype(StepExplicitPropertyOriginal)(Memory::GetAddress(0x19b0980));
StepExplicitPropertyOriginal(__int64(this), Result, Property);
}
__forceinline void Step(UObject* Context, RESULT_DECL)
{
static void (*StepOriginal)(__int64 frame, UObject * Context, RESULT_DECL) = decltype(StepOriginal)(Memory::GetAddress(0x19b0950));
StepOriginal(__int64(this), Context, RESULT_PARAM);
}
__forceinline void StepCompiledIn(void* const Result)
{
if (Code)
{
Step(Object, Result);
}
else
{
PropertyChainForCompiledIn = PropertyChainForCompiledIn->Next;
StepExplicitProperty(Result, PropertyChainForCompiledIn);
}
}
template<typename TNativeType>
__forceinline TNativeType& StepCompiledInRef(void* const TemporaryBuffer)
{
MostRecentPropertyAddress = nullptr;
if (Code)
Step(Object, TemporaryBuffer);
return (MostRecentPropertyAddress != NULL) ? *(TNativeType*)(MostRecentPropertyAddress) : *(TNativeType*)TemporaryBuffer;
}
};
+13 -22
View File
@@ -39,14 +39,6 @@ namespace GameMode
GameMode->FortGameSession->MaxPlayers = Playlist->MaxPlayers;
GameMode->FortGameSession->MaxPartySize = Playlist->MaxSocialPartySize;
if (!Globals::bUseBeacons) // No idea why it does this tbh
{
Logging::Log(ELogEvent::Info, ELogType::Game, "GamePhase set to 'Setup'");
EAthenaGamePhase OldGamePhase = GameState->GamePhase;
GameState->GamePhase = EAthenaGamePhase::Setup;
GameState->OnRep_GamePhase(OldGamePhase);
}
}
else
Logging::Log(ELogEvent::Error, ELogType::Athena, "Playlist is null.");
@@ -64,12 +56,6 @@ namespace GameMode
Server::Listen();
Server::Initialize();
ActorHandler::Initialize();
auto Lake2 = StaticFindObject<ABuildingFoundation>(L"/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.LF_Lake2");
auto FloatingIsland = StaticFindObject<ABuildingFoundation>(L"/Game/Athena/Maps/Athena_POI_Foundations.Athena_POI_Foundations.PersistentLevel.LF_FloatingIsland");
Utils::ShowFoundation(Lake2);
Utils::ShowFoundation(FloatingIsland);
}
GameMode->bWorldIsReady = true;
@@ -88,18 +74,23 @@ namespace GameMode
int hkPickTeam(AFortGameModeAthena* GameMode, uint8 preferredTeam, AActor* Controller)
{
return 3;
}
static int CurrentIndex = 3;
static int MaxTeamSize = Globals::GetGameState()->CurrentPlaylistInfo.OverridePlaylist->MaxTeamSize;
static int CurrentSize = 0;
/*
Deciding whether to do proper game sessions or nah.
*/
if (CurrentSize >= MaxTeamSize)
CurrentIndex++;
CurrentSize++;
return CurrentIndex;
}
void Initialize()
{
MH_STATUS StatusReadyToStartMatch = Memory::CreateHook(Memory::GetAddress(0xcb45a0), hkReadyToStartMatch, (void**)&oReadyToStartMatch);
MH_STATUS StatusSpawnDefaultPawnFor = Memory::CreateHook(Memory::GetAddress(0xcbb040), hkSpawnDefaultPawnFor);
MH_STATUS StatusPickTeam = Memory::CreateHook(Memory::GetAddress(0xcb0890), hkPickTeam);
MH_STATUS StatusReadyToStartMatch = Memory::CreateHook(Memory::GetAddress(0x25bac60), hkReadyToStartMatch, (void**)&oReadyToStartMatch);
MH_STATUS StatusSpawnDefaultPawnFor = Memory::CreateHook(Memory::GetAddress(0xa083a0), hkSpawnDefaultPawnFor);
MH_STATUS StatusPickTeam = Memory::CreateHook(Memory::GetAddress(0x9fe680), hkPickTeam);
#ifdef LOG_HOOKSTATUS
Logging::Log(ELogEvent::Info, ELogType::Hook, "hkReadyToStartMatch Status: %s.", MH_StatusToString(StatusReadyToStartMatch));
+1
View File
@@ -6,6 +6,7 @@ namespace Globals
bool bUseBeacons = true;
bool bUseAccountID = false; // backend communication, etc...
bool bNoMCP = true;
bool bSupportMatchmaking = false;
bool bIsServerListening = false;
bool bIsPlaylistSetup = false;
-266
View File
@@ -1,266 +0,0 @@
#pragma once
#include "framework.h"
namespace InventoryHandler // for now as a symbol with this name already exists shit
{
void Update(AFortPlayerController* PlayerController, FFortItemEntry ItemEntry)
{
PlayerController->WorldInventory->HandleInventoryLocalUpdate();
PlayerController->WorldInventory->Inventory.MarkArrayDirty();
PlayerController->WorldInventory->Inventory.MarkItemDirty(ItemEntry);
}
EFortQuickBars GetQuickBars(UFortItemDefinition* ItemDefinition)
{
if (!ItemDefinition->IsA(UFortWeaponMeleeItemDefinition::StaticClass()) && !ItemDefinition->IsA(UFortEditToolItemDefinition::StaticClass()) &&
!ItemDefinition->IsA(UFortBuildingItemDefinition::StaticClass()) && !ItemDefinition->IsA(UFortAmmoItemDefinition::StaticClass()) &&
!ItemDefinition->IsA(UFortResourceItemDefinition::StaticClass()) && !ItemDefinition->IsA(UFortTrapItemDefinition::StaticClass()))
return EFortQuickBars::Primary;
return EFortQuickBars::Secondary;
}
bool IsFull(AFortPlayerController* PlayerController)
{
int Slots = 0;
auto InstancesPtr = &PlayerController->WorldInventory->Inventory.ReplicatedEntries;
for (int i = 0; i < InstancesPtr->Num(); i++)
{
if (!InstancesPtr->operator[](i).ItemDefinition)
continue;
if (GetQuickBars(InstancesPtr->operator[](i).ItemDefinition) == EFortQuickBars::Primary)
{
Slots++;
if (Slots >= 5)
{
break;
}
}
}
return Slots >= 5;
}
FFortItemEntry* FindItem(AFortPlayerController* PlayerController, UFortItemDefinition* ItemDefinition)
{
TArray<FFortItemEntry> ReplicatedEntries = PlayerController->WorldInventory->Inventory.ReplicatedEntries;
if (!ReplicatedEntries.IsValid())
return nullptr;
for (int i = 0; i < ReplicatedEntries.Num(); i++)
{
if (ReplicatedEntries[i].ItemDefinition == ItemDefinition)
return &ReplicatedEntries[i];
}
return nullptr;
}
FFortItemEntry* FindItem(AFortPlayerController* PlayerController, FGuid ItemGuid)
{
TArray<FFortItemEntry> ReplicatedEntries = PlayerController->WorldInventory->Inventory.ReplicatedEntries;
if (!ReplicatedEntries.IsValid())
return nullptr;
for (int i = 0; i < ReplicatedEntries.Num(); i++)
{
if (ReplicatedEntries[i].ItemGuid == ItemGuid)
return &ReplicatedEntries[i];
}
return nullptr;
}
UFortWorldItem* CreateItem(AFortPlayerController* PlayerController, UFortItemDefinition* ItemDefinition, int Count = 1)
{
auto WorldItem = static_cast<UFortWorldItem*>(ItemDefinition->CreateTemporaryItemInstanceBP(Count, 1));
WorldItem->SetOwningControllerForTemporaryItem(PlayerController);
return WorldItem;
}
bool RemoveItem(AFortPlayerController* PlayerController, FGuid ItemGuid, int Count = -1)
{
if (!PlayerController)
return false;
AFortInventory* WorldInventory = PlayerController->WorldInventory;
if (!WorldInventory)
return false;
bool bWasSuccessful = false;
for (int i = 0; i < WorldInventory->Inventory.ReplicatedEntries.Num(); i++)
{
if (WorldInventory->Inventory.ReplicatedEntries[i].ItemGuid == ItemGuid)
{
if (Count == -1 || Count >= WorldInventory->Inventory.ReplicatedEntries[i].Count)
{
WorldInventory->Inventory.ReplicatedEntries.Remove(i);
break;
}
WorldInventory->Inventory.ReplicatedEntries[i].Count -= Count;
WorldInventory->Inventory.MarkItemDirty(WorldInventory->Inventory.ReplicatedEntries[i]);
bWasSuccessful = true;
}
}
PlayerController->WorldInventory->Inventory.MarkArrayDirty();
PlayerController->WorldInventory->HandleInventoryLocalUpdate();
return bWasSuccessful;
}
bool RemoveItem(AFortPlayerController* PlayerController, UFortItemDefinition* ItemDefinition, int Count = -1)
{
if (!PlayerController || !ItemDefinition)
return false;
AFortInventory* WorldInventory = PlayerController->WorldInventory;
if (!WorldInventory)
return false;
bool bWasSuccessful = false;
for (int i = 0; i < WorldInventory->Inventory.ReplicatedEntries.Num(); i++)
{
if (WorldInventory->Inventory.ReplicatedEntries[i].ItemDefinition == ItemDefinition)
{
if (Count == -1 || Count >= WorldInventory->Inventory.ReplicatedEntries[i].Count)
{
WorldInventory->Inventory.ReplicatedEntries.Remove(i);
break;
}
WorldInventory->Inventory.ReplicatedEntries[i].Count -= Count;
WorldInventory->Inventory.MarkItemDirty(WorldInventory->Inventory.ReplicatedEntries[i]);
bWasSuccessful = true;
}
}
PlayerController->WorldInventory->HandleInventoryLocalUpdate();
PlayerController->WorldInventory->Inventory.MarkArrayDirty();
return bWasSuccessful;
}
FGuid AddItem(AFortPlayerControllerAthena* PlayerController, UFortItemDefinition* ItemDefinition, int Count = 1, int LoadedAmmo = 0, bool bForceNewItem = false)
{
bool bAllowMultipleStacks = ItemDefinition->bAllowMultipleStacks;
auto MaxStackSize = ItemDefinition->MaxStackSize;
auto& ReplicatedEntries = PlayerController->WorldInventory->Inventory.ReplicatedEntries;
UFortWorldItem* StackingItemInstance = nullptr;
int OverStack = 0;
if (MaxStackSize > 1)
{
for (int i = 0; i < ReplicatedEntries.Num(); i++)
{
auto CurrentEntry = ReplicatedEntries[i];
auto& CurrentReplicatedEntry = CurrentEntry.ItemDefinition;
if (CurrentEntry.ItemDefinition == ItemDefinition)
{
if (CurrentEntry.Count < MaxStackSize || !bAllowMultipleStacks)
{
StackingItemInstance = reinterpret_cast<UFortWorldItem*>(CurrentReplicatedEntry);
OverStack = CurrentEntry.Count + Count - MaxStackSize;
if (!bAllowMultipleStacks && !(CurrentEntry.Count < MaxStackSize))
{
break;
}
int AmountToStack = OverStack > 0 ? Count - OverStack : Count;
auto ReplicatedEntry = FindItem(PlayerController, CurrentEntry.ItemGuid);
CurrentEntry.Count += AmountToStack;
ReplicatedEntry->Count += AmountToStack;
if (ItemDefinition->IsA(UFortAmmoItemDefinition::StaticClass()) || ItemDefinition->IsA(UFortResourceItemDefinition::StaticClass()))
{
FFortItemEntryStateValue Value{};
Value.IntValue = 1;
Value.StateType = EFortItemEntryState::ShouldShowItemToast;
ReplicatedEntry->StateValues.Add(Value);
}
PlayerController->WorldInventory->Inventory.MarkItemDirty(CurrentEntry);
PlayerController->WorldInventory->Inventory.MarkItemDirty(*ReplicatedEntry);
if (OverStack <= 0)
return ReplicatedEntry->ItemGuid;
}
}
}
}
Count = OverStack > 0 ? OverStack : Count;
if (OverStack > 0 && !ItemDefinition->bAllowMultipleStacks || OverStack > 0 && IsFull(PlayerController))
{
auto Pawn = static_cast<APlayerPawn_Athena_C*>(PlayerController->AcknowledgedPawn);
if (!Pawn)
return FGuid(-1, -1, -1, -1);
FFortItemEntry itemEntry{};
itemEntry.Count = Count;
itemEntry.ItemDefinition = ItemDefinition;
Utils::SpawnPickup(&itemEntry, Pawn->K2_GetActorLocation(), false, EFortPickupSourceTypeFlag::Player, Pawn);
return FGuid(-1, -1, -1, -1);
}
UFortWorldItem* NewWorldItem = CreateItem(PlayerController, ItemDefinition, Count);
if (!NewWorldItem)
return FGuid(-1, -1, -1, -1);
NewWorldItem->ItemEntry.LoadedAmmo = LoadedAmmo;
if (ItemDefinition->MaxStackSize < Count)
{
PlayerController->ServerAttemptInventoryDrop(NewWorldItem->ItemEntry.ItemGuid, Count - ItemDefinition->MaxStackSize);
NewWorldItem->ItemEntry.Count = ItemDefinition->MaxStackSize;
}
if (ItemDefinition->IsA(UFortAmmoItemDefinition::StaticClass()) || ItemDefinition->IsA(UFortResourceItemDefinition::StaticClass()))
{
FFortItemEntryStateValue Value{};
Value.IntValue = 1;
Value.StateType = EFortItemEntryState::ShouldShowItemToast;
NewWorldItem->ItemEntry.StateValues.Add(Value);
}
PlayerController->WorldInventory->Inventory.ReplicatedEntries.Add(NewWorldItem->ItemEntry);
PlayerController->WorldInventory->HandleInventoryLocalUpdate();
PlayerController->WorldInventory->Inventory.MarkArrayDirty();
PlayerController->WorldInventory->Inventory.MarkItemDirty(NewWorldItem->ItemEntry);
return NewWorldItem->ItemEntry.ItemGuid;
}
void Setup(AFortPlayerControllerAthena* PlayerController)
{
if (Globals::bNoMCP || reinterpret_cast<AFortPlayerStateAthena*>(PlayerController->PlayerState)->bIsABot)
{
static auto PickaxeWID = StaticFindObject<UFortWeaponMeleeItemDefinition>(L"/Game/Athena/Items/Weapons/WID_Harvest_Pickaxe_Athena_C_T01.WID_Harvest_Pickaxe_Athena_C_T01");
AddItem(PlayerController, PickaxeWID, 1);
}
else
AddItem(PlayerController, PlayerController->CustomizationLoadout.Pickaxe->WeaponDefinition, 1);
TArray<FItemAndCount> StartingItems = Globals::GetGameMode()->StartingItems;
for (int i = 0; i < StartingItems.Num(); i++)
{
FItemAndCount StartingItem = StartingItems[i];
AddItem(PlayerController, StartingItem.Item, StartingItem.Count);
}
}
}
-558
View File
@@ -1,558 +0,0 @@
#pragma once
#include "framework.h"
namespace Looting // Most if not all of this is reboot, I'm very clueless on looting :p
{
struct LootDrop
{
FFortItemEntry* ItemEntry;
FFortItemEntry* operator->() {
return ItemEntry;
}
~LootDrop()
{
}
};
int GetClipSize(UFortWeaponItemDefinition* ItemDefinition)
{
if (!ItemDefinition)
return 0;
FDataTableRowHandle& WeaponStatHandle = ItemDefinition->WeaponStatHandle;
UDataTable* Table = WeaponStatHandle.DataTable;
if (!Table)
return 0;
auto& RowMap = Table->RowMap;
void* Row = nullptr;
if (RowMap.Num() <= 0)
return 0;
for (int i = 0; i < RowMap.Num(); ++i)
{
auto& Pair = RowMap[i];
if (Pair.Key() == WeaponStatHandle.RowName)
{
Row = Pair.Second;
break;
}
}
if (!Row)
return 0;
return reinterpret_cast<FFortBaseWeaponStats*>(Row)->ClipSize;
}
float RandomFloatForLoot(float AllWeightsSum)
{
return (rand() * 0.000030518509f) * AllWeightsSum;
}
template <typename KeyType, typename ValueType>
ValueType PickWeightedElement(const std::map<KeyType, ValueType>& Elements,
std::function<float(ValueType)> GetWeightFn,
std::function<float(float)> RandomFloatGenerator = RandomFloatForLoot,
float TotalWeightParam = -1, bool bCheckIfWeightIsZero = false, int RandMultiplier = 1, KeyType* OutName = nullptr, bool bPrint = false, bool bKeepGoingUntilWeGetValue = false)
{
float TotalWeight = TotalWeightParam;
if (TotalWeight == -1)
{
TotalWeight = std::accumulate(Elements.begin(), Elements.end(), 0.0f, [&](float acc, const std::pair<KeyType, ValueType>& p) {
auto Weight = GetWeightFn(p.second);
return acc + Weight;
});
}
float RandomNumber = RandMultiplier * RandomFloatGenerator(TotalWeight);
for (auto& Element : Elements)
{
float Weight = GetWeightFn(Element.second);
if (bCheckIfWeightIsZero && Weight == 0)
continue;
if (RandomNumber <= Weight)
{
if (OutName)
*OutName = Element.first;
return Element.second;
}
RandomNumber -= Weight;
}
if (bKeepGoingUntilWeGetValue)
return PickWeightedElement<KeyType, ValueType>(Elements, GetWeightFn, RandomFloatGenerator, TotalWeightParam, bCheckIfWeightIsZero, RandMultiplier, OutName, bPrint, bKeepGoingUntilWeGetValue);
return ValueType();
}
FName RedirectLootTierGroup(FName LootTierGroup)
{
static FName Loot_TreasureFName = UKismetStringLibrary::Conv_StringToName(L"Loot_Treasure");
static FName Loot_AmmoFName = UKismetStringLibrary::Conv_StringToName(L"Loot_Ammo");
if (LootTierGroup == Loot_TreasureFName)
return UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaTreasure");
if (LootTierGroup == Loot_AmmoFName)
return UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaAmmoLarge");
}
template <typename RowStructType = uint8>
void CollectDataTablesRows(const std::vector<UDataTable*>& DataTables, map<FName, RowStructType*>* OutMap, std::function<bool(FName, RowStructType*)> Check = []() { return true; })
{
std::vector<UDataTable*> DataTablesToIterate;
for (UDataTable* DataTable : DataTables)
{
if (!Utils::IsValidLowLevel(DataTable))
{
continue;
}
DataTablesToIterate.push_back(DataTable);
}
for (auto CurrentDataTable : DataTablesToIterate)
{
for (TPair<FName, uint8_t*>& CurrentPair : CurrentDataTable->RowMap)
{
if (Check(CurrentPair.Key(), (RowStructType*)CurrentPair.Value()))
{
(*OutMap)[CurrentPair.Key()] = (RowStructType*)CurrentPair.Value();
}
}
}
}
FFortLootTierData* PickLootTierData(const std::vector<UDataTable*>& LTDTables, FName LootTierGroup, int ForcedLootTier = -1, FName* OutRowName = nullptr)
{
float LootTier = ForcedLootTier;
map<FName, FFortLootTierData*> TierGroupLTDs;
CollectDataTablesRows<FFortLootTierData>(LTDTables, &TierGroupLTDs, [&](FName RowName, FFortLootTierData* TierData) -> bool {
if (LootTierGroup == TierData->TierGroup)
{
if ((LootTier == -1 ? true : LootTier == TierData->LootTier))
{
return true;
}
}
return false;
});
int Multiplier = LootTier == -1 ? 1 : LootTier;
FFortLootTierData* ChosenRowLootTierData = PickWeightedElement<FName, FFortLootTierData*>(TierGroupLTDs,
[](FFortLootTierData* LootTierData) -> float { return LootTierData->Weight; }, RandomFloatForLoot, -1,
true, Multiplier, OutRowName);
return ChosenRowLootTierData;
}
int PickLevel(UFortWorldItemDefinition* ItemDefinition, int PreferredLevel)
{
const int MinLevel = ItemDefinition->MinLevel;
const int MaxLevel = ItemDefinition->MaxLevel;
int PickedLevel = 0;
if (PreferredLevel >= MinLevel)
PickedLevel = PreferredLevel;
if (MaxLevel >= 0)
{
if (PickedLevel <= MaxLevel)
return PickedLevel;
return MaxLevel;
}
return PickedLevel;
}
void PickLootDropsFromLootPackage(const std::vector<UDataTable*>& LPTables, const FName& LootPackageName, std::vector<LootDrop>* OutEntries, int LootPackageCategory = -1, int WorldLevel = 0, bool bPrint = false, bool bCombineDrops = true)
{
if (!OutEntries)
return;
map<FName, FFortLootPackageData*> LootPackageIDMap;
CollectDataTablesRows<FFortLootPackageData>(LPTables, &LootPackageIDMap, [&](FName RowName, FFortLootPackageData* LootPackage) -> bool {
if (LootPackage->LootPackageID != LootPackageName)
{
return false;
}
if (LootPackageCategory != -1 && LootPackage->LootPackageCategory != LootPackageCategory) // idk if proper
{
return false;
}
if (WorldLevel >= 0)
{
if (LootPackage->MaxWorldLevel >= 0 && WorldLevel > LootPackage->MaxWorldLevel)
return 0;
if (LootPackage->MinWorldLevel >= 0 && WorldLevel < LootPackage->MinWorldLevel)
return 0;
}
return true;
});
if (LootPackageIDMap.size() == 0)
{
return;
}
FName PickedPackageRowName;
FFortLootPackageData* PickedPackage = PickWeightedElement<FName, FFortLootPackageData*>(LootPackageIDMap,
[](FFortLootPackageData* LootPackageData) -> float { return LootPackageData->Weight; }, RandomFloatForLoot,
-1, true, 1, &PickedPackageRowName, bPrint);
if (!PickedPackage)
return;
if (PickedPackage->LootPackageCall.Num() > 1)
{
if (PickedPackage->Count > 0)
{
int v9 = 0;
while (v9 < PickedPackage->Count)
{
int LootPackageCategoryToUseForLPCall = 0; // hmm
PickLootDropsFromLootPackage(LPTables,
PickedPackage->LootPackageCall.IsValid() ? UKismetStringLibrary::Conv_StringToName(PickedPackage->LootPackageCall) : FName(0),
OutEntries, LootPackageCategoryToUseForLPCall, WorldLevel, bPrint
);
v9++;
}
}
return;
}
auto ItemDefinition = PickedPackage->ItemDefinition.Get();
if (!ItemDefinition)
return;
auto WeaponItemDefinition = static_cast<UFortWeaponItemDefinition*>(ItemDefinition);
int LoadedAmmo = WeaponItemDefinition ? GetClipSize(WeaponItemDefinition) : 0;
auto WorldItemDefinition = static_cast<UFortWorldItemDefinition*>(ItemDefinition);
if (!WorldItemDefinition)
return;
int CountMultiplier = 1;
int FinalCount = CountMultiplier * PickedPackage->Count;
if (FinalCount > 0)
{
int FinalItemLevel = 0;
while (FinalCount > 0)
{
int MaxStackSize = ItemDefinition->MaxStackSize;
int CurrentCountForEntry = MaxStackSize;
if (FinalCount <= MaxStackSize)
CurrentCountForEntry = FinalCount;
if (CurrentCountForEntry <= 0)
CurrentCountForEntry = 0;
auto ActualItemLevel = PickLevel(WorldItemDefinition, FinalItemLevel);
bool bHasCombined = false;
if (bCombineDrops)
{
for (auto& CurrentLootDrop : *OutEntries)
{
if (CurrentLootDrop->ItemDefinition == ItemDefinition)
{
int NewCount = CurrentLootDrop->Count + CurrentCountForEntry;
if (NewCount <= ItemDefinition->MaxStackSize)
{
bHasCombined = true;
CurrentLootDrop->Count = NewCount;
}
}
}
}
if (!bHasCombined)
{
FFortItemEntry* NewItemEntry = new FFortItemEntry();
NewItemEntry->ItemDefinition = ItemDefinition;
NewItemEntry->Count = CurrentCountForEntry;
NewItemEntry->LoadedAmmo = LoadedAmmo;
NewItemEntry->Durability = 0x3F800000;
NewItemEntry->Level = ActualItemLevel;
OutEntries->push_back(LootDrop(NewItemEntry));
}
FinalCount -= CurrentCountForEntry;
}
}
}
float GetAmountOfLootPackagesToDrop(FFortLootTierData* LootTierData, int OriginalNumberLootDrops)
{
if (LootTierData->LootPackageCategoryMinArray.Num() != LootTierData->LootPackageCategoryWeightArray.Num()
|| LootTierData->LootPackageCategoryMinArray.Num() != LootTierData->LootPackageCategoryMaxArray.Num())
return 0;
float MinimumLootDrops = 0;
if (LootTierData->LootPackageCategoryMinArray.Num() > 0)
{
for (int i = 0; i < LootTierData->LootPackageCategoryMinArray.Num(); ++i)
{
MinimumLootDrops += LootTierData->LootPackageCategoryMinArray[i];
}
}
int SumLootPackageCategoryWeightArray = 0;
if (LootTierData->LootPackageCategoryWeightArray.Num() > 0)
{
for (int i = 0; i < LootTierData->LootPackageCategoryWeightArray.Num(); ++i)
{
if (LootTierData->LootPackageCategoryWeightArray[i] > 0)
{
auto LootPackageCategoryMaxArrayIt = LootTierData->LootPackageCategoryWeightArray[i];
if (LootPackageCategoryMaxArrayIt < 0 || 0 < LootPackageCategoryMaxArrayIt)
{
SumLootPackageCategoryWeightArray += LootTierData->LootPackageCategoryWeightArray[i];
}
}
}
}
while (SumLootPackageCategoryWeightArray > 0)
{
float v29 = (float)rand() * 0.000030518509f;
float v35 = (int)(float)((float)((float)((float)SumLootPackageCategoryWeightArray * v29)
+ (float)((float)SumLootPackageCategoryWeightArray * v29))
+ 0.5f) >> 1;
MinimumLootDrops++;
if (MinimumLootDrops >= OriginalNumberLootDrops)
return MinimumLootDrops;
SumLootPackageCategoryWeightArray--;
}
return MinimumLootDrops;
}
std::vector<LootDrop> PickLootDrops(FName TierGroupName, int WorldLevel, int ForcedLootTier = -1, bool bPrint = false, int recursive = 0, bool bCombineDrops = true)
{
std::vector<LootDrop> LootDrops;
if (recursive > 6)
return LootDrops;
AFortGameStateAthena* GameState = Globals::GetGameState();
static std::vector<UDataTable*> LTDTables;
static std::vector<UDataTable*> LPTables;
static int LastNum1 = 14915;
static UFortPlaylistAthena* CurrentPlaylist = Globals::GetGameState()->CurrentPlaylistInfo.OverridePlaylist;
LTDTables.clear();
LPTables.clear();
bool bFoundPlaylistTable = false;
if (CurrentPlaylist)
{
auto& LootTierDataSoft = CurrentPlaylist->LootTierData;
auto& LootPackagesSoft = CurrentPlaylist->LootPackages;
if (LootTierDataSoft.ObjectID.AssetPathName.ComparisonIndex && LootPackagesSoft.ObjectID.AssetPathName.ComparisonIndex)
{
auto LootTierDataStr = LootTierDataSoft.ObjectID.AssetPathName.ToString();
auto LootPackagesStr = LootPackagesSoft.ObjectID.AssetPathName.ToString();
auto LootTierDataTableIsComposite = LootTierDataStr.contains("Composite");
auto LootPackageTableIsComposite = LootPackagesStr.contains("Composite");
UDataTable* StrongLootTierData = nullptr;
UDataTable* StrongLootPackage = nullptr;
StrongLootTierData = LootTierDataSoft.Get();
StrongLootPackage = LootPackagesSoft.Get();
if (StrongLootTierData && StrongLootPackage)
{
LTDTables.push_back(StrongLootTierData);
LPTables.push_back(StrongLootPackage);
bFoundPlaylistTable = true;
}
}
}
if (!bFoundPlaylistTable)
{
LTDTables.push_back(StaticFindObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootTierData_Client.AthenaLootTierData_Client"));
LPTables.push_back(StaticFindObject<UDataTable>(L"/Game/Items/Datatables/AthenaLootPackages_Client.AthenaLootPackages_Client"));
}
for (int i = 0; i < LTDTables.size(); ++i)
{
auto& Table = LTDTables.at(i);
if (!Utils::IsValidLowLevel(Table))
{
continue;
}
}
for (int i = 0; i < LPTables.size(); ++i)
{
auto& Table = LPTables.at(i);
if (!Utils::IsValidLowLevel(Table))
{
continue;
}
}
if (LTDTables.size() <= 0 || LPTables.size() <= 0)
return LootDrops;
FName LootTierRowName;
auto ChosenRowLootTierData = PickLootTierData(LTDTables, TierGroupName, ForcedLootTier, &LootTierRowName);
if (!ChosenRowLootTierData)
return LootDrops;
float NumLootPackageDrops = ChosenRowLootTierData->NumLootPackageDrops;
float NumberLootDrops = 0;
if (NumLootPackageDrops > 0)
{
if (NumLootPackageDrops < 1)
{
NumberLootDrops = 1;
}
else
{
NumberLootDrops = (int)(float)((float)(NumLootPackageDrops + NumLootPackageDrops) - 0.5f) >> 1;
float v20 = NumLootPackageDrops - NumberLootDrops;
if (v20 > 0.0000099999997f)
{
NumberLootDrops += v20 >= (rand() * 0.000030518509f);
}
}
}
float AmountOfLootPackageDrops = GetAmountOfLootPackagesToDrop(ChosenRowLootTierData, NumberLootDrops);
LootDrops.reserve(AmountOfLootPackageDrops);
if (AmountOfLootPackageDrops > 0)
{
for (int i = 0; i < AmountOfLootPackageDrops; ++i)
{
if (i >= ChosenRowLootTierData->LootPackageCategoryMinArray.Num())
break;
for (int j = 0; j < ChosenRowLootTierData->LootPackageCategoryMinArray[i]; ++j)
{
if (ChosenRowLootTierData->LootPackageCategoryMinArray[i] < 1)
break;
int LootPackageCategory = i;
PickLootDropsFromLootPackage(LPTables, ChosenRowLootTierData->LootPackage, &LootDrops, LootPackageCategory, WorldLevel, bPrint);
}
}
}
return LootDrops;
}
void SpawnFloorLoot()
{
auto SpawnIsland_FloorLoot = StaticFindObject<UClass>(L"/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_Warmup.Tiered_Athena_FloorLoot_Warmup_C");
auto BRIsland_FloorLoot = StaticFindObject<UClass>(L"/Game/Athena/Environments/Blueprints/Tiered_Athena_FloorLoot_01.Tiered_Athena_FloorLoot_01_C");
TArray<AActor*> SpawnIsland_FloorLoot_Actors;
UGameplayStatics::GetAllActorsOfClass(Globals::GetWorld(), SpawnIsland_FloorLoot, &SpawnIsland_FloorLoot_Actors);
TArray<AActor*> BRIsland_FloorLoot_Actors;
UGameplayStatics::GetAllActorsOfClass(Globals::GetWorld(), BRIsland_FloorLoot, &BRIsland_FloorLoot_Actors);
auto SpawnIslandTierGroup = UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaFloorLoot_Warmup");
auto BRIslandTierGroup = UKismetStringLibrary::Conv_StringToName(L"Loot_AthenaFloorLoot");
for (int i = 0; i < SpawnIsland_FloorLoot_Actors.Num(); i++)
{
ABuildingContainer* CurrentActor = (ABuildingContainer*)SpawnIsland_FloorLoot_Actors[i];
auto Location = CurrentActor->K2_GetActorLocation() + CurrentActor->GetActorForwardVector() * CurrentActor->LootSpawnLocation_Athena.X + CurrentActor->GetActorRightVector() * CurrentActor->LootSpawnLocation_Athena.Y + CurrentActor->GetActorUpVector() * CurrentActor->LootSpawnLocation_Athena.Z;
std::vector<LootDrop> LootDrops = PickLootDrops(SpawnIslandTierGroup, Globals::GetGameState()->WorldLevel);
for (auto& LootDrop : LootDrops)
{
Utils::SpawnPickup(LootDrop.ItemEntry, Location, false, EFortPickupSourceTypeFlag::FloorLoot);
}
CurrentActor->K2_DestroyActor();
}
int spawned = 0;
for (int i = 0; i < BRIsland_FloorLoot_Actors.Num(); i++)
{
ABuildingContainer* CurrentActor = (ABuildingContainer*)BRIsland_FloorLoot_Actors[i];
spawned++;
auto Location = CurrentActor->K2_GetActorLocation() + CurrentActor->GetActorForwardVector() * CurrentActor->LootSpawnLocation_Athena.X + CurrentActor->GetActorRightVector() * CurrentActor->LootSpawnLocation_Athena.Y + CurrentActor->GetActorUpVector() * CurrentActor->LootSpawnLocation_Athena.Z;
std::vector<LootDrop> LootDrops = PickLootDrops(BRIslandTierGroup, Globals::GetGameState()->WorldLevel);
for (auto& LootDrop : LootDrops)
{
Utils::SpawnPickup(LootDrop.ItemEntry, Location, false, EFortPickupSourceTypeFlag::FloorLoot);
}
CurrentActor->K2_DestroyActor();
}
SpawnIsland_FloorLoot_Actors.Free();
BRIsland_FloorLoot_Actors.Free();
}
}
+4 -3
View File
@@ -30,6 +30,7 @@ namespace Pawn
Pickup->OnRep_bPickedUp();
}
void (*oServerChoosePart)(AFortPlayerPawn* Pawn, EFortCustomPartType Part, UCustomCharacterPart* ChosenCharacterPart);
void hkServerChoosePart(AFortPlayerPawn* Pawn, EFortCustomPartType Part, UCustomCharacterPart* ChosenCharacterPart)
{
return;
@@ -65,14 +66,14 @@ namespace Pawn
{
auto DefaultObject = APlayerPawn_Athena_C::GetDefaultObj();
MH_STATUS StatusNetMulticast_Athena_BatchedDamageCues = Memory::CreateHook(Memory::GetAddress(0x1615a80), hkNetMulticast_Athena_BatchedDamageCues, (void**)&oNetMulticast_Athena_BatchedDamageCues);
MH_STATUS StatusNetMulticast_Athena_BatchedDamageCues = Memory::CreateHook(Memory::GetAddress(0x11b2b10), hkNetMulticast_Athena_BatchedDamageCues, (void**)&oNetMulticast_Athena_BatchedDamageCues);
#ifdef LOG_HOOKSTATUS
Logging::Log(ELogEvent::Info, ELogType::Hook, "hkNetMulticast_Athena_BatchedDamageCues Status: %s.", MH_StatusToString(StatusNetMulticast_Athena_BatchedDamageCues));
#endif
Memory::VirtualHook(DefaultObject, 0x1ac, hkServerHandlePickup);
Memory::VirtualHook(DefaultObject, 0x19c, hkServerChoosePart);
Memory::VirtualHook(DefaultObject, 0x18f, hkServerHandlePickup);
Memory::VirtualHook(DefaultObject, 0x17f, hkServerChoosePart, (void**)&oServerChoosePart);
Logging::Log(ELogEvent::Info, ELogType::Hook, "Pawn hooks initialized.");
}
+10 -10
View File
@@ -355,17 +355,17 @@ namespace PlayerController
auto DefaultObject = AAthena_PlayerController_C::GetDefaultObj();
Memory::VirtualHook(DefaultObject, 0x104, hkServerAcknowledgePossession);
Memory::VirtualHook(DefaultObject, 0x252, hkServerReadyToStartMatch, (void**)&oServerReadyToStartMatch);
Memory::VirtualHook(DefaultObject, 0x254, hkServerLoadingScreenDropped, (void**)&oServerLoadingScreenDropped);
Memory::VirtualHook(DefaultObject, 0x1f4, hkServerExecuteInventoryItem);
Memory::VirtualHook(DefaultObject, 0x212, hkServerCreateBuildingActor);
Memory::VirtualHook(DefaultObject, 0x214, hkServerEditBuildingActor, (void**)&oServerEditBuildingActor);
Memory::VirtualHook(DefaultObject, 0x218, hkServerBeginEditingBuildingActor);
Memory::VirtualHook(DefaultObject, 0x216, hkServerEndEditingBuildingActor);
Memory::VirtualHook(DefaultObject, 0x1b8, hkServerPlayEmoteItem);
Memory::VirtualHook(DefaultObject, 0x241, hkServerReadyToStartMatch, (void**)&oServerReadyToStartMatch);
Memory::VirtualHook(DefaultObject, 0x243, hkServerLoadingScreenDropped, (void**)&oServerLoadingScreenDropped);
Memory::VirtualHook(DefaultObject, 0x1e5, hkServerExecuteInventoryItem);
Memory::VirtualHook(DefaultObject, 0x201, hkServerCreateBuildingActor);
Memory::VirtualHook(DefaultObject, 0x203, hkServerEditBuildingActor, (void**)&oServerEditBuildingActor);
Memory::VirtualHook(DefaultObject, 0x207, hkServerBeginEditingBuildingActor);
Memory::VirtualHook(DefaultObject, 0x205, hkServerEndEditingBuildingActor);
Memory::VirtualHook(DefaultObject, 0x1b3, hkServerPlayEmoteItem);
MH_STATUS StatusEnterAircraft = Memory::CreateHook(Memory::GetAddress(0xcd81a0), hkEnterAircraft, (void**)&oEnterAircraft);
MH_STATUS StatusClientOnPawnDied = Memory::CreateHook(Memory::GetAddress(0x1642b40), hkClientOnPawnDied, (void**)&oClientOnPawnDied);
MH_STATUS StatusEnterAircraft = Memory::CreateHook(Memory::GetAddress(0xa26d10), hkEnterAircraft, (void**)&oEnterAircraft);
MH_STATUS StatusClientOnPawnDied = Memory::CreateHook(Memory::GetAddress(0x11ac700), hkClientOnPawnDied, (void**)&oClientOnPawnDied);
#ifdef LOG_HOOKSTATUS
Logging::Log(ELogEvent::Info, ELogType::Hook, "hkEnterAircraft Status: %s.", MH_StatusToString(StatusEnterAircraft));
-1
View File
@@ -5,7 +5,6 @@ namespace QuestsHandler
{
void Initialize()
{
Logging::Log(ELogEvent::Info, ELogType::Hook, "Quests hooks initialized.");
}
}
File diff suppressed because it is too large Load Diff
-139
View File
@@ -1,139 +0,0 @@
#pragma once
#include "framework.h"
namespace Server
{
static UNetDriver* (*CreateNetDriver)(UEngine* a1, UWorld* a2, FName a3) = decltype(CreateNetDriver)(Memory::GetAddress(0x2A56600));
static bool (*InitListen)(UNetDriver* a1, void* InNotify, FURL& LocalURL, bool bReuseAddressAndPort, FString& Error) = decltype(InitListen)(Memory::GetAddress(0x44b700));
static void (*SetWorld)(UNetDriver* a1, UWorld* a2) = decltype(SetWorld)(Memory::GetAddress(0x27e2040));
static bool (*InitHost)(UObject* Beacon) = decltype(InitHost)(Memory::GetAddress(0x44b320));
static void (*PauseBeaconRequests)(UObject* Beacon, bool bPause) = decltype(PauseBeaconRequests)(Memory::GetAddress(0x1149920));
static void (*ReplicateActors)(UReplicationDriver* a1);
void Listen()
{
if (Globals::bIsServerListening)
return;
Globals::bIsServerListening = true;
UWorld* World = UWorld::GetWorld();
UNetDriver* NetDriver = nullptr;
if (Globals::bUseBeacons)
{
auto Beacon = Spawner::SpawnActor<AFortOnlineBeaconHost>(AFortOnlineBeaconHost::StaticClass(), FTransform());
if (!Beacon)
{
Logging::Log(ELogEvent::Error, ELogType::Athena, "Beacon failed to spawn.");
return;
}
Beacon->ListenPort = Globals::Port - 1;
InitHost(Beacon);
PauseBeaconRequests(Beacon, false);
NetDriver = Beacon->NetDriver;
}
else
NetDriver = CreateNetDriver(UEngine::GetEngine(), World, FName(282));
if (!NetDriver)
{
Logging::Log(ELogEvent::Error, ELogType::Athena, "NetDriver failed to create.");
return;
}
Logging::Log(ELogEvent::Info, ELogType::Athena, "NetDriver successfully created. (%s)", NetDriver->GetFullName().c_str());
World->NetDriver = NetDriver;
NetDriver->World = World;
NetDriver->NetDriverName = FName(282);
FString Error;
FURL URL = FURL();
URL.Port = Globals::Port;
InitListen(NetDriver, World, URL, false, Error);
SetWorld(NetDriver, World);
World->LevelCollections[0].NetDriver = NetDriver;
World->LevelCollections[1].NetDriver = NetDriver;
auto vft = *(void***)NetDriver->ReplicationDriver;
ReplicateActors = decltype(ReplicateActors)(vft[0x56]);
if (NetDriver->MaxInternetClientRate < NetDriver->MaxClientRate && NetDriver->MaxInternetClientRate > 2500)
NetDriver->MaxClientRate = NetDriver->MaxInternetClientRate;
Logging::Log(ELogEvent::Info, ELogType::Athena, "Server::Listen: Server Listening on port %i", Globals::Port);
}
APlayerPawn_Athena_C* Bot = nullptr;
void (*oTickFlush)(UNetDriver* a1);
void hkTickFlush(UNetDriver* a1)
{
if (a1 && a1->ReplicationDriver && a1->ClientConnections.Num() > 0 && !a1->ClientConnections[0]->InternalAck)
Server::ReplicateActors(a1->ReplicationDriver);
if (GetAsyncKeyState(VK_F6) & 0x01)
{
auto Pawn = Utils::GetActorOfClass<APlayerPawn_Athena_C>(APlayerPawn_Athena_C::StaticClass());
if (Pawn)
{
Bot = AI::SpawnBot(Pawn->K2_GetActorLocation() + FVector(10, 0, 10));
}
}
return oTickFlush(a1);
}
__int64 hkGetNetMode(UWorld*)
{
return 1;
}
char hkKickPlayer(__int64 a1, __int64 a2, __int64 a3)
{
return 1;
}
__int64 hkCollectGarbage(__int64)
{
return 0;
}
__int64 hkNoMCP()
{
return Globals::bNoMCP;
}
void (*oDispatchRequest)(__int64 a1, __int64* a2, int a3);
void hkDispatchRequest(__int64 a1, __int64* a2, int a3)
{
if (Globals::bNoMCP)
return oDispatchRequest(a1, a2, a3);
*(int*)(__int64(a2) + 0x28) = 3;
return oDispatchRequest(a1, a2, 3);
}
float hkGetMaxTickRate()
{
return 30.f;
}
void Initialize()
{
Memory::CreateHook(Memory::GetAddress(0x27e36a0), hkTickFlush, (void**)&oTickFlush);
Memory::CreateHook(Memory::GetAddress(0x26a2e00), hkKickPlayer);
Memory::CreateHook(Memory::GetAddress(0x5f4cc22), hkCollectGarbage);
Memory::CreateHook(Memory::GetAddress(0x35b57b76), hkGetNetMode);
// Memory::CreateHook(Memory::GetAddress(0x2470ca0), hkActorGetNetMode);
Memory::CreateHook(Memory::GetAddress(0x96e200), hkDispatchRequest, (void**)&oDispatchRequest);
Memory::CreateHook(Memory::GetAddress(0x2a62bb0), hkGetMaxTickRate);
Memory::CreateHook(Memory::GetAddress(0xfb7e40), hkNoMCP);
}
}
-130
View File
@@ -1,130 +0,0 @@
#pragma once
#include "framework.h"
namespace Spawner
{
void sinCos(float* ScalarSin, float* ScalarCos, float Value)
{
float quotient = (0.31830988618f * 0.5f) * Value;
if (Value >= 0.0f)
{
quotient = (float)((int)(quotient + 0.5f));
}
else
{
quotient = (float)((int)(quotient - 0.5f));
}
float y = Value - (2.0f * 3.1415926535897932f) * quotient;
float sign;
if (y > 1.57079632679f)
{
y = 3.1415926535897932f - y;
sign = -1.0f;
}
else if (y < -1.57079632679f)
{
y = -3.1415926535897932f - y;
sign = -1.0f;
}
else
{
sign = +1.0f;
}
float y2 = y * y;
*ScalarSin = (((((-2.3889859e-08f * y2 + 2.7525562e-06f) * y2 - 0.00019840874f) * y2 + 0.0083333310f) * y2 - 0.16666667f) * y2 + 1.0f) * y;
float p = ((((-2.6051615e-07f * y2 + 2.4760495e-05f) * y2 - 0.0013888378f) * y2 + 0.041666638f) * y2 - 0.5f) * y2 + 1.0f;
*ScalarCos = sign * p;
}
FQuat FRotToQuat(FRotator Rot)
{
const float DEG_TO_RAD = 3.1415926535897932f / (180.f);
const float DIVIDE_BY_2 = DEG_TO_RAD / 2.f;
float SP, SY, SR;
float CP, CY, CR;
sinCos(&SP, &CP, Rot.Pitch * DIVIDE_BY_2);
sinCos(&SY, &CY, Rot.Yaw * DIVIDE_BY_2);
sinCos(&SR, &CR, Rot.Roll * DIVIDE_BY_2);
FQuat RotationQuat;
RotationQuat.X = CR * SP * SY - SR * CP * CY;
RotationQuat.Y = -CR * SP * CY - SR * CP * SY;
RotationQuat.Z = CR * CP * SY - SR * SP * CY;
RotationQuat.W = CR * CP * CY + SR * SP * SY;
return RotationQuat;
}
struct FActorSpawnParameters
{
FName Name = FName(0);
AActor* Template = nullptr;
AActor* Owner = nullptr;
APawn* Instigator = nullptr;
ULevel* OverrideLevel = nullptr;
ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined;
uint16 bRemoteOwned : 1;
uint16 bNoFail : 1;
uint16 bDeferConstruction : 1;
uint16 bAllowDuringConstructionScript : 1;
EObjectFlags ObjectFlags;
};
FActorSpawnParameters CreateSpawnParams(ESpawnActorCollisionHandlingMethod SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::Undefined, bool bDeferConstruction = false, AActor* Owner = nullptr)
{
FActorSpawnParameters Params{};
Params.Owner = Owner;
Params.SpawnCollisionHandlingOverride = SpawnCollisionHandlingOverride;
Params.bDeferConstruction = bDeferConstruction;
return Params;
}
template<typename T = AActor>
T* SpawnActor(UClass* ActorClass, FTransform SpawnTransform = FTransform(), FActorSpawnParameters SpawnParameters = CreateSpawnParams())
{
static auto oSpawnActor = (AActor* (*)(UWorld * World, UClass * Class, FTransform const* UserTransformPtr, const FActorSpawnParameters& SpawnParameters))(Memory::GetAddress(0x276a290));
if (!oSpawnActor)
return nullptr;
auto Actor = (T*)oSpawnActor(UWorld::GetWorld(), ActorClass, &SpawnTransform, SpawnParameters);
return Actor;
}
template<typename T = AActor>
T* SpawnActor(UClass* ActorClass, FVector Location = {}, FRotator Rotation = {}, FActorSpawnParameters SpawnParameters = CreateSpawnParams())
{
FTransform SpawnTransform{};
SpawnTransform.Translation = Location;
SpawnTransform.Scale3D = { 1,1,1 };
SpawnTransform.Rotation = FRotToQuat(Rotation);
auto Actor = SpawnActor<T>(ActorClass, SpawnTransform, SpawnParameters);
VirtualFree(&SpawnParameters, 0, MEM_RELEASE);
return Actor;
}
/* template<typename T = AActor>
T* SpawnActor(UClass* ActorClass, FVector Location = {}, FRotator Rotation = {}, AActor* Owner = nullptr)
{
FTransform Transform;
Transform.Translation = Location;
Transform.Scale3D = { 1,1,1 };
Transform.Rotation = FRotToQuat(Rotation);
AActor* Actor = UGameplayStatics::BeginDeferredActorSpawnFromClass(UWorld::GetWorld(), ActorClass, Transform, ESpawnActorCollisionHandlingMethod::AdjustIfPossibleButAlwaysSpawn, Owner);
UGameplayStatics::FinishSpawningActor(Actor, Transform);
return static_cast<T*>(Actor);
}
template<typename T = AActor>
T* SpawnActor(FVector Location = {}, FRotator Rotation = {}, AActor* Owner = nullptr)
{
return SpawnActor<T>(T::StaticClass());
}*/
}
+15 -55
View File
@@ -1,54 +1,17 @@
#include "framework.h"
#ifdef PROCESSEVENT
void (*oProcessEvent)(UObject*, UFunction*, void*);
void hkProcessEvent(UObject* InObject, UFunction* InFunction, void* InParameters)
{
if (!InObject || !InFunction)
return oProcessEvent(InObject, InFunction, InParameters);
string ObjectName = InObject->GetFullName();
string FunctionName = InFunction->GetFullName();
if (InFunction->GetName() == "ReceiveTick" && ObjectName.contains("Athena_PlayerController"))
{
auto PlayerController = reinterpret_cast<AAthena_PlayerController_C*>(InObject);
auto PlayerState = reinterpret_cast<AFortPlayerStateAthena*>(PlayerController->PlayerState);
if (!PlayerState->bIsABot)
return oProcessEvent(InObject, InFunction, InParameters);
auto Pawn = reinterpret_cast<APlayerPawn_Athena_C*>(PlayerController->Pawn);
if (PlayerController->bHasServerFinishedLoading)
{
if (Globals::GetGameState()->GamePhase == EAthenaGamePhase::Setup || Globals::GetGameState()->GamePhase == EAthenaGamePhase::Warmup)
{
if (!PlayerController->IsPlayingEmote())
{
auto bot = AI::GetBotByDisplayName(PlayerState->GetPlayerName());
PlayerController->ServerPlayEmoteItem(bot.Loadout.AssignedEmote);
}
}
else
{
}
}
}
return oProcessEvent(InObject, InFunction, InParameters);
}
#endif // PROCESSEVENT
#include "Actor.h"
#include "GameMode.h"
#include "PlayerController.h"
#include "Pawn.h"
#include "Quests.h"
DWORD Initialize(LPVOID)
{
AllocConsole();
FILE* File;
freopen_s(&File, "CONOUT$", "w+", stdout);
SetConsoleTitleA("Athena - 6.31");
SetConsoleTitleA("Athena - 3.6");
if (filesystem::exists("Athena.log"))
filesystem::remove("Athena.log");
@@ -67,16 +30,20 @@ DWORD Initialize(LPVOID)
Logging::Log(ELogEvent::Info, ELogType::Athena, "Globals::bUseBeacons: %s", Globals::bUseBeacons ? "true" : "false");
Logging::Log(ELogEvent::Info, ELogType::Athena, "Globals::bUseAccountID: %s", Globals::bUseAccountID ? "true" : "false");
Logging::Log(ELogEvent::Info, ELogType::Athena, "Globals::bNoMCP: %s", Globals::bNoMCP ? "true" : "false");
Logging::Log(ELogEvent::Info, ELogType::Athena, "Globals::bSupportMatchmaking: %s", Globals::bSupportMatchmaking ? "true" : "false");
Logging::Log(ELogEvent::Info, ELogType::Athena, "Globals::Port: %i", Globals::Port);
*(uint8_t*)(Memory::GetAddress(0x2AC2E4E) + 7) = 0x74;
Logging::Log(ELogEvent::Info, ELogType::Athena, "Matchmaking should now be supported????");
if (Globals::bSupportMatchmaking)
{
*(uint8_t*)(Memory::GetAddress(0x255BB17) + 7) = 0x74;
Logging::Log(ELogEvent::Info, ELogType::Athena, "Matchmaking issupported.");
}
UKismetSystemLibrary::ExecuteConsoleCommand(Globals::GetWorld(), L"open Athena_Terrain", nullptr);
Globals::GetWorld()->OwningGameInstance->LocalPlayers.Remove(0);
for (uintptr_t FuncToNull : vector{ 0xd16310, 0x233bd47, 0xf89d40, 0x12f4fe0 })
for (uintptr_t FuncToNull : vector{ 0xa767b0, 0xc22e90, 0xf1c000 })
{
uintptr_t func = Memory::GetAddress(FuncToNull);
@@ -90,7 +57,7 @@ DWORD Initialize(LPVOID)
Logging::Log(ELogEvent::Info, ELogType::Athena, "Nulled at 0x%.8x", FuncToNull);
}
auto ByteToPatch = (uint8_t*)(uint8_t*)(Memory::GetAddress(0xc98a16));
auto ByteToPatch = (uint8_t*)(uint8_t*)(Memory::GetAddress(0x9eb786));
DWORD dwProtection;
VirtualProtect((PVOID)ByteToPatch, 1, PAGE_EXECUTE_READWRITE, &dwProtection);
*ByteToPatch = 0x85;
@@ -98,15 +65,8 @@ DWORD Initialize(LPVOID)
VirtualProtect((PVOID)ByteToPatch, 1, dwProtection, &dwTemp);
Logging::Log(ELogEvent::Info, ELogType::Athena, "Patched Byte at 0x%.8x", ByteToPatch);
*(bool*)Memory::GetAddress(0x5634b5b) = false;
*(bool*)Memory::GetAddress(0x4a9ca14) = false;
Logging::Log(ELogEvent::Info, ELogType::Athena, "GIsClient should now be false.");
*(bool*)Memory::GetAddress(0x5634b5c) = true;
Logging::Log(ELogEvent::Info, ELogType::Athena, "GIsServer should now be true.");
#ifdef PROCESSEVENT
Memory::CreateHook(Memory::GetAddress(Offsets::ProcessEvent), hkProcessEvent, (void**)&oProcessEvent);
Logging::Log(ELogEvent::Info, ELogType::Hook, "ProcessEvent is enabled.");
#endif // PROCESSEVENT
AbilitiesHandler::Initialize();
GameMode::Initialize();
+2 -19
View File
@@ -18,43 +18,26 @@ using namespace SDK;
#define PROCESSEVENT
#define LOG_HOOKSTATUS
#include "Memory.h"
#include "Logging.h"
#include "Frame.h"
template <typename T>
T* StaticFindObject(wstring ObjectName, UClass* ObjectClass = nullptr)
{
static UObject* (*oStaticFindObject)(UClass * Class, void* InOuter, const wchar_t* Name, bool ExactClass) = decltype(oStaticFindObject)(Memory::GetAddress(0x19d5680));
static UObject* (*oStaticFindObject)(UClass * Class, void* InOuter, const wchar_t* Name, bool ExactClass) = decltype(oStaticFindObject)(Memory::GetAddress(0x14e5890));
return (T*)oStaticFindObject(ObjectClass, nullptr, ObjectName.c_str(), false);
}
template <typename T>
static T* StaticLoadObject(wstring ObjectName, UClass* ObjectClass = nullptr)
{
static UObject* (*oStaticLoadObject)(UObject*, UObject*, const TCHAR*, const TCHAR*, uint32_t, void*, bool) = decltype(oStaticLoadObject)(Memory::GetAddress(0x19d70f0));
static UObject* (*oStaticLoadObject)(UObject*, UObject*, const TCHAR*, const TCHAR*, uint32_t, void*, bool) = decltype(oStaticLoadObject)(Memory::GetAddress(0x14e7390));
return reinterpret_cast<T*>(oStaticLoadObject(ObjectClass, 0, ObjectName.c_str(), nullptr, 0, nullptr, false));
}
#include "Globals.h"
#include "Spawner.h"
#include "Utils.h"
#include "Inventory.h"
#include "Abilities.h"
#include "AI.h"
#include "Server.h"
#include "Looting.h"
#include "Actor.h"
#include "GameMode.h"
#include "PlayerController.h"
#include "Pawn.h"
#include "Quests.h"