RealtimeStyleTransferRuntime/Source/LyraGame/Weapons/LyraWeaponSpawner.cpp

247 lines
7.3 KiB
C++
Raw Normal View History

2022-05-23 18:41:30 +00:00
// Copyright Epic Games, Inc. All Rights Reserved.
#include "LyraWeaponSpawner.h"
#include "Net/UnrealNetwork.h"
#include "Components/StaticMeshComponent.h"
#include "Components/CapsuleComponent.h"
#include "Equipment/LyraEquipmentDefinition.h"
#include "Equipment/LyraEquipmentManagerComponent.h"
#include "Equipment/LyraPickupDefinition.h"
#include "AbilitySystemBlueprintLibrary.h"
#include "NiagaraFunctionLibrary.h"
#include "Kismet/GameplayStatics.h"
#include "Inventory/LyraInventoryItemDefinition.h"
#include "Inventory/InventoryFragment_SetStats.h"
#include "TimerManager.h"
#include "LyraLogChannels.h"
// Sets default values
ALyraWeaponSpawner::ALyraWeaponSpawner()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
RootComponent = CollisionVolume = CreateDefaultSubobject<UCapsuleComponent>(TEXT("CollisionVolume"));
CollisionVolume->InitCapsuleSize(80.f, 80.f);
CollisionVolume->OnComponentBeginOverlap.AddDynamic(this, &ALyraWeaponSpawner::OnOverlapBegin);
PadMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("PadMesh"));
PadMesh->SetupAttachment(RootComponent);
WeaponMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WeaponMesh"));
WeaponMesh->SetupAttachment(RootComponent);
WeaponMeshRotationSpeed = 40.0f;
CoolDownTime = 30.0f;
CheckExistingOverlapDelay = 0.25f;
bIsWeaponAvailable = true;
bReplicates = true;
}
// Called when the game starts or when spawned
void ALyraWeaponSpawner::BeginPlay()
{
Super::BeginPlay();
if (WeaponDefinition && WeaponDefinition->InventoryItemDefinition)
{
CoolDownTime = WeaponDefinition->SpawnCoolDownSeconds;
}
else
{
UE_LOG(LogLyra, Error, TEXT("'%s' does not have a valid weapon definition! Make sure to set this data on the instance!"), *GetNameSafe(this));
}
}
void ALyraWeaponSpawner::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
if (UWorld* World = GetWorld())
{
World->GetTimerManager().ClearTimer(CoolDownTimerHandle);
World->GetTimerManager().ClearTimer(CheckOverlapsDelayTimerHandle);
}
Super::EndPlay(EndPlayReason);
}
// Called every frame
void ALyraWeaponSpawner::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//Update the CoolDownPercentage property to drive respawn time indicators
UWorld* World = GetWorld();
if (World->GetTimerManager().IsTimerActive(CoolDownTimerHandle))
{
CoolDownPercentage = 1.0f - World->GetTimerManager().GetTimerRemaining(CoolDownTimerHandle)/CoolDownTime;
}
WeaponMesh->AddRelativeRotation(FRotator(0.0f, World->GetDeltaSeconds() * WeaponMeshRotationSpeed, 0.0f));
}
void ALyraWeaponSpawner::OnConstruction(const FTransform& Transform)
{
if (WeaponDefinition != nullptr && WeaponDefinition->DisplayMesh != nullptr)
{
WeaponMesh->SetStaticMesh(WeaponDefinition->DisplayMesh);
WeaponMesh->SetRelativeLocation(WeaponDefinition->WeaponMeshOffset);
WeaponMesh->SetRelativeScale3D(WeaponDefinition->WeaponMeshScale);
}
}
void ALyraWeaponSpawner::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepHitResult)
{
APawn* OverlappingPawn = Cast<APawn>(OtherActor);
if (GetLocalRole() == ROLE_Authority && bIsWeaponAvailable && OverlappingPawn != nullptr)
{
AttemptPickUpWeapon(OverlappingPawn);
}
}
void ALyraWeaponSpawner::CheckForExistingOverlaps()
{
TArray<AActor*> OverlappingActors;
GetOverlappingActors(OverlappingActors, APawn::StaticClass());
for (AActor* OverlappingActor : OverlappingActors)
{
AttemptPickUpWeapon(Cast<APawn>(OverlappingActor));
}
}
void ALyraWeaponSpawner::AttemptPickUpWeapon_Implementation(APawn* Pawn)
{
if (GetLocalRole() == ROLE_Authority && bIsWeaponAvailable && UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(Pawn))
{
TSubclassOf<ULyraInventoryItemDefinition> WeaponItemDefinition = WeaponDefinition ? WeaponDefinition->InventoryItemDefinition : nullptr;
if (WeaponItemDefinition != nullptr)
{
//Attempt to grant the weapon
if (GiveWeapon(WeaponItemDefinition, Pawn))
{
//Weapon picked up by pawn
bIsWeaponAvailable = false;
SetWeaponPickupVisibility(false);
PlayPickupEffects();
StartCoolDown();
}
}
}
}
void ALyraWeaponSpawner::StartCoolDown()
{
if (UWorld* World = GetWorld())
{
World->GetTimerManager().SetTimer(CoolDownTimerHandle, this, &ALyraWeaponSpawner::OnCoolDownTimerComplete, CoolDownTime);
}
}
void ALyraWeaponSpawner::ResetCoolDown()
{
UWorld* World = GetWorld();
if (World)
{
World->GetTimerManager().ClearTimer(CoolDownTimerHandle);
}
if (GetLocalRole() == ROLE_Authority)
{
bIsWeaponAvailable = true;
PlayRespawnEffects();
SetWeaponPickupVisibility(true);
if (World)
{
World->GetTimerManager().SetTimer(CheckOverlapsDelayTimerHandle, this, &ALyraWeaponSpawner::CheckForExistingOverlaps, CheckExistingOverlapDelay);
}
}
CoolDownPercentage = 0.0f;
}
void ALyraWeaponSpawner::OnCoolDownTimerComplete()
{
ResetCoolDown();
}
void ALyraWeaponSpawner::SetWeaponPickupVisibility(bool bShouldBeVisible)
{
WeaponMesh->SetVisibility(bShouldBeVisible, true);
}
void ALyraWeaponSpawner::PlayPickupEffects_Implementation()
{
if (WeaponDefinition != nullptr)
{
USoundBase* PickupSound = WeaponDefinition->PickedUpSound;
if (PickupSound != nullptr)
{
UGameplayStatics::PlaySoundAtLocation(this, PickupSound, GetActorLocation());
}
UNiagaraSystem* PickupEffect = WeaponDefinition->PickedUpEffect;
if (PickupEffect != nullptr)
{
UNiagaraFunctionLibrary::SpawnSystemAtLocation(this, PickupEffect, WeaponMesh->GetComponentLocation());
}
}
}
void ALyraWeaponSpawner::PlayRespawnEffects_Implementation()
{
if (WeaponDefinition != nullptr)
{
USoundBase* RespawnSound = WeaponDefinition->RespawnedSound;
if (RespawnSound != nullptr)
{
UGameplayStatics::PlaySoundAtLocation(this, RespawnSound, GetActorLocation());
}
UNiagaraSystem* RespawnEffect = WeaponDefinition->RespawnedEffect;
if (RespawnEffect != nullptr)
{
UNiagaraFunctionLibrary::SpawnSystemAtLocation(this, RespawnEffect, WeaponMesh->GetComponentLocation());
}
}
}
void ALyraWeaponSpawner::OnRep_WeaponAvailability()
{
if (bIsWeaponAvailable)
{
PlayRespawnEffects();
SetWeaponPickupVisibility(true);
}
else
{
SetWeaponPickupVisibility(false);
StartCoolDown();
PlayPickupEffects();
}
}
void ALyraWeaponSpawner::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(ALyraWeaponSpawner, bIsWeaponAvailable);
}
int32 ALyraWeaponSpawner::GetDefaultStatFromItemDef(const TSubclassOf<ULyraInventoryItemDefinition> WeaponItemClass, FGameplayTag StatTag)
{
if (WeaponItemClass != nullptr)
{
if (ULyraInventoryItemDefinition* WeaponItemCDO = WeaponItemClass->GetDefaultObject<ULyraInventoryItemDefinition>())
{
if (const UInventoryFragment_SetStats* ItemStatsFragment = Cast<UInventoryFragment_SetStats>( WeaponItemCDO->FindFragmentByClass(UInventoryFragment_SetStats::StaticClass()) ))
{
return ItemStatsFragment->GetItemStatByTag(StatTag);
}
}
}
return 0;
}