From c58c400d435e796b36e8ef70f475a4186d662540 Mon Sep 17 00:00:00 2001 From: PHILIP WHITE Date: Sun, 8 Oct 2023 20:09:31 +0100 Subject: [PATCH] Update Characters to Use Built-in TakeDamage Function --- .../Source/EndlessVendetta/AI/AICharacter.cpp | 92 +++++++++++++++++++ .../Source/EndlessVendetta/AI/AICharacter.h | 52 +++++++++++ .../EndlessVendetta/AI/CompanionCharacter.cpp | 64 +------------ .../EndlessVendetta/AI/CompanionCharacter.h | 25 +---- .../EndlessVendetta/AI/EnemyCharacter.cpp | 65 +------------ .../EndlessVendetta/AI/EnemyCharacter.h | 26 +----- .../EndlessVendettaCharacter.cpp | 4 +- .../EndlessVendettaCharacter.h | 4 +- 8 files changed, 155 insertions(+), 177 deletions(-) create mode 100644 EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp create mode 100644 EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp new file mode 100644 index 00000000..e6b4e22d --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.cpp @@ -0,0 +1,92 @@ +// Fill out your copyright notice in the Description page of Project Settings. + + +#include "AICharacter.h" + +#include "AI_CompanionController.h" +#include "Components/CapsuleComponent.h" +#include "Engine/DamageEvents.h" +#include "GameFramework/CharacterMovementComponent.h" +#include "Perception/AIPerceptionStimuliSourceComponent.h" +#include "Perception/AISense_Sight.h" + + +// Sets default values +AAICharacter::AAICharacter() +{ + // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. + PrimaryActorTick.bCanEverTick = true; + SetupStimuliSourceComponent(); +} + +// Called when the game starts or when spawned +void AAICharacter::BeginPlay() +{ + Super::BeginPlay(); + +} + +// Called every frame +void AAICharacter::Tick(float DeltaTime) +{ + Super::Tick(DeltaTime); +} + +// Called to bind functionality to input +void AAICharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) +{ + Super::SetupPlayerInputComponent(PlayerInputComponent); +} + +UBehaviorTree* AAICharacter::GetBehaviorTree() const +{ + return BehaviorTree; +} + +float AAICharacter::TakeDamage(const float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) +{ + CurrentHealth -= DamageAmount; + if (CurrentHealth <= 0) + { + CurrentHealth = 0; + UE_LOG(LogTemp, Display, TEXT("%s is dead"), *CharacterName.ToString()); + + const AAI_CompanionController* AIController = Cast(GetController()); + AIController->GetBrainComponent()->StopLogic(*CharacterName.ToString() + FString(" is dead")); + + //Ragdoll + DetachFromControllerPendingDestroy(); + UCapsuleComponent* CapsuleComp = GetCapsuleComponent(); + CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision); + CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore); + + GetMesh()->SetCollisionProfileName(TEXT("Ragdoll")); + SetActorEnableCollision(true); + + GetMesh()->SetAllBodiesSimulatePhysics(true); + GetMesh()->SetSimulatePhysics(true); + GetMesh()->WakeAllRigidBodies(); + GetMesh()->bBlendPhysics = true; + + if (UCharacterMovementComponent* CharacterComp = Cast(GetMovementComponent())) + { + CharacterComp->StopMovementImmediately(); + CharacterComp->DisableMovement(); + CharacterComp->SetComponentTickEnabled(false); + } + + SetLifeSpan(30.0f); + } + return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); +} + +void AAICharacter::SetupStimuliSourceComponent() +{ + StimuliSourceComponent = CreateDefaultSubobject(TEXT("Stimuli Source Component")); + if (IsValid(StimuliSourceComponent)) + { + StimuliSourceComponent->RegisterForSense(TSubclassOf()); + StimuliSourceComponent->RegisterWithPerceptionSystem(); + } +} + diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h new file mode 100644 index 00000000..9431cbce --- /dev/null +++ b/EndlessVendetta/Source/EndlessVendetta/AI/AICharacter.h @@ -0,0 +1,52 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +#pragma once + +#include "CoreMinimal.h" +#include "BehaviorTree/BehaviorTree.h" +#include "GameFramework/Character.h" +#include "AICharacter.generated.h" + +UCLASS() +class ENDLESSVENDETTA_API AAICharacter : public ACharacter +{ + GENERATED_BODY() + +public: + // Sets default values for this character's properties + AAICharacter(); + + UPROPERTY(EditDefaultsOnly, Category = "Stats") + float CurrentHealth = 100.0f; + UPROPERTY(EditDefaultsOnly, Category = "Stats") + float MaxHealth = 100.0f; + UPROPERTY(EditDefaultsOnly, Category = "Stats") + float DefaultHealth = 100.0f; + + UPROPERTY(EditDefaultsOnly, Category = "Profile") + FName CharacterName = "AI Character"; + +protected: + // Called when the game starts or when spawned + virtual void BeginPlay() override; + + UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI") + UBehaviorTree* BehaviorTree; + + UPROPERTY() + class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent; + void SetupStimuliSourceComponent(); + +public: + // Called every frame + virtual void Tick(float DeltaTime) override; + + // Called to bind functionality to input + virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; + + UFUNCTION(BlueprintCallable, Category = "AI") + UBehaviorTree* GetBehaviorTree() const; + + UFUNCTION(BlueprintCallable, Category = "Damage Control") + virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override; +}; diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.cpp index 73ceb453..197ba5d5 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.cpp @@ -3,12 +3,6 @@ #include "CompanionCharacter.h" -#include "AI_CompanionController.h" -#include "Components/CapsuleComponent.h" -#include "GameFramework/CharacterMovementComponent.h" -#include "Perception/AIPerceptionStimuliSourceComponent.h" -#include "Perception/AISense_Sight.h" - // Sets default values ACompanionCharacter::ACompanionCharacter() @@ -21,6 +15,7 @@ ACompanionCharacter::ACompanionCharacter() void ACompanionCharacter::BeginPlay() { Super::BeginPlay(); + CharacterName = "Companion"; } // Called every frame @@ -28,60 +23,3 @@ void ACompanionCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); } - -// Called to bind functionality to input -void ACompanionCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) -{ - Super::SetupPlayerInputComponent(PlayerInputComponent); -} - -UBehaviorTree* ACompanionCharacter::GetBehaviorTree() const -{ - return BehaviorTree; -} - -void ACompanionCharacter::TakeDamage(const float DamageAmount) -{ - CurrentHealth -= DamageAmount; - if (CurrentHealth <= 0) - { - CurrentHealth = 0; - UE_LOG(LogTemp, Warning, TEXT("Companion is dead")); - - const AAI_CompanionController* AIController = Cast(GetController()); - AIController->GetBrainComponent()->StopLogic("Companion is dead"); - - //Ragdoll - DetachFromControllerPendingDestroy(); - UCapsuleComponent* CapsuleComp = GetCapsuleComponent(); - CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision); - CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore); - - GetMesh()->SetCollisionProfileName(TEXT("Ragdoll")); - SetActorEnableCollision(true); - - GetMesh()->SetAllBodiesSimulatePhysics(true); - GetMesh()->SetSimulatePhysics(true); - GetMesh()->WakeAllRigidBodies(); - GetMesh()->bBlendPhysics = true; - - if (UCharacterMovementComponent* CharacterComp = Cast(GetMovementComponent())) - { - CharacterComp->StopMovementImmediately(); - CharacterComp->DisableMovement(); - CharacterComp->SetComponentTickEnabled(false); - } - - SetLifeSpan(30.0f); - } -} - -void ACompanionCharacter::SetupStimuliSourceComponent() -{ - StimuliSourceComponent = CreateDefaultSubobject(TEXT("Stimuli Source Component")); - if (IsValid(StimuliSourceComponent)) - { - StimuliSourceComponent->RegisterForSense(TSubclassOf()); - StimuliSourceComponent->RegisterWithPerceptionSystem(); - } -} diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.h b/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.h index cc6fccce..a9c0aa23 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.h +++ b/EndlessVendetta/Source/EndlessVendetta/AI/CompanionCharacter.h @@ -3,12 +3,13 @@ #pragma once #include "CoreMinimal.h" +#include "AICharacter.h" #include "BehaviorTree/BehaviorTree.h" #include "GameFramework/Character.h" #include "CompanionCharacter.generated.h" UCLASS() -class ENDLESSVENDETTA_API ACompanionCharacter : public ACharacter +class ENDLESSVENDETTA_API ACompanionCharacter : public AAICharacter { GENERATED_BODY() @@ -16,33 +17,11 @@ public: // Sets default values for this character's properties ACompanionCharacter(); - UPROPERTY(EditDefaultsOnly, Category = "Stats") - float CurrentHealth = 100.0f; - UPROPERTY(EditDefaultsOnly, Category = "Stats") - float MaxHealth = 100.0f; - UPROPERTY(EditDefaultsOnly, Category = "Stats") - float DefaultHealth = 100.0f; - protected: // Called when the game starts or when spawned virtual void BeginPlay() override; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI") - UBehaviorTree* BehaviorTree; public: // Called every frame virtual void Tick(float DeltaTime) override; - - // Called to bind functionality to input - virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; - - UFUNCTION(BlueprintCallable, Category = "AI") - UBehaviorTree* GetBehaviorTree() const; - - UFUNCTION(BlueprintCallable, Category = "Damage Control") - void TakeDamage(float DamageAmount); - -private: - class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent; - void SetupStimuliSourceComponent(); }; diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.cpp b/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.cpp index fa286bc9..72f9fabb 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.cpp @@ -3,12 +3,6 @@ #include "EnemyCharacter.h" -#include "AI_EnemyController.h" -#include "Components/CapsuleComponent.h" -#include "GameFramework/CharacterMovementComponent.h" -#include "Perception/AIPerceptionStimuliSourceComponent.h" -#include "Perception/AISense_Sight.h" - class UAISense_Sight; // Sets default values @@ -16,13 +10,13 @@ AEnemyCharacter::AEnemyCharacter() { // Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it. PrimaryActorTick.bCanEverTick = true; - SetupStimuliSourceComponent(); } // Called when the game starts or when spawned void AEnemyCharacter::BeginPlay() { Super::BeginPlay(); + CharacterName = "Enemy"; } // Called every frame @@ -30,60 +24,3 @@ void AEnemyCharacter::Tick(float DeltaTime) { Super::Tick(DeltaTime); } - -// Called to bind functionality to input -void AEnemyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) -{ - Super::SetupPlayerInputComponent(PlayerInputComponent); -} - -UBehaviorTree* AEnemyCharacter::GetBehaviorTree() const -{ - return BehaviorTree; -} - -void AEnemyCharacter::TakeDamage(const float DamageAmount) -{ - CurrentHealth -= DamageAmount; - if (CurrentHealth <= 0) - { - CurrentHealth = 0; - UE_LOG(LogTemp, Warning, TEXT("Enemy is dead")); - - const AAI_EnemyController* AIController = Cast(GetController()); - AIController->GetBrainComponent()->StopLogic("Enemy is dead"); - - //Ragdoll - DetachFromControllerPendingDestroy(); - UCapsuleComponent* CapsuleComp = GetCapsuleComponent(); - CapsuleComp->SetCollisionEnabled(ECollisionEnabled::NoCollision); - CapsuleComp->SetCollisionResponseToAllChannels(ECR_Ignore); - - GetMesh()->SetCollisionProfileName(TEXT("Ragdoll")); - SetActorEnableCollision(true); - - GetMesh()->SetAllBodiesSimulatePhysics(true); - GetMesh()->SetSimulatePhysics(true); - GetMesh()->WakeAllRigidBodies(); - GetMesh()->bBlendPhysics = true; - - if (UCharacterMovementComponent* CharacterComp = Cast(GetMovementComponent())) - { - CharacterComp->StopMovementImmediately(); - CharacterComp->DisableMovement(); - CharacterComp->SetComponentTickEnabled(false); - } - - SetLifeSpan(30.0f); - } -} - -void AEnemyCharacter::SetupStimuliSourceComponent() -{ - StimuliSourceComponent = CreateDefaultSubobject(TEXT("Stimuli Source Component")); - if (IsValid(StimuliSourceComponent)) - { - StimuliSourceComponent->RegisterForSense(TSubclassOf()); - StimuliSourceComponent->RegisterWithPerceptionSystem(); - } -} diff --git a/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.h b/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.h index 0344fa15..6c6cfebe 100644 --- a/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.h +++ b/EndlessVendetta/Source/EndlessVendetta/AI/EnemyCharacter.h @@ -3,12 +3,13 @@ #pragma once #include "CoreMinimal.h" +#include "AICharacter.h" #include "BehaviorTree/BehaviorTree.h" #include "GameFramework/Character.h" #include "EnemyCharacter.generated.h" UCLASS() -class ENDLESSVENDETTA_API AEnemyCharacter : public ACharacter +class ENDLESSVENDETTA_API AEnemyCharacter : public AAICharacter { GENERATED_BODY() @@ -16,34 +17,11 @@ public: // Sets default values for this character's properties AEnemyCharacter(); - UPROPERTY(EditDefaultsOnly, Category = "Stats") - float CurrentHealth = 100.0f; - UPROPERTY(EditDefaultsOnly, Category = "Stats") - float MaxHealth = 100.0f; - UPROPERTY(EditDefaultsOnly, Category = "Stats") - float DefaultHealth = 100.0f; - protected: // Called when the game starts or when spawned virtual void BeginPlay() override; - UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI") - UBehaviorTree* BehaviorTree; - public: // Called every frame virtual void Tick(float DeltaTime) override; - - // Called to bind functionality to input - virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override; - - UFUNCTION(BlueprintCallable, Category = "AI") - UBehaviorTree* GetBehaviorTree() const; - - UFUNCTION(BlueprintCallable, Category = "Damage Control") - void TakeDamage(float DamageAmount); - -private: - class UAIPerceptionStimuliSourceComponent* StimuliSourceComponent; - void SetupStimuliSourceComponent(); }; diff --git a/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.cpp b/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.cpp index 736a065c..0fd3afde 100644 --- a/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.cpp +++ b/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.cpp @@ -109,7 +109,7 @@ void AEndlessVendettaCharacter::SetUnCrouch() UnCrouch(); } -void AEndlessVendettaCharacter::TakeDamage(const float DamageAmount) +float AEndlessVendettaCharacter::TakeDamage(const float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) { CurrentHealth -= DamageAmount; if (CurrentHealth <= 0) @@ -117,6 +117,8 @@ void AEndlessVendettaCharacter::TakeDamage(const float DamageAmount) CurrentHealth = 0; UE_LOG(LogTemp, Warning, TEXT("Player is dead")); } + + return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser); } void AEndlessVendettaCharacter::ToggleRecon() diff --git a/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.h b/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.h index 758d92c2..e1a503a7 100644 --- a/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.h +++ b/EndlessVendetta/Source/EndlessVendetta/EndlessVendettaCharacter.h @@ -74,7 +74,7 @@ public: float MaxHealth = 100.0f; UPROPERTY(EditDefaultsOnly, Category = "Stats") float DefaultHealth = 100.0f; - + protected: virtual void BeginPlay() override; @@ -144,5 +144,5 @@ public: UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; } UFUNCTION(BlueprintCallable, Category = "Damage Control") - void TakeDamage(float DamageAmount); + virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override; };