super-duper-spoon/Source/Shooter/Enemy.h

263 lines
8.7 KiB
C++

// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "BulletHitInterface.h"
#include "GameFramework/Character.h"
#include "Enemy.generated.h"
class UParticleSystem;
class USoundCue;
class UAnimMontage;
class UBehaviorTree;
class AEnemyController;
class USphereComponent;
class UBoxComponent;
class AShooterCharacter;
UCLASS()
class SHOOTER_API AEnemy : public ACharacter, public IBulletHitInterface
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AEnemy();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
UFUNCTION(BlueprintNativeEvent)
void ShowHealthBar();
void ShowHealthBar_Implementation();
UFUNCTION(BlueprintImplementableEvent)
void HideHealthBar();
void Die();
void PlayHitMontage(FName Section, float PlayRate = 1.0f);
void ResetHitReactTimer();
UFUNCTION(BlueprintCallable)
void StoreHitNumber(UUserWidget* HitNumber, FVector Location);
UFUNCTION()
void DestroyHitNumber(UUserWidget* HitNumber);
void UpdateHitNumbers();
UFUNCTION(BlueprintCallable)
float GetHealth() const { return Health; }
UFUNCTION(BlueprintCallable)
float GetMaxHealth() const { return MaxHealth; }
/** Called when something overlaps with the agro sphere */
UFUNCTION()
void AgroSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION(BlueprintCallable)
void SetStunned(bool Stunned);
UFUNCTION()
void CombatRangeOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION()
void CombatRangeEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
UFUNCTION(BlueprintCallable)
void PlayAttackMontage(FName Section, float PlayRate = 1.0f);
UFUNCTION(BlueprintPure)
FName GetAttackSectionName() const;
UFUNCTION()
void OnLeftWeaponOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
UFUNCTION()
void OnRightWeaponOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep,
const FHitResult& SweepResult);
// Activate/Deactivate collision for weapon boxes
UFUNCTION(BlueprintCallable)
void ActivateLeftWeapon();
UFUNCTION(BlueprintCallable)
void DeactivateLeftWeapon();
UFUNCTION(BlueprintCallable)
void ActivateRightWeapon();
UFUNCTION(BlueprintCallable)
void DeactivateRightWeapon();
void DoDamage(AShooterCharacter* Victim);
void SpawnBlood(AShooterCharacter* Victim, FName WeaponSocket);
// Attemp to stun character
void StunCharacter(AShooterCharacter* Victim);
void ResetCanAttack();
UFUNCTION(BlueprintCallable)
void FinishDeath();
void DestroyEnemy();
private:
/** Particles to spawn when hit by bullets */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
UParticleSystem* ImpactParticles;
/** Sound to play when hit by bullets */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
USoundCue* ImpactSound;
/** Current health */
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Combat, meta = (AllowPrivateAccess = true))
float Health;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float MaxHealth;
/** Name of the head bone */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
FString HeadBone;
/** Time to display health bar once shot */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float HealthBarDisplayTime;
FTimerHandle HealthBarTimer;
/** Montage containing Hit and Death animations */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
UAnimMontage* HitMontage;
FTimerHandle HitReactTimer;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float HitReactTimeMin;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float HitReactTimeMax;
bool bCanHitReact;
/** Map to store HitNumber widgets and their hit locations */
UPROPERTY(VisibleAnywhere, Category = Combat, meta = (AllowPrivateAccess = true))
TMap<UUserWidget*, FVector> HitNumbers;
/** Time before a hit number is removed from the screen */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float HitNumberDestroyTime;
/** Behavior tree for the AI Character */
UPROPERTY(EditAnywhere, Category = "Behavior Tree", meta = (AllowPrivateAccess = true))
UBehaviorTree* BehaviorTree;
/** Point for the enemy to move to */
UPROPERTY(EditAnywhere, Category = "Behavior Tree", meta = (AllowPrivateAccess = true, MakeEditWidget = true))
FVector PatrolPoint;
/** 2nd Point for the enemy to move to */
UPROPERTY(EditAnywhere, Category = "Behavior Tree", meta = (AllowPrivateAccess = true, MakeEditWidget = true))
FVector PatrolPoint2;
AEnemyController* EnemyController;
/** Overlap sphere for when the enemy becomes hostile */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
USphereComponent* AgroSphere;
/** True when playing the get hit animation */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
bool bStunned;
/** Chance of being stunned. 0: no stun chance, 1: 100% stun chance */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float StunChance;
/** True when in attack rangel; time to attack */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
bool bInAttackRange;
/** Overlap sphere for attack range */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
USphereComponent* CombatRangeSphere;
/** Montage containing different attacks */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
UAnimMontage* AttackMontage;
/** The 4 attack montage section names */
FName AttackLFast;
FName AttackRFast;
FName AttackL;
FName AttackR;
/** Collision volume for the left weapon */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
UBoxComponent* LeftWeaponCollision;
/** Collision volume for the right weapon */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
UBoxComponent* RightWeaponCollision;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float BaseDamage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
FName LeftWeaponSocket;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
FName RightWeaponSocket;
/** True when Enemy can attack */
UPROPERTY(VisibleAnywhere, Category = Combat, meta = (AllowPrivateAccess = true))
bool bCanAttack;
FTimerHandle AttackWaitTimer;
/** Min wait time between attacks */
UPROPERTY(EditAnywhere, Category = Combat, meta = (AllowPrivateAccess = true))
float AttackWaitTime;
/** Death anim montage */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
UAnimMontage* DeathMontage;
bool bDying;
FTimerHandle DeathTimer;
/** Time after death until Destroy */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Combat, meta = (AllowPrivateAccess = true))
float DeathTime;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
virtual void BulletHit_Implementation(FHitResult HitResult, AActor* Shooter, AController* ShooterController) override;
virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
FORCEINLINE FString GetHeadBone() const { return HeadBone; }
UFUNCTION(BlueprintImplementableEvent)
void ShowHitNumber(int32 Damage, FVector HitLocation, bool bHeadshot);
FORCEINLINE UBehaviorTree* GetBehaviorTree() const { return BehaviorTree; }
};