haxis/Source/UnrealProject/Abilities/ProjectileBase.cpp

175 lines
4.1 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "NetworkCharacter.h"
#include "ProjectileBase.h"
#include "BlueprintAbilityLibrary.h"
#include "AbilityTriggerBase.h"
AProjectileBase::AProjectileBase()
{
m_finishTimer = 0.0f;
m_fixedTimer = 0.0f;
maxDistance = 1000.0f;
distanceTraveled = 0.0f;
keepAliveAfterFinish = 1.0f;
filter = EAbilityFilter::EnemyAll;
m_finished = false;
//server client replication
bReplicateMovement = true;
bReplicates = true;
bAlwaysRelevant = true;
PrimaryActorTick.bCanEverTick = true;
}
void AProjectileBase::BeginPlay()
{
// Get collider component
collider = Cast<UPrimitiveComponent>(GetRootComponent());
if(!collider)
{
GWERROR(L"Projectile does not have a collider root!");
Destroy();
return;
}
if(Role != ROLE_Authority)
{
collider->SetCollisionEnabled(ECollisionEnabled::NoCollision);
}
else
{
collider->OnComponentHit.AddDynamic(this, &AProjectileBase::m_OnHit);
collider->OnComponentBeginOverlap.AddDynamic(this, &AProjectileBase::m_OnOverlapBegin);
// collider->SetCollisionProfileName("Projectiles");
}
Super::BeginPlay();
}
void AProjectileBase::NativeFixedProjectileTick(float DeltaTime)
{
FixedProjectileTick(DeltaTime);
}
//call this in inherited classes, will call move
void AProjectileBase::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// Fixed timestep for projectiles
m_fixedTimer += DeltaTime;
FVector startPos = GetActorLocation();
const float delta = 1.0f / 60.0f;
while(m_fixedTimer >= delta)
{
NativeFixedProjectileTick(delta);
if (autoMove)
{
NativeMove(DeltaTime);
FVector newLocation = GetActorLocation();
FVector movedVector = newLocation - startPos;
startPos = newLocation;
distanceTraveled += movedVector.Size();
}
if (distanceTraveled > maxDistance)
{
Finish();
break;
}
m_fixedTimer -= delta;
}
if(m_finished && autoDestroy)
{
if((m_finishTimer -= DeltaTime) <= 0.0f)
{
Destroy();
}
}
}
void AProjectileBase::m_OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
ANetworkCharacter* netChar = Cast<ANetworkCharacter>(OtherActor);
if(netChar && ULib::CheckAbilityFilter(filter, character, netChar))
{
OnProjectileHit(netChar);
}
}
void AProjectileBase::m_OnHit(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
Finish();
}
void AProjectileBase::Finish_Implementation()
{
if(!m_finished)
{
if(Role == ROLE_Authority)
{
NativeServerOnFinish();
}
NativeOnProjectileFinished();
if(collider)
collider->SetCollisionEnabled(ECollisionEnabled::NoCollision);
m_finishTimer = keepAliveAfterFinish;
m_finished = true;
}
}
void AProjectileBase::FixedProjectileTick_Implementation(float DeltaTime)
{
}
void AProjectileBase::OnProjectileHit_Implementation(ANetworkCharacter* character)
{
NativeOnProjectileHit(character);
}
void AProjectileBase::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME_CONDITION(AProjectileBase, speed, COND_InitialOnly);
DOREPLIFETIME_CONDITION(AProjectileBase, filter, COND_InitialOnly);
DOREPLIFETIME_CONDITION(AProjectileBase, maxDistance, COND_InitialOnly);
DOREPLIFETIME_CONDITION(AProjectileBase, autoMove, COND_InitialOnly);
DOREPLIFETIME_CONDITION(AProjectileBase, autoDestroy, COND_InitialOnly);
}
void AProjectileBase::Move(float DeltaTime)
{
NativeMove(DeltaTime);
}
void AProjectileBase::NativeMove(float DeltaTime)
{
//moves with sweep to get collision
float distance = speed * DeltaTime;
AddActorWorldOffset(GetActorForwardVector() * distance,true);
}
void AProjectileBase::OnProjectileFinished_Implementation()
{
}
void AProjectileBase::NativeOnProjectileFinished()
{
OnProjectileFinished();
}
void AProjectileBase::NativeOnProjectileHit(ANetworkCharacter* hitCharacter)
{
}
void AProjectileBase::NativeServerOnFinish()
{
ServerOnFinish();
}