// Project Lab - NHTV Igad #include "UnrealProject.h" #include "NetworkCharacter.h" #include "AbilityTriggerBase.h" #include "BlueprintAbilityLibrary.h" AAbilityTriggerBase::AAbilityTriggerBase() { PrimaryActorTick.bCanEverTick = true; filter = EAbilityFilter::EnemyAll; autoDestroy = true; bReplicateMovement = true; bReplicates = true; duration = 1.0f; ticksPerSecond = 0.0f; m_lifeTime = 0.0f; } void AAbilityTriggerBase::BeginPlay() { if (Role == ROLE_Authority) { if (!character) { GWERROR(L"No owner assigned to trigger " + GetName()); this->SetActorEnableCollision(false); Destroy(); } if (ticksPerSecond > 0) { m_tickTime = 1.0f / ticksPerSecond; } else { m_tickTime = 0.0f; } } //make sure the collision delegates are working UShapeComponent* root = Cast(RootComponent); if (root != nullptr && !delegatesSet) { root->OnComponentBeginOverlap.AddDynamic(this, &AAbilityTriggerBase::OnOverlapBegin); root->OnComponentEndOverlap.AddDynamic(this, &AAbilityTriggerBase::OnOverlapEnd); delegatesSet = true; } else FWARNING("rootComponent is not a UShapeComponent"); Super::BeginPlay(); if (Role == ROLE_Authority) UpdateOverlaps(); } void AAbilityTriggerBase::EndPlay(const EEndPlayReason::Type EndPlayReason) { if (Role == ROLE_Authority) { while (m_actorsInside.Num()>0) { if (IsValid(m_actorsInside.GetData()[0])) { LeaveEvent(Cast(m_actorsInside.GetData()[0])); } } } Super::EndPlay(EndPlayReason); } void AAbilityTriggerBase::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const { Super::GetLifetimeReplicatedProps(OutLifetimeProps); DOREPLIFETIME_CONDITION(AAbilityTriggerBase, duration, COND_InitialOnly); } void AAbilityTriggerBase::Tick(float DeltaTime) { m_lifeTime += DeltaTime; Super::Tick(DeltaTime); if(Role != ROLE_Authority || !IsValid(this)) return; UpdateOverlaps(); if(autoDestroy && m_lifeTime >= duration) { Destroy(); return; } if(m_tickTime > 0) { m_tickTimer += DeltaTime; while(m_tickTimer > m_tickTime) { m_tickTimer -= m_tickTime; for(AActor* actorInside : m_actorsInside) { if (CollisionCheck(Cast(actorInside))) { OnTriggerTick(Cast(actorInside)); NativeOnLocalTriggerTick(Cast(actorInside)); } } } } } void AAbilityTriggerBase::OnOverlapBegin(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) { if(Role != ROLE_Authority) return; if(OtherActor == NULL) { FWPRINT(L"Error - wrong otherunit on OnOverlapBegin "); return; } if(character == NULL) { FWPRINT(L"Error - m_character NULL on OnOverlapBegin "); return; } ANetworkCharacter* otherUnit = Cast(OtherActor); if(!otherUnit->GetHitable()) return; if(!ULib::CheckAbilityFilter(filter, character, otherUnit)) return; if(hitOnce && m_CheckActorsHit(otherUnit)) return; m_actorsInside.Add(OtherActor); if (CollisionCheck(Cast(OtherActor))) { HitEvent(otherUnit); } } void AAbilityTriggerBase::OnOverlapEnd(class AActor * OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) { if(Role == ROLE_Authority) LeaveEvent(Cast(OtherActor)); } void AAbilityTriggerBase::HitEvent(class ANetworkCharacter* otherUnit) { if (hitOnce) m_actorsHit.Add(otherUnit); OnTriggerHit(otherUnit); } void AAbilityTriggerBase::LeaveEvent(class ANetworkCharacter* otherActor) { if (Role == ROLE_Authority) { for (auto it = (m_actorsInside.CreateIterator()); it; it++) { if (*it == otherActor) { m_actorsInside.Remove(otherActor); break; } } if (!ULib::CheckAbilityFilter(filter, character, otherActor)) return; OnTriggerLeave(otherActor); } } float AAbilityTriggerBase::GetLifeTime() const { return m_lifeTime; } float AAbilityTriggerBase::GetLifeTimeRate() const { return FMath::Clamp(m_lifeTime / duration, 0.0f, 1.0f); } bool AAbilityTriggerBase::m_CheckActorsHit(class ANetworkCharacter* otherUnit) { for (ANetworkCharacter* character : m_actorsHit) { if (character == otherUnit) return true; } return false; } bool AAbilityTriggerBase::CollisionCheck(ANetworkCharacter* otheractor) { return IsValid(otheractor); } void AAbilityTriggerBase::OnTriggerHit_Implementation(ANetworkCharacter* actor) { } void AAbilityTriggerBase::OnTriggerTick_Implementation(ANetworkCharacter* actor) { } void AAbilityTriggerBase::OnTriggerLeave_Implementation(ANetworkCharacter* actor) { } void AAbilityTriggerBase::OnLocalTriggerTick_Implementation(ANetworkCharacter* actor) { } void AAbilityTriggerBase::NativeOnLocalTriggerTick_Implementation(ANetworkCharacter* actor) { OnLocalTriggerTick(actor); }