237 lines
7.4 KiB
C++
237 lines
7.4 KiB
C++
// Project Lab - NHTV Igad
|
|
|
|
#include "UnrealProject.h"
|
|
#include "GeneralEnemy.h"
|
|
#include "SpawnerBase.h"
|
|
#include "BehaviorTree/EnemyAIController.h"
|
|
#include "NetworkPlayer.h"
|
|
#include "OffensiveEnemy.h"
|
|
#include "MinionAnimInstance.h"
|
|
|
|
AGeneralEnemy::AGeneralEnemy()
|
|
{
|
|
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
}
|
|
void AGeneralEnemy::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
if (Role != ROLE_Authority)
|
|
return;
|
|
if (m_spawn)
|
|
{
|
|
m_spawn->hasGeneral = true;
|
|
FVector addVector;
|
|
for (int i = 0; i < 4; i++)
|
|
{
|
|
addVector = m_spawn->GetActorForwardVector().RotateAngleAxis(i * 90, FVector::UpVector);
|
|
patrolLocations.Add(addVector);
|
|
}
|
|
}
|
|
if (distance == 0)
|
|
{
|
|
distance = 100.0f;
|
|
}
|
|
/* for (int i = 0; i < formationEnemies.Num(); i++)
|
|
{
|
|
formationEnemies[i]->general = this;
|
|
}*/
|
|
|
|
|
|
}
|
|
void AGeneralEnemy::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
Super::EndPlay(EndPlayReason);
|
|
if (Role != ROLE_Authority)
|
|
return;
|
|
for (int i = 0; i < formationEnemies.Num(); i++)
|
|
{
|
|
formationEnemies[i]->ResetConfusionTimer(3.0f);
|
|
formationEnemies[i]->general = nullptr;
|
|
}
|
|
if (m_spawn != nullptr)
|
|
m_spawn->hasGeneral = false;
|
|
//formationEnemies.Empty();
|
|
}
|
|
void AGeneralEnemy::Tick(float deltaTime)
|
|
{
|
|
Super::Tick(deltaTime);
|
|
if (Role != ROLE_Authority)
|
|
return;
|
|
if (!IsValid(m_spawn))
|
|
{
|
|
RERROR("There is no spawn for the general enemy");
|
|
return;
|
|
}
|
|
for (int i = 0; i < formationEnemies.Num(); i++)
|
|
{
|
|
if (IsValid(formationEnemies[i]->general))
|
|
continue;
|
|
formationEnemies[i]->general = this;
|
|
|
|
}
|
|
|
|
if (IsValid(target))
|
|
{
|
|
|
|
|
|
FVector2D locationVec = FVector2D(target->GetActorLocation()) - FVector2D(GetActorLocation());
|
|
locationVec.Normalize();
|
|
if (FVector::DistSquaredXY(GetActorLocation(), target->GetActorLocation()) > m_spawn->formationDistance* m_spawn->formationDistance)
|
|
{
|
|
|
|
MoveToPoint((target->GetActorLocation()));// +(FVector(locationVec, 0))* m_spawn->formationDistance));
|
|
DefaultFormation();
|
|
|
|
}
|
|
else
|
|
{
|
|
GetCharacterMovement()->Velocity = FVector::ZeroVector;
|
|
MoveToPoint(GetActorLocation());
|
|
GetCharacterMovement()->Velocity = FVector::ZeroVector;
|
|
SetActorRotation(FVector(target->GetActorLocation() - GetActorLocation()).Rotation());
|
|
ChargeFormation();
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
IdleFormation(deltaTime);
|
|
}
|
|
}
|
|
void AGeneralEnemy::SingleTargetFormation(int enemyNum)
|
|
{
|
|
if ((formationEnemies[enemyNum]->enemycontroller)->IsA(AEnemyAIController::StaticClass()))
|
|
{
|
|
formationEnemies[enemyNum]->target = target;
|
|
formationEnemies[enemyNum]->enemycontroller->SetBool(true, FName("EnableTree"));
|
|
formationEnemies[enemyNum]->SetActorRotation(FVector(target->GetActorLocation() - formationEnemies[enemyNum]->GetActorLocation()).Rotation());
|
|
if (count < 3)
|
|
{
|
|
formationEnemies[enemyNum]->enemycontroller->SetBool(false, FName("GuardKey"));
|
|
formationEnemies[enemyNum]->enemycontroller->SetVector(target->GetActorLocation() + target->GetActorForwardVector() * 200, FName("FrontLoc"));
|
|
formationEnemies[enemyNum]->enemycontroller->SetVector(target->GetActorLocation() + target->GetActorForwardVector() * -200, FName("BacktLoc"));
|
|
formationEnemies[enemyNum]->enemycontroller->SetVector(target->GetActorLocation() + target->GetActorRightVector() *-200, FName("LeftLoc"));
|
|
formationEnemies[enemyNum]->enemycontroller->SetVector(target->GetActorLocation() + target->GetActorRightVector() * 200, FName("RightLoc"));
|
|
}
|
|
else
|
|
{
|
|
formationEnemies[enemyNum]->enemycontroller->SetBool(true, FName("GuardKey"));
|
|
formationEnemies[enemyNum]->enemycontroller->SetVector(GetActorLocation() + GetActorForwardVector() * 100, FName("HomeLocation"));
|
|
}
|
|
count++;
|
|
}
|
|
|
|
}
|
|
void AGeneralEnemy::ChargeFormation()
|
|
{
|
|
if (!IsValid(target))
|
|
return;
|
|
count = 0;
|
|
TArray<ANetworkPlayer*> targetArray = m_spawn->GetNearbyPlayers();
|
|
if (targetArray.Num() == 0)
|
|
return;
|
|
for (int i = 0; i < formationEnemies.Num(); i++)
|
|
{
|
|
if (targetArray.Num() == 1)
|
|
{
|
|
SingleTargetFormation(i);
|
|
continue;
|
|
}
|
|
if (Cast<AOffensiveEnemy>(formationEnemies[i]))
|
|
{
|
|
formationEnemies[i]->target = m_spawn->GetClosestPlayer();
|
|
formationEnemies[i]->MoveToPoint(target->GetActorLocation());
|
|
}
|
|
else
|
|
{
|
|
ANetworkPlayer* newTarget = nullptr;
|
|
for (int j = 0; j < targetArray.Num(); j++)
|
|
{
|
|
if(targetArray[j]==m_spawn->GetClosestPlayer())
|
|
continue;
|
|
newTarget = targetArray[j];
|
|
continue;
|
|
}
|
|
formationEnemies[i]->target = newTarget;
|
|
}
|
|
}
|
|
}
|
|
void AGeneralEnemy::DefaultFormation()
|
|
{
|
|
FVector rotatedFormation;
|
|
for (int i = 0; i < formationEnemies.Num(); i++)
|
|
{
|
|
if (!IsValid(formationEnemies[i]) || !IsValid(m_spawn) || (m_spawn->formationPoints.Num() + 1) < formationEnemies.Num())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
|
|
formationEnemies[i]->target = target;
|
|
rotatedFormation = GetActorRotation().RotateVector(FVector(m_spawn->formationPoints[i + 1].X - m_spawn->formationPoints[0].X, m_spawn->formationPoints[i + 1].Y - m_spawn->formationPoints[0].Y, 0));
|
|
|
|
formationEnemies[i]->MoveToPoint(GetActorLocation() + rotatedFormation);
|
|
formationEnemies[i]->SetActorRotation(FRotator(0, m_spawn->formationRotation[i + 1], 0) + (GetActorRotation()));
|
|
|
|
formationEnemies[i]->enemycontroller->SetBool(false, FName("EnableTree"));
|
|
formationEnemies[i]->enemycontroller->SetVector(formationEnemies[i]->GetActorLocation(), FName("HomeLocation"));
|
|
|
|
|
|
}
|
|
}
|
|
int AGeneralEnemy::NativeDealDamage(class ANetworkCharacter* dealer, int32 damage, float armorPercentageIgnore, class UAbilityInfo* ability)
|
|
{
|
|
//CHANGEANIMATION(EMinionAnimState::MAS_Pointing);
|
|
ChangeNPCAnimation((uint8)EMinionAnimState::MAS_Pointing);
|
|
return Super::NativeDealDamage(dealer, damage, armorPercentageIgnore, ability);
|
|
}
|
|
void AGeneralEnemy::NativeOnKilled(class ANetworkCharacter* killer, class UAbilityInfo* ability)
|
|
{
|
|
Super::NativeOnKilled(killer, ability);
|
|
if (Role != ROLE_Authority)
|
|
return;
|
|
if (m_spawn &&m_spawn->possesable)
|
|
{
|
|
int32 team = killer->GetTeam();
|
|
m_spawn->CaptureCamp(team);
|
|
|
|
}
|
|
}
|
|
void AGeneralEnemy::IdleFormation(float deltaTime)
|
|
{
|
|
// Move to a random point near the spawn point;
|
|
|
|
//controll enemies in the formation
|
|
int counter = 0;
|
|
for (int i = 0; i < formationEnemies.Num(); i++)
|
|
{
|
|
if (!IsValid(formationEnemies[i]) || !IsValid(m_spawn) || (m_spawn->formationPoints.Num() + 1) < formationEnemies.Num())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!formationEnemies[i]->m_tempTarget)
|
|
{
|
|
if (Cast<AOffensiveEnemy>(formationEnemies[i])&&counter<4)
|
|
{
|
|
formationEnemies[i]->PatrolBetweenLocations (patrolLocations[counter].RotateAngleAxis( 90, FVector::UpVector)*500+ patrolLocations[counter]* 500 + m_spawn->GetActorLocation(), patrolLocations[counter].RotateAngleAxis( 270, FVector::UpVector) * 500 + patrolLocations[counter] * 500 + m_spawn->GetActorLocation(), deltaTime);
|
|
counter++;
|
|
continue;
|
|
}
|
|
|
|
formationEnemies[i]->MoveToPoint(FVector(m_spawn->formationPoints[i + 1],0)+m_spawn->GetActorLocation());
|
|
//formationEnemies[i]->MoveToPointSlow(randpos + m_spawn->GetActorLocation(), 50.0f);
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
if(formationEnemies[i]->IsA(AOffensiveEnemy::StaticClass()))
|
|
Cast<AOffensiveEnemy>(formationEnemies[i])->BasicBehavior();
|
|
if(formationEnemies[i]->IsA(ARangedEnemy::StaticClass()))
|
|
Cast<ARangedEnemy>(formationEnemies[i])->BasicBehavior();
|
|
}
|
|
formationEnemies[i]->target = nullptr;
|
|
}
|
|
} |