mirror of
https://github.com/nax1800/Athena.git
synced 2026-08-26 19:43:33 +00:00
All I cba doing, does not work atm.
This commit is contained in:
@@ -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
@@ -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.");
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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));
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user