259 lines
6.7 KiB
C++
259 lines
6.7 KiB
C++
// Project Lab - NHTV Igad
|
|
|
|
#include "UnrealProject.h"
|
|
#include "PatrolSpawn.h"
|
|
#include "NPCBase.h"
|
|
#include "DefaultGameMode.h"
|
|
#include "NetworkPlayer.h"
|
|
|
|
APatrolSpawn::APatrolSpawn()
|
|
{
|
|
respawnTime = 5;
|
|
m_respawnTimer = 0;
|
|
|
|
spawnContinuous = true;
|
|
}
|
|
|
|
void APatrolSpawn::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
if (Role != ROLE_Authority)
|
|
return;
|
|
FName name;
|
|
|
|
if (aggroRadius < 0) aggroRadius = 0;
|
|
if (respawnTime < 0) respawnTime = 0;
|
|
|
|
if (spawns.Num() == 0)
|
|
{
|
|
JWARNING("Empty spawner in scene");
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < controlPoints.Num(); i++)
|
|
m_controlPoints.Add(FVector(controlPoints[i].X + this->GetActorLocation().X, controlPoints[i].Y + this->GetActorLocation().Y, this->GetActorLocation().Z));
|
|
|
|
m_controlPointSign = 1;
|
|
m_isPulled = false;
|
|
|
|
m_currentControlPoint = 0;
|
|
m_lastPosition = GetActorLocation();
|
|
|
|
//SpawnMobs();
|
|
}
|
|
|
|
void APatrolSpawn::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
Super::EndPlay(EndPlayReason);
|
|
|
|
}
|
|
|
|
void APatrolSpawn::Tick(float DeltaTime)
|
|
{
|
|
Super::Tick(DeltaTime);
|
|
|
|
|
|
|
|
if (Role != ROLE_Authority)
|
|
return;
|
|
|
|
UWorld* const world = GetWorld();
|
|
if (!world) return;
|
|
|
|
check(m_mobs.Num() == spawns.Num());
|
|
|
|
m_respawnTimer = m_respawnTimer > 0 ? (m_respawnTimer - DeltaTime) : 0;
|
|
if (m_respawnTimer <= 0 && m_mobCount != m_mobs.Num() && spawnContinuous)
|
|
m_RespawnMobs();
|
|
if (m_mobs.Num() == 0)
|
|
return;
|
|
// Respawn the mobs
|
|
/* if (spawnContinuous)
|
|
m_RespawnMobs();*/
|
|
if (m_controlPoints.Num() <= 0)
|
|
{
|
|
RWARNING("There are no control points");
|
|
return;
|
|
}
|
|
|
|
bool anyIdle = false;
|
|
for (int32 i = 0; i < spawns.Num(); i++)
|
|
{
|
|
if (!spawns[i])
|
|
continue;
|
|
|
|
if (i == 0 && m_mobs[i] != nullptr)
|
|
{
|
|
if (m_isPulled == false)
|
|
{
|
|
RPRINT("testing");
|
|
m_lastPosition = m_mobs[i]->GetActorLocation();
|
|
}
|
|
else if (!m_mobs[i]->target)
|
|
{
|
|
const FVector2D mobPos = FVector2D(m_mobs[i]->GetActorLocation().X, m_mobs[i]->GetActorLocation().Y);
|
|
const float distSqr = FVector2D::DistSquared(mobPos, FVector2D(m_lastPosition.X, m_lastPosition.Y));
|
|
if (distSqr < (m_mobs[i]->collisionRadius*m_mobs[i]->collisionRadius)*collisionScaler)
|
|
m_isPulled = false;
|
|
}
|
|
|
|
|
|
// Any of the mobs not doing anything?
|
|
const FVector2D mobPos = FVector2D(m_mobs[i]->GetActorLocation().X, m_mobs[i]->GetActorLocation().Y);
|
|
const float distSqr = FVector2D::DistSquared(mobPos, FVector2D(m_lastPosition.X, m_lastPosition.Y));
|
|
|
|
////// Regeneration (hardcoded, remove in future)
|
|
if (!m_mobs[i]->target && distSqr < aggroRadius*aggroRadius)
|
|
{
|
|
anyIdle = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_mobs[0] != nullptr && m_isPulled)
|
|
{
|
|
m_mobs[0]->SetControlPoint(m_lastPosition);
|
|
for (int i = 1; i < m_mobs.Num(); i++)
|
|
{
|
|
m_mobs[i]->SetControlPoint(m_lastPosition);
|
|
}
|
|
}
|
|
ADefaultGameMode* const mode = Cast<ADefaultGameMode>(world->GetAuthGameMode());
|
|
if (mode)
|
|
{
|
|
FVector controlLocation = GetActorLocation();
|
|
// check if there are some controll points
|
|
if (m_mobs[0] != nullptr && !m_isPulled)
|
|
{
|
|
if (FVector2D::DistSquared(FVector2D(m_mobs[0]->GetActorLocation().X, m_mobs[0]->GetActorLocation().Y), FVector2D(m_controlPoints[m_currentControlPoint].X, m_controlPoints[m_currentControlPoint].Y)) < 10000)
|
|
{
|
|
m_currentControlPoint += m_controlPointSign;
|
|
if (m_currentControlPoint >= m_controlPoints.Num() || m_currentControlPoint < 0)
|
|
{
|
|
m_controlPointSign *= -1;
|
|
m_currentControlPoint += m_controlPointSign;
|
|
if (isConnected)
|
|
{
|
|
m_currentControlPoint = 0;
|
|
m_controlPointSign *= -1;
|
|
}
|
|
}
|
|
}
|
|
// set new control location
|
|
controlLocation = m_controlPoints[m_currentControlPoint];
|
|
|
|
m_mobs[0]->SetControlPoint(controlLocation);
|
|
if (m_mobs.Num() > 1)
|
|
{
|
|
|
|
for (int i = 1; i < m_mobs.Num(); i++)
|
|
{
|
|
m_mobs[i]->SetControlPoint(m_lastPosition);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (anyIdle && !m_isPulled)
|
|
{
|
|
/*// Find the closest player (in aggroRadius)
|
|
ANetworkCharacter* closest = nullptr;
|
|
float closestDist = BIG_NUMBER;
|
|
TArray<ANetworkCharacter*> players = mode->GetPlayers();
|
|
const float aggroSqr = aggroRadius * aggroRadius;
|
|
for (int32 i = 0; i < players.Num(); i++)
|
|
{
|
|
const float distSqr = FVector::DistSquared(m_mobs[0]->GetActorLocation(), players[i]->GetActorLocation());
|
|
if (distSqr < closestDist && distSqr <= aggroSqr)
|
|
{
|
|
closest = players[i];
|
|
closestDist = distSqr;
|
|
}
|
|
}*/
|
|
ANetworkPlayer* closest = m_GetClosestPlayer();
|
|
if (closest)
|
|
{
|
|
// Attack the closest player
|
|
for (int32 i = 0; i < spawns.Num(); i++)
|
|
{
|
|
if (m_mobs[i] == nullptr)
|
|
continue;
|
|
|
|
m_mobs[i]->target = (closest);
|
|
m_isPulled = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
FVector APatrolSpawn::SpawnResetPosition()
|
|
{
|
|
return m_lastPosition;
|
|
}
|
|
|
|
void APatrolSpawn::SpawnMobs()
|
|
{
|
|
m_RespawnMobs();
|
|
}
|
|
void APatrolSpawn::m_RespawnMobs()
|
|
{
|
|
UWorld* const world = GetWorld();
|
|
if (!world)
|
|
return;
|
|
for (int32 i = 0; i < m_mobs.Num(); i++)
|
|
{
|
|
if (!spawns[i])
|
|
continue;
|
|
if (m_mobs[i] == nullptr)
|
|
{
|
|
// Respawn!
|
|
FTransform spawnTransform = GetTransform();
|
|
if (hasGeneral)
|
|
{
|
|
spawnTransform.SetLocation(FVector(formationPoints[i].X, formationPoints[i].Y,0) + GetActorLocation());
|
|
}
|
|
else
|
|
{
|
|
spawnTransform.SetLocation(GetActorLocation() + FVector(0, 0, 120));
|
|
}
|
|
spawnTransform.SetRotation(FRotator(GetActorRotation() + FRotator(0, formationRotation[i], 0)).Quaternion());
|
|
ANPCBase* character = world->SpawnActorDeferred<ANPCBase>(spawns[i], spawnTransform, nullptr, nullptr, ESpawnActorCollisionHandlingMethod());
|
|
character->SetSpawn(this);
|
|
character->SetTeam((int32)team);
|
|
m_mobs[i] = character;
|
|
m_mobCount++;
|
|
m_OnMobSpawn(i);
|
|
UGameplayStatics::FinishSpawningActor(character, spawnTransform);
|
|
character->SpawnDefaultController();
|
|
}
|
|
}
|
|
|
|
m_respawnTimer = respawnTime;
|
|
}
|
|
class ANetworkPlayer* APatrolSpawn::m_GetClosestPlayer()
|
|
{
|
|
UWorld* const world = GetWorld();
|
|
if (!world)
|
|
return nullptr;
|
|
ADefaultGameMode* const mode = Cast<ADefaultGameMode>(world->GetAuthGameMode());
|
|
if (!mode)
|
|
return nullptr;
|
|
|
|
// Find the closest player (in aggroRadius)
|
|
ANetworkPlayer* closest = nullptr;
|
|
float closestDist = BIG_NUMBER;
|
|
TArray<ANetworkPlayer*> players = mode->GetPlayers();
|
|
const float aggroSqr = aggroRadius * aggroRadius;
|
|
for (int32 i = 0; i < players.Num(); i++)
|
|
{
|
|
const float distSqr = FVector2D::DistSquared(FVector2D(m_mobs[0]->GetActorLocation()), FVector2D(players[i]->GetActorLocation()));
|
|
if (distSqr < closestDist && distSqr <= aggroSqr)
|
|
{
|
|
closest = players[i];
|
|
closestDist = distSqr;
|
|
}
|
|
}
|
|
|
|
return closest;
|
|
} |