189 lines
4.6 KiB
C++
189 lines
4.6 KiB
C++
// Project Lab - NHTV Igad
|
|
|
|
#include "UnrealProject.h"
|
|
#include "Creatures/NetworkCharacter.h"
|
|
#include "Creatures/NetworkPlayer.h"
|
|
#include "IllusionCharacter.h"
|
|
#include "BlueprintAbilityLibrary.h"
|
|
#include "AIController.h"
|
|
#include "DealDamageProxy.h"
|
|
#include "AbilityInfo.h"
|
|
#include "NativeModifiers.h"
|
|
|
|
AIllusionCharacter::AIllusionCharacter()
|
|
{
|
|
PrimaryActorTick.bCanEverTick = true;
|
|
aggroRange = 400;
|
|
acceptenceDistance = 200;
|
|
lifeTime = 30;
|
|
}
|
|
|
|
void AIllusionCharacter::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
if (Role != ROLE_Authority)
|
|
{
|
|
return;
|
|
}
|
|
FActorSpawnParameters SpawnInfo;
|
|
SpawnInfo.Instigator = Instigator;
|
|
SpawnInfo.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
|
|
SpawnInfo.OverrideLevel = GetLevel();
|
|
SpawnInfo.ObjectFlags |= RF_Transient; // We never want to save AI controllers into a map
|
|
AController* NewController = GetWorld()->SpawnActor<AController>(AAIController::StaticClass(), GetActorLocation(), GetActorRotation(), SpawnInfo);
|
|
|
|
if (NewController != NULL)
|
|
{
|
|
// if successful will result in setting this->Controller
|
|
// as part of possession mechanics
|
|
NewController->Possess(this);
|
|
}
|
|
|
|
if (IsValid(illOwner))
|
|
{
|
|
m_maxHealth = illOwner->GetMaxHealth();
|
|
m_health = illOwner->GetHealth();
|
|
}
|
|
else
|
|
{
|
|
FERROR("NO ILLOWNER IN ILLUSIONCHARACTER");
|
|
}
|
|
if (illOwner)
|
|
{
|
|
abilities.Add(illOwner->abilities[0]);
|
|
m_attackSpeed =illOwner->m_attackSpeed;
|
|
}
|
|
m_isdying = false;
|
|
}
|
|
void AIllusionCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|
{
|
|
Super::EndPlay(EndPlayReason);
|
|
}
|
|
void AIllusionCharacter::Tick(float deltaTime)
|
|
{
|
|
Super::Tick(deltaTime);
|
|
if (Role != ROLE_Authority)
|
|
{
|
|
return;
|
|
}
|
|
lifeTime -= deltaTime;
|
|
if (lifeTime <= 0)
|
|
{
|
|
if(!m_isdying)
|
|
Kill();
|
|
return;
|
|
}
|
|
UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld());
|
|
if (!NavSys)
|
|
{
|
|
RERROR("there is no nav sys");
|
|
}
|
|
if (!GetController())
|
|
{
|
|
RERROR("there is no controller");
|
|
}
|
|
if (!IsValid(illOwner))
|
|
{
|
|
Kill();
|
|
return;
|
|
}
|
|
if (!IsValid(target))
|
|
{
|
|
attacking = false;
|
|
//targetList = ULib::GetCharacterOverlaps();
|
|
target = GetClosestTarget();
|
|
if (FVector::DistSquared(illOwner->GetActorLocation(), GetActorLocation()) > acceptenceDistance*acceptenceDistance)
|
|
{
|
|
MoveTo(illOwner->GetActorLocation());
|
|
FPRINT("moving to the illOwner");
|
|
}
|
|
else MoveTo(GetActorLocation());
|
|
return;
|
|
}
|
|
if (!attacking)
|
|
{
|
|
attacking = IsAttacking(1.0f);
|
|
return;
|
|
}
|
|
Attack();
|
|
|
|
}
|
|
void AIllusionCharacter::Attack()
|
|
{
|
|
int randdistance =0;
|
|
randdistance += ((int)abilities[0]->AICastRange / 2);
|
|
if (FVector::Dist(GetActorLocation(), target->GetActorLocation()) < randdistance)
|
|
{
|
|
MoveTo(GetActorLocation());
|
|
SetActorRotation(FVector(target->GetActorLocation() - GetActorLocation()).Rotation());
|
|
}
|
|
else MoveTo(target->GetActorLocation());
|
|
for (int i = 0; i < abilities.Num(); i++)
|
|
{
|
|
if ((abilities[i])&&FVector::DistSquared(GetActorLocation(),target->GetActorLocation())<abilities[i]->AICastRange*abilities[i]->AICastRange)
|
|
{
|
|
CastAbility(abilities[i]);
|
|
}
|
|
}
|
|
}
|
|
ANetworkCharacter* AIllusionCharacter::GetClosestTarget()
|
|
{
|
|
ANetworkCharacter* returnTarget = nullptr;
|
|
float distance = 1e34;
|
|
for (ANetworkCharacter* character : targetList)
|
|
{
|
|
if(!IsValid(character)||character==this || character->GetTeam()==GetTeam())
|
|
continue;
|
|
float tempdistance = FVector::DistSquared(character->GetActorLocation(), GetActorLocation());
|
|
if (distance > tempdistance)
|
|
{
|
|
distance = tempdistance;
|
|
returnTarget = character;
|
|
}
|
|
}
|
|
return returnTarget;
|
|
}
|
|
void AIllusionCharacter::MoveTo(FVector Location)
|
|
{
|
|
UNavigationSystem* NavSys = UNavigationSystem::GetCurrent(GetWorld());
|
|
if (IsPendingKill() || IsPendingKillPending())
|
|
return;
|
|
if (!IsStunned())
|
|
{
|
|
NavSys->SimpleMoveToLocation(this->Controller, Location);
|
|
}
|
|
else
|
|
{
|
|
NavSys->SimpleMoveToLocation(this->Controller, GetActorLocation());
|
|
}
|
|
}
|
|
bool AIllusionCharacter::IsAttacking(float changePercentage)
|
|
{
|
|
int num = rand() % 100;
|
|
if (num > (int)changePercentage)
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void AIllusionCharacter::Kill()
|
|
{
|
|
if (IsPendingKill() || IsPendingKillPending())
|
|
{
|
|
RERROR("the character is pending kill");
|
|
return;
|
|
|
|
}
|
|
ADOTModifier* deathMod = GetWorld()->SpawnActor<ADOTModifier>();
|
|
deathMod->damagePerTick = 500;
|
|
deathMod->lifeTime = 0;
|
|
deathMod->target = this;
|
|
deathMod->character = this;
|
|
deathMod->abilityInfo = abilityInfo;
|
|
m_modifierManager->AddModifier(deathMod);
|
|
m_isdying = true;
|
|
//m_health = 0;
|
|
// m_shouldBeDestroyed = true;
|
|
} |