haxis/Source/UnrealProject/Abilities/AbilityEventGroup.cpp

165 lines
3.9 KiB
C++

// Project Lab - NHTV Igad
#include "UnrealProject.h"
#include "AbilityEventGroup.h"
#include "NetworkCharacter.h"
#include "NPCBase.h"
AAbilityEventGroup::AAbilityEventGroup()
{
// 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;
channelEvent = false;
stunWhileChannel = true;
progressionType = EAbilityEventGroupProgressionType::Continue;
duration = 1.0f;
m_endEventSend = false;
m_hasBeenDestroyed = false;
allowRotateWhileChannel = false;
}
void AAbilityEventGroup::BeginPlay()
{
check(Role == ROLE_Authority);
Super::BeginPlay();
m_life = 0.0f;
if(!character || character->IsActorBeingDestroyed())
{
m_MoveToNextGroup();
}
else
{
// Handle the destruction of the caster
character->OnDestroyed.AddDynamic(this, &AAbilityEventGroup::m_OnCharacterDestroyed);
}
}
void AAbilityEventGroup::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
check(Role == ROLE_Authority);
if(EndPlayReason == EEndPlayReason::Destroyed)
{
Super::EndPlay(EndPlayReason);
AAbilityEventGroup* nextGroup = nullptr;
if(m_nextGroups.Num() > 0)
{
//GWPRINT(L"Move next");
nextGroup = SpawnSequence(character, abilityInfo, abilityState, m_nextGroups);
}
m_SendEndEvent(nextGroup);
}
}
void AAbilityEventGroup::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if(IsPendingKill())
return;
m_life += DeltaTime;
if(progressionType == EAbilityEventGroupProgressionType::Continue)
{
if(m_life >= duration || m_continue)
m_MoveToNextGroup();
}
else
{
if(m_continue)
m_MoveToNextGroup();
}
}
void AAbilityEventGroup::m_OnCharacterDestroyed()
{
m_MoveToNextGroup();
}
void AAbilityEventGroup::m_MoveToNextGroup()
{
if(m_hasBeenDestroyed)
return;
m_hasBeenDestroyed = true;
if(IsValid(this) && !IsPendingKillPending())
Destroy();
}
void AAbilityEventGroup::m_SendEndEvent(AAbilityEventGroup* next)
{
if(!m_endEventSend)
{
onAbilityEventGroupEnded.Broadcast(abilityInfo, this, next);
m_endEventSend = true;
}
}
void AAbilityEventGroup::Interrupt()
{
//GPRINT("Interrupting ability");
if(IsPendingKill())
return;
m_nextGroups.Empty(); // Don't execute any follow up events
m_hasBeenDestroyed = true;
}
void AAbilityEventGroup::TransitionTo(class AAbilityEventGroup* newGroup)
{
check(newGroup);
check(abilityInfo);
check(abilityState);
newGroup->character = character;
newGroup->abilityInfo = abilityInfo;
newGroup->abilityState = abilityState;
newGroup->m_nextGroups = m_nextGroups;
m_nextGroups.Empty();
m_SendEndEvent(newGroup);
//GWPRINT(L"TransitionTo next");
m_MoveToNextGroup();
}
void AAbilityEventGroup::NextGroup()
{
m_continue = true;
}
ANetworkCharacter* AAbilityEventGroup::GetTarget()
{
ANPCBase* creature = Cast<ANPCBase>(character);
if(creature)
{
return creature->target;
}
return nullptr;
}
float AAbilityEventGroup::GetLifetimeRate() const
{
float rate = m_life / duration;
return FMath::Fmod(rate, 1.0f + FLT_EPSILON);
}
float AAbilityEventGroup::GetLifetime() const
{
return m_life;
}
AAbilityEventGroup* AAbilityEventGroup::SpawnSequence(ANetworkCharacter* character, class UAbilityInfo* abilityInfo, class AAbilityState* abilityState, TArray<TSubclassOf<class AAbilityEventGroup>> groups)
{
UWorld* world = character->GetWorld();
check(world);
check(groups.Num() > 0);
AAbilityEventGroup* group = world->SpawnActorDeferred<AAbilityEventGroup>(groups[0], FTransform::Identity);
check(group);
check(abilityInfo);
check(abilityState);
group->character = character;
group->abilityState = abilityState;
group->abilityInfo = abilityInfo;
groups.RemoveAt(0);
group->m_nextGroups = groups;
UGameplayStatics::FinishSpawningActor(group, FTransform::Identity);
return group;
}