// 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 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(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(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(formationEnemies[i])->BasicBehavior(); if(formationEnemies[i]->IsA(ARangedEnemy::StaticClass())) Cast(formationEnemies[i])->BasicBehavior(); } formationEnemies[i]->target = nullptr; } }