// 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(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())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(); 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; }