mirror of
https://github.com/nax1800/Athena.git
synced 2026-08-26 19:43:33 +00:00
188 lines
7.8 KiB
C++
188 lines
7.8 KiB
C++
#pragma once
|
|
#include "framework.h"
|
|
|
|
namespace ActorHandler
|
|
{
|
|
void (*oOnDamageServer)(ABuildingActor* Actor, float Damage, FGameplayTagContainer DamageTags, FVector Momentum, FHitResult HitInfo, AActor* InstigatedBy, AActor* DamageCauser, FGameplayEffectContextHandle EffectContext);
|
|
void hkOnDamageServer(ABuildingActor* Actor, float Damage, FGameplayTagContainer DamageTags, FVector Momentum, FHitResult HitInfo, AActor* InstigatedBy, AActor* DamageCauser, FGameplayEffectContextHandle EffectContext)
|
|
{
|
|
if (!Actor || !InstigatedBy || !DamageCauser)
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
|
|
if (!DamageCauser->IsA(AFortWeapon::StaticClass()))
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
|
|
auto BuildingActor = static_cast<ABuildingSMActor*>(Actor);
|
|
auto Weapon = static_cast<AFortWeapon*>(DamageCauser);
|
|
auto PlayerController = static_cast<AFortPlayerControllerAthena*>(InstigatedBy);
|
|
|
|
if (!Weapon->WeaponData->IsA(UFortWeaponMeleeItemDefinition::StaticClass()))
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
|
|
auto PlayerPawn = static_cast<AFortPlayerPawn*>(PlayerController->Pawn);
|
|
if (!PlayerPawn)
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
|
|
if (BuildingActor->bDestroyed || BuildingActor->bPlayerPlaced)
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
|
|
bool bWeakSpotHit = (Damage == 100.f);
|
|
auto ResourceDefinition = UFortKismetLibrary::K2_GetResourceItemDefinition(BuildingActor->ResourceType);
|
|
if (!ResourceDefinition)
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
|
|
FCurveTableRowHandle BuildingResourceAmountOverride = BuildingActor->BuildingResourceAmountOverride;
|
|
|
|
int ResourceAmount = 0;
|
|
|
|
if (BuildingResourceAmountOverride.RowName.ComparisonIndex)
|
|
{
|
|
static UFortPlaylistAthena* Playlist = Globals::GetGameState()->CurrentPlaylistInfo.OverridePlaylist;
|
|
static UCurveTable* ResourceRates = Playlist->ResourceRates.Get();
|
|
|
|
if (!ResourceRates)
|
|
{
|
|
ResourceRates = StaticFindObject<UCurveTable>(L"/Game/Athena/Balance/DataTables/AthenaResourceRates.AthenaResourceRates");
|
|
Logging::Log(ELogEvent::Warning, ELogType::Athena, "Playlist's ResourceRate was null, set to 'AthenaResourceRates'.");
|
|
}
|
|
|
|
float AmountOut = 0;
|
|
|
|
UDataTableFunctionLibrary::EvaluateCurveTableRow(ResourceRates, BuildingResourceAmountOverride.RowName, 0.f, nullptr, &AmountOut, L"");
|
|
|
|
float Amount = AmountOut / (BuildingActor->GetMaxHealth() / Damage);
|
|
ResourceAmount = round(Amount);
|
|
}
|
|
|
|
if (ResourceAmount > 0)
|
|
{
|
|
PlayerController->ClientReportDamagedResourceBuilding(BuildingActor, BuildingActor->ResourceType, ResourceAmount, Actor->bDestroyed, bWeakSpotHit);
|
|
InventoryHandler::AddItem(PlayerController, ResourceDefinition, ResourceAmount);
|
|
}
|
|
|
|
return oOnDamageServer(Actor, Damage, DamageTags, Momentum, HitInfo, InstigatedBy, DamageCauser, EffectContext);
|
|
}
|
|
|
|
char (*oCompletePickupAnimation)(AFortPickup* Pickup);
|
|
char hkCompletePickupAnimation(AFortPickup* Pickup)
|
|
{
|
|
if(!Pickup)
|
|
return oCompletePickupAnimation(Pickup);
|
|
|
|
auto Pawn = static_cast<APlayerPawn_Athena_C*>(Pickup->PickupLocationData.PickupTarget);
|
|
|
|
if (!Pawn)
|
|
return oCompletePickupAnimation(Pickup);
|
|
|
|
auto PlayerController = static_cast<AFortPlayerControllerAthena*>(Pawn->GetController());
|
|
|
|
if (!PlayerController)
|
|
return oCompletePickupAnimation(Pickup);
|
|
|
|
FGuid Swap = FGuid(-1, -1, -1, -1);
|
|
|
|
FFortItemEntry* PickupEntry = &Pickup->PrimaryPickupItemEntry;
|
|
FFortItemEntry* InvItemEntry = InventoryHandler::FindItem(PlayerController, Pickup->PickupLocationData.PickupGuid);
|
|
|
|
if (!PickupEntry || !InvItemEntry)
|
|
{
|
|
FFortItemEntry DropEntry{};
|
|
DropEntry.Count = PickupEntry->Count;
|
|
DropEntry.ItemDefinition = PickupEntry->ItemDefinition;
|
|
DropEntry.LoadedAmmo = PickupEntry->LoadedAmmo;
|
|
|
|
Utils::SpawnPickup(&DropEntry, Pawn->K2_GetActorLocation(), false, EFortPickupSourceTypeFlag::Player, Pawn);
|
|
|
|
return oCompletePickupAnimation(Pickup);
|
|
}
|
|
|
|
auto PickupItemDefinition = static_cast<UFortWorldItemDefinition*>(PickupEntry->ItemDefinition);
|
|
int IncomingCount = PickupEntry->Count;
|
|
FGuid ItemGuid = PickupEntry->ItemGuid;
|
|
|
|
if (!PickupItemDefinition)
|
|
return oCompletePickupAnimation(Pickup);
|
|
|
|
if (InventoryHandler::GetQuickBars(PickupItemDefinition) == EFortQuickBars::Primary)
|
|
{
|
|
int NewCount = 0;
|
|
int OverStack = 0;
|
|
|
|
bool bSuccess = false;
|
|
bool bDrop = false;
|
|
|
|
for (int i = 0; i < PlayerController->WorldInventory->Inventory.ReplicatedEntries.Num(); i++)
|
|
{
|
|
FFortItemEntry* CurrentEntry = &PlayerController->WorldInventory->Inventory.ReplicatedEntries[i];
|
|
if (CurrentEntry->ItemDefinition == PickupItemDefinition)
|
|
{
|
|
NewCount = CurrentEntry->Count + IncomingCount;
|
|
OverStack = NewCount - PickupItemDefinition->MaxStackSize;
|
|
|
|
CurrentEntry->Count = OverStack > 0 ? NewCount - OverStack : NewCount;
|
|
|
|
PlayerController->WorldInventory->Inventory.MarkItemDirty(*CurrentEntry);
|
|
PlayerController->WorldInventory->Inventory.MarkArrayDirty();
|
|
|
|
if (OverStack <= 0)
|
|
{
|
|
bSuccess = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bDrop = !bSuccess;
|
|
|
|
if (InventoryHandler::IsFull(PlayerController) && bDrop)
|
|
{
|
|
int DropCount = OverStack > 0 ? OverStack : IncomingCount;
|
|
|
|
if (static_cast<UFortWorldItemDefinition*>(InvItemEntry->ItemDefinition)->bCanBeDropped && InvItemEntry->ItemDefinition->bAllowMultipleStacks)
|
|
{
|
|
PlayerController->ServerAttemptInventoryDrop(InvItemEntry->ItemGuid, InvItemEntry->Count);
|
|
Swap = InventoryHandler::AddItem(PlayerController, PickupItemDefinition, DropCount, PickupEntry->LoadedAmmo);
|
|
}
|
|
else
|
|
{
|
|
FFortItemEntry DropEntry{};
|
|
DropEntry.Count = DropCount;
|
|
DropEntry.ItemDefinition = PickupItemDefinition;
|
|
DropEntry.LoadedAmmo = PickupEntry->LoadedAmmo;
|
|
|
|
Utils::SpawnPickup(&DropEntry, Pawn->K2_GetActorLocation(), false, EFortPickupSourceTypeFlag::Player, Pawn);
|
|
}
|
|
}
|
|
else if (!InventoryHandler::IsFull(PlayerController) && bDrop)
|
|
{
|
|
int DropCount = OverStack > 0 ? OverStack : IncomingCount;
|
|
|
|
InventoryHandler::AddItem(PlayerController, PickupItemDefinition, DropCount, PickupEntry->LoadedAmmo);
|
|
}
|
|
}
|
|
else
|
|
InventoryHandler::AddItem(PlayerController, PickupItemDefinition, IncomingCount, PickupEntry->LoadedAmmo);
|
|
|
|
|
|
FGuid CurrentGuid = FGuid(-1, -1, -1, -1);
|
|
if (Pawn->CurrentWeapon)
|
|
CurrentGuid = Pawn->CurrentWeapon->ItemEntryGuid;
|
|
|
|
if (Swap != FGuid(-1, -1, -1, -1) && CurrentGuid == Pickup->PickupLocationData.PickupGuid)
|
|
PlayerController->ClientEquipItem(Swap, true);
|
|
|
|
return oCompletePickupAnimation(Pickup);
|
|
}
|
|
|
|
void Initialize()
|
|
{
|
|
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));
|
|
Logging::Log(ELogEvent::Info, ELogType::Hook, "hkCompletePickupAnimation Status: %s.", MH_StatusToString(StatusCompletePickupAnimation));
|
|
#endif
|
|
Logging::Log(ELogEvent::Info, ELogType::Hook, "Actor hooks initialized.");
|
|
}
|
|
} |