Advertisement
Dieton

Enemy.cpp

Dec 17th, 2023 (edited)
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.38 KB | Gaming | 0 0
  1. // Fill out your copyright notice in the Description page of Project Settings.
  2.  
  3. #include "Enemy/Enemy.h"
  4. #include "AIController.h"
  5.  
  6. #include "Components/SkeletalMeshComponent.h"
  7. #include "Components/CapsuleComponent.h"
  8. #include "Components/AttributeComponent.h"
  9. #include "HUD/HealthBarComponent.h"
  10. #include "GameFramework/CharacterMovementComponent.h"
  11. #include "Perception/PawnSensingComponent.h"
  12.  
  13. #include "Items/Weapons/Weapon.h"
  14. #include "Kismet/KismetSystemLibrary.h"
  15. #include "Kismet/GameplayStatics.h"
  16.  
  17. #include "Slash/DebugMacros.h"
  18.  
  19.  
  20. // Sets default values
  21. AEnemy::AEnemy()
  22. {
  23.     // Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
  24.     PrimaryActorTick.bCanEverTick = true;
  25.  
  26.     GetMesh()->SetCollisionObjectType(ECollisionChannel::ECC_WorldDynamic);
  27.     GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Visibility, ECollisionResponse::ECR_Block);
  28.     GetMesh()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
  29.     GetMesh()->SetGenerateOverlapEvents(true);
  30.     GetCapsuleComponent()->SetCollisionResponseToChannel(ECollisionChannel::ECC_Camera, ECollisionResponse::ECR_Ignore);
  31.  
  32.    
  33.  
  34.     HealthBarWidget = CreateDefaultSubobject<UHealthBarComponent>(TEXT("Helth Bar Widget"));
  35.     HealthBarWidget->SetupAttachment(GetRootComponent());
  36.  
  37.     GetCharacterMovement()->bOrientRotationToMovement = true;
  38.     bUseControllerRotationPitch = false;
  39.     bUseControllerRotationYaw = false;
  40.     bUseControllerRotationRoll = false;
  41.  
  42.     PawnSensing = CreateDefaultSubobject<UPawnSensingComponent>(TEXT("Pawn Sensing"));
  43.     PawnSensing->SightRadius = 2048.f;
  44.     PawnSensing->SetPeripheralVisionAngle(45.f);
  45. }
  46.  
  47. void AEnemy::PatrolTimerFinished()
  48. {
  49.     MoveToTarget(PatrolTarget);
  50. }
  51.  
  52.  
  53.  
  54. void AEnemy::BeginPlay()
  55. {
  56.     Super::BeginPlay();
  57.  
  58.     if (HealthBarWidget)
  59.     {
  60.         HealthBarWidget->SetVisibility(false);
  61.     }
  62.  
  63.     EnemyController = Cast<AAIController>(GetController());
  64.     MoveToTarget(PatrolTarget);
  65.  
  66.     if (PawnSensing)
  67.     {
  68.         PawnSensing->OnSeePawn.AddDynamic(this, &AEnemy::PawnSeen);
  69.     }
  70.  
  71.     UWorld* World = GetWorld();
  72.     if (World && WeaponClass)
  73.     {
  74.         AWeapon* DefultWeapon = World->SpawnActor<AWeapon>(WeaponClass);
  75.         DefultWeapon->Equip(GetMesh(), FName("RightHandSocket"), this, this);
  76.         EquippedWeapon = DefultWeapon;
  77.     }
  78.  
  79.     /*
  80.     if (EnemyController && PatrolTarget)
  81.     {
  82.         FAIMoveRequest MoveRequest;
  83.         MoveRequest.SetGoalActor(PatrolTarget);
  84.         MoveRequest.SetAcceptanceRadius(15.f);
  85.         FNavPathSharedPtr NavPath;
  86.         EnemyController->MoveTo(MoveRequest, &NavPath);
  87.         TArray<FNavPathPoint>& PathPoints = NavPath->GetPathPoints();
  88.         for (auto& Point : PathPoints)
  89.         {
  90.             const FVector& Location = Point.Location;
  91.             DrawDebugSphere(GetWorld(), Location, 12.f, 12, FColor::Green, false, 10.f);
  92.         }
  93.     }
  94.     */
  95. }
  96.  
  97. void AEnemy::ClearPatrolTimer()
  98. {
  99.     GetWorldTimerManager().ClearTimer(PatrolTimer);
  100. }
  101.  
  102. void AEnemy::PawnSeen(APawn* SeenPawn)
  103. {
  104.     const bool bShouldChaseTarget =
  105.         EnemyState != EEnemyState::EES_Dead &&
  106.         EnemyState != EEnemyState::EES_Chasing &&
  107.         EnemyState < EEnemyState::EES_Attacking &&
  108.         SeenPawn->ActorHasTag(FName("SlashCharacter"));
  109.  
  110.     if (bShouldChaseTarget)
  111.     {
  112.         CombatTarget = SeenPawn;
  113.         ClearPatrolTimer();
  114.         ChaseTarget();
  115.     }
  116. }
  117.  
  118. void AEnemy::Die()
  119. {
  120.     UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
  121.     if (AnimInstance && DeathMontage)
  122.     {
  123.         AnimInstance->Montage_Play(DeathMontage);
  124.  
  125.         const int32 Selection = FMath::RandRange(0, 4);
  126.         FName SectionName = FName();
  127.         switch (Selection)
  128.         {
  129.         case 0:
  130.             SectionName = FName("Death1");
  131.             DeathPose = EDeathPose::EDP_Death1;
  132.             break;
  133.         case 1:
  134.             SectionName = FName("Death2");
  135.             DeathPose = EDeathPose::EDP_Death2;
  136.             break;
  137.         case 2:
  138.             SectionName = FName("Death3");
  139.             DeathPose = EDeathPose::EDP_Death3;
  140.             break;
  141.         case 3:
  142.             SectionName = FName("Death4");
  143.             DeathPose = EDeathPose::EDP_Death4;
  144.             break;
  145.         case 4:
  146.             SectionName = FName("Death5");
  147.             DeathPose = EDeathPose::EDP_Death5;
  148.             break;
  149.         default:
  150.             break;
  151.         }
  152.  
  153.         AnimInstance->Montage_JumpToSection(SectionName, DeathMontage);
  154.     }
  155.  
  156.     GetCapsuleComponent()->SetCollisionEnabled(ECollisionEnabled::NoCollision);
  157.     SetLifeSpan(20.f);
  158.  
  159.     if (HealthBarWidget)
  160.     {
  161.         HealthBarWidget->SetVisibility(false);
  162.     }
  163. }
  164.  
  165. bool AEnemy::InTargetRange(AActor* Target, double Radius)
  166. {
  167.     if (Target == nullptr) return false;
  168.     const double DistanceToTarget = (Target->GetActorLocation() - GetActorLocation()).Size();
  169.     //DRAW_SPHERE_SingleFrame(GetActorLocation());
  170.     //DRAW_SPHERE_SingleFrame(Target->GetActorLocation());
  171.     return DistanceToTarget <= Radius;
  172. }
  173.  
  174. void AEnemy::MoveToTarget(AActor* Target)
  175. {
  176.     if (EnemyController == nullptr || Target == nullptr) return;
  177.  
  178.     FAIMoveRequest MoveRequest;
  179.     MoveRequest.SetGoalActor(Target);
  180.     MoveRequest.SetAcceptanceRadius(50.f);
  181.     EnemyController->MoveTo(MoveRequest);
  182. }
  183.  
  184.  
  185.  
  186. AActor* AEnemy::ChoosePatrolTarget()
  187. {
  188.  
  189.     TArray<AActor*> ValitdTargets;
  190.     for (AActor* Target : PatrolTargets)
  191.     {
  192.         if (Target != PatrolTarget)
  193.         {
  194.             ValitdTargets.AddUnique(Target);
  195.         }
  196.     }
  197.  
  198.     const int32 NumPatrolTargets = ValitdTargets.Num();
  199.     if (NumPatrolTargets > 0)
  200.     {
  201.         const int32 TargetSelecection = FMath::RandRange(0, NumPatrolTargets - 1);
  202.         return ValitdTargets[TargetSelecection];
  203.     }
  204.     return nullptr;
  205. }
  206.  
  207. void AEnemy::Attack()
  208. {
  209.     Super::Attack();
  210.  
  211.     PlayAttackMontage();
  212. }
  213.  
  214. void AEnemy::PlayAttackMontage()
  215. {
  216.     Super::PlayAttackMontage();
  217.  
  218.     UAnimInstance* AnimInstance = GetMesh()->GetAnimInstance();
  219.     if (AnimInstance && AttackMontage)
  220.     {
  221.         AnimInstance->Montage_Play(AttackMontage);
  222.         const int32 Selection = FMath::RandRange(0, 2);
  223.         FName SlectionName = FName();
  224.         switch (Selection)
  225.         {
  226.         case 0:
  227.             SlectionName = FName("Attack1");
  228.             break;
  229.         case 1:
  230.             SlectionName = FName("Attack2");
  231.             break;
  232.         default:
  233.             break;
  234.         }
  235.         AnimInstance->Montage_JumpToSection(SlectionName, AttackMontage);
  236.     }
  237. }
  238.  
  239. void AEnemy::Tick(float DeltaTime)
  240. {
  241.     Super::Tick(DeltaTime);
  242.  
  243.     if (EnemyState > EEnemyState::EES_Patrolling)
  244.     {
  245.         CheckCombatTarget();
  246.     }
  247.     else
  248.     {
  249.         CheckPatrolTarget();
  250.     }
  251.    
  252.    
  253.     /*
  254.     if (PatrolTarget && EnemyController)
  255.     {
  256.         if (InTargetRange(PatrolTarget, PatrollRadius))
  257.         {
  258.             TArray<AActor*> ValitdTargets;
  259.             for (AActor* Target : PatrolTargets)
  260.             {
  261.                 if (Target != PatrolTarget)
  262.                 {
  263.                     ValitdTargets.AddUnique(Target);
  264.                 }
  265.             }
  266.  
  267.             const int32 NumPatrolTargets = PatrolTargets.Num();
  268.             if (NumPatrolTargets > 0)
  269.             {
  270.                 const int32 TargetSelecection = FMath::RandRange(0, NumPatrolTargets - 1);
  271.                 AActor* Target = ValitdTargets[TargetSelecection];
  272.                 PatrolTarget = Target;
  273.  
  274.                 FAIMoveRequest MoveRequest;
  275.                 MoveRequest.SetGoalActor(PatrolTarget);
  276.                 MoveRequest.SetAcceptanceRadius(15.f);
  277.                 EnemyController->MoveTo(MoveRequest);
  278.             }
  279.         }
  280.     }
  281.     */
  282. }
  283.  
  284. void AEnemy::CheckPatrolTarget()
  285. {
  286.     if (InTargetRange(PatrolTarget, PatrollRadius))
  287.     {
  288.         PatrolTarget = ChoosePatrolTarget();
  289.         //MoveToTarget(PatrolTarget);
  290.  
  291.         const int32 PatrolWaitTime = FMath::RandRange(WaitMaxMin.X, WaitMaxMin.Y);
  292.  
  293.         GetWorldTimerManager().SetTimer(PatrolTimer, this, &AEnemy::PatrolTimerFinished, PatrolWaitTime);
  294.     }
  295. }
  296.  
  297. void AEnemy::HideHealthBar()
  298. {
  299.     if (HealthBarWidget)
  300.     {
  301.         HealthBarWidget->SetVisibility(false);
  302.     }
  303. }
  304.  
  305. void AEnemy::ShowHealthBar()
  306. {
  307.     if (HealthBarWidget)
  308.     {
  309.         HealthBarWidget->SetVisibility(true);
  310.     }
  311. }
  312.  
  313. void AEnemy::LoosInterest()
  314. {
  315.     CombatTarget = nullptr;
  316.     HideHealthBar();
  317. }
  318.  
  319. void AEnemy::StartPatrolling()
  320. {
  321.     EnemyState = EEnemyState::EES_Patrolling;
  322.     GetCharacterMovement()->MaxWalkSpeed = PatrollingSpeed;
  323.     MoveToTarget(PatrolTarget);
  324.     UE_LOG(LogTemp, Warning, TEXT("Loos intrest"));
  325. }
  326.  
  327. void AEnemy::ChaseTarget()
  328. {
  329.     //Outside attack range, chase character
  330.     EnemyState = EEnemyState::EES_Chasing;
  331.     GetCharacterMovement()->MaxWalkSpeed = chasingSpeed;
  332.     MoveToTarget(CombatTarget);
  333.     UE_LOG(LogTemp, Warning, TEXT("Chase player"));
  334. }
  335.  
  336. bool AEnemy::IsOutsideCombatRadius()
  337. {
  338.     return !InTargetRange(CombatTarget, CombatRadius);
  339. }
  340.  
  341. bool AEnemy::IsOutsideAttackRadius()
  342. {
  343.     return !InTargetRange(CombatTarget, CombatRadius);
  344. }
  345.  
  346. bool AEnemy::IsInsideAttackRadius()
  347. {
  348.     return InTargetRange(CombatTarget, AttackRadius);
  349. }
  350.  
  351. bool AEnemy::IsChasing()
  352. {
  353.     return EnemyState == EEnemyState::EES_Chasing;
  354. }
  355.  
  356. bool AEnemy::IsAttacking()
  357. {
  358.     return EnemyState == EEnemyState::EES_Attacking;
  359. }
  360.  
  361.  
  362.  
  363. void AEnemy::StartAttackTimer()
  364. {
  365.     EnemyState = EEnemyState::EES_Attacking;
  366.     const float AttackTime = FMath::RandRange(AttackMinMaxTime.X,AttackMinMaxTime.Y);
  367.     GetWorldTimerManager().SetTimer(AttackTimer, this, &AEnemy::Attack, AttackTime);
  368. }
  369.  
  370. void AEnemy::CheckCombatTarget()
  371. {
  372.     if (IsOutsideCombatRadius())
  373.     {
  374.         LoosInterest();
  375.         StartPatrolling();
  376.     }
  377.     else if (IsOutsideAttackRadius() && !IsChasing())
  378.     {
  379.         ChaseTarget();
  380.     }
  381.     else if (IsInsideAttackRadius() && !IsAttacking())
  382.     {
  383.         StartAttackTimer();
  384.         /*
  385.         //Inside attacking range, attack charechter
  386.         EnemyState = EEnemyState::EES_Attacking;
  387.        
  388.         Attack();
  389.         */
  390.         UE_LOG(LogTemp, Warning, TEXT("Attacking"));
  391.  
  392.     }
  393. }
  394.  
  395. void AEnemy::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
  396. {
  397.     Super::SetupPlayerInputComponent(PlayerInputComponent);
  398. }
  399.  
  400. void AEnemy::GetHit_Implementation(const FVector& ImpactPoint)
  401. {
  402.     //DRAW_SPHERE_COLOR(ImpactPoint, FColor::Orange);
  403.    
  404.     if (HealthBarWidget)
  405.     {
  406.         HealthBarWidget->SetVisibility(true);
  407.     }
  408.  
  409.     if (Attibutes && Attibutes->IsAlive())
  410.     {
  411.         DirectionalHitReact(ImpactPoint);
  412.     }
  413.     else
  414.     {
  415.         Die();
  416.     }
  417.  
  418.     if (HitSound)
  419.     {
  420.         UGameplayStatics::PlaySoundAtLocation
  421.         (
  422.             this,
  423.             HitSound,
  424.             ImpactPoint
  425.         );
  426.     }
  427.  
  428.     if (HitParticles)
  429.     {
  430.         UGameplayStatics::SpawnEmitterAtLocation
  431.         (
  432.             GetWorld(),
  433.             HitParticles,
  434.             ImpactPoint
  435.         );
  436.     }
  437. }
  438.  
  439. float AEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
  440. {
  441.     //UE_LOG(LogTemp, Warning, TEXT("Attacking %s"), DamageCauser->GetFName());
  442.     if (Attibutes && HealthBarWidget)
  443.     {
  444.         Attibutes->ReceiveDamage(DamageAmount);
  445.         HealthBarWidget->SetHealthPercent(Attibutes->GetHealthPercent());
  446.     }
  447.     CombatTarget = EventInstigator->GetPawn();
  448.     EnemyState = EEnemyState::EES_Chasing;
  449.     GetCharacterMovement()->MaxWalkSpeed = 300.f;
  450.     MoveToTarget(CombatTarget);
  451.     return DamageAmount;
  452. }
  453.  
  454. void AEnemy::Destroyed()
  455. {
  456.     if (EquippedWeapon)
  457.     {
  458.         EquippedWeapon->Destroy();
  459.     }
  460. }
  461.  
  462.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement