Update Characters to Use Built-in TakeDamage Function

This commit is contained in:
Philip W 2023-10-08 20:09:31 +01:00
parent 8a8421c03f
commit c58c400d43
8 changed files with 155 additions and 177 deletions

View File

@ -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<AAI_CompanionController>(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<UCharacterMovementComponent>(GetMovementComponent()))
{
CharacterComp->StopMovementImmediately();
CharacterComp->DisableMovement();
CharacterComp->SetComponentTickEnabled(false);
}
SetLifeSpan(30.0f);
}
return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
}
void AAICharacter::SetupStimuliSourceComponent()
{
StimuliSourceComponent = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(TEXT("Stimuli Source Component"));
if (IsValid(StimuliSourceComponent))
{
StimuliSourceComponent->RegisterForSense(TSubclassOf<UAISense_Sight>());
StimuliSourceComponent->RegisterWithPerceptionSystem();
}
}

View File

@ -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;
};

View File

@ -3,12 +3,6 @@
#include "CompanionCharacter.h" #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 // Sets default values
ACompanionCharacter::ACompanionCharacter() ACompanionCharacter::ACompanionCharacter()
@ -21,6 +15,7 @@ ACompanionCharacter::ACompanionCharacter()
void ACompanionCharacter::BeginPlay() void ACompanionCharacter::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
CharacterName = "Companion";
} }
// Called every frame // Called every frame
@ -28,60 +23,3 @@ void ACompanionCharacter::Tick(float DeltaTime)
{ {
Super::Tick(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<AAI_CompanionController>(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<UCharacterMovementComponent>(GetMovementComponent()))
{
CharacterComp->StopMovementImmediately();
CharacterComp->DisableMovement();
CharacterComp->SetComponentTickEnabled(false);
}
SetLifeSpan(30.0f);
}
}
void ACompanionCharacter::SetupStimuliSourceComponent()
{
StimuliSourceComponent = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(TEXT("Stimuli Source Component"));
if (IsValid(StimuliSourceComponent))
{
StimuliSourceComponent->RegisterForSense(TSubclassOf<UAISense_Sight>());
StimuliSourceComponent->RegisterWithPerceptionSystem();
}
}

View File

@ -3,12 +3,13 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "AICharacter.h"
#include "BehaviorTree/BehaviorTree.h" #include "BehaviorTree/BehaviorTree.h"
#include "GameFramework/Character.h" #include "GameFramework/Character.h"
#include "CompanionCharacter.generated.h" #include "CompanionCharacter.generated.h"
UCLASS() UCLASS()
class ENDLESSVENDETTA_API ACompanionCharacter : public ACharacter class ENDLESSVENDETTA_API ACompanionCharacter : public AAICharacter
{ {
GENERATED_BODY() GENERATED_BODY()
@ -16,33 +17,11 @@ public:
// Sets default values for this character's properties // Sets default values for this character's properties
ACompanionCharacter(); 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: protected:
// Called when the game starts or when spawned // Called when the game starts or when spawned
virtual void BeginPlay() override; virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI")
UBehaviorTree* BehaviorTree;
public: public:
// Called every frame // Called every frame
virtual void Tick(float DeltaTime) override; 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();
}; };

View File

@ -3,12 +3,6 @@
#include "EnemyCharacter.h" #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; class UAISense_Sight;
// Sets default values // 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. // 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; PrimaryActorTick.bCanEverTick = true;
SetupStimuliSourceComponent();
} }
// Called when the game starts or when spawned // Called when the game starts or when spawned
void AEnemyCharacter::BeginPlay() void AEnemyCharacter::BeginPlay()
{ {
Super::BeginPlay(); Super::BeginPlay();
CharacterName = "Enemy";
} }
// Called every frame // Called every frame
@ -30,60 +24,3 @@ void AEnemyCharacter::Tick(float DeltaTime)
{ {
Super::Tick(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<AAI_EnemyController>(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<UCharacterMovementComponent>(GetMovementComponent()))
{
CharacterComp->StopMovementImmediately();
CharacterComp->DisableMovement();
CharacterComp->SetComponentTickEnabled(false);
}
SetLifeSpan(30.0f);
}
}
void AEnemyCharacter::SetupStimuliSourceComponent()
{
StimuliSourceComponent = CreateDefaultSubobject<UAIPerceptionStimuliSourceComponent>(TEXT("Stimuli Source Component"));
if (IsValid(StimuliSourceComponent))
{
StimuliSourceComponent->RegisterForSense(TSubclassOf<UAISense_Sight>());
StimuliSourceComponent->RegisterWithPerceptionSystem();
}
}

View File

@ -3,12 +3,13 @@
#pragma once #pragma once
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "AICharacter.h"
#include "BehaviorTree/BehaviorTree.h" #include "BehaviorTree/BehaviorTree.h"
#include "GameFramework/Character.h" #include "GameFramework/Character.h"
#include "EnemyCharacter.generated.h" #include "EnemyCharacter.generated.h"
UCLASS() UCLASS()
class ENDLESSVENDETTA_API AEnemyCharacter : public ACharacter class ENDLESSVENDETTA_API AEnemyCharacter : public AAICharacter
{ {
GENERATED_BODY() GENERATED_BODY()
@ -16,34 +17,11 @@ public:
// Sets default values for this character's properties // Sets default values for this character's properties
AEnemyCharacter(); 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: protected:
// Called when the game starts or when spawned // Called when the game starts or when spawned
virtual void BeginPlay() override; virtual void BeginPlay() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "AI")
UBehaviorTree* BehaviorTree;
public: public:
// Called every frame // Called every frame
virtual void Tick(float DeltaTime) override; 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();
}; };

View File

@ -109,7 +109,7 @@ void AEndlessVendettaCharacter::SetUnCrouch()
UnCrouch(); UnCrouch();
} }
void AEndlessVendettaCharacter::TakeDamage(const float DamageAmount) float AEndlessVendettaCharacter::TakeDamage(const float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{ {
CurrentHealth -= DamageAmount; CurrentHealth -= DamageAmount;
if (CurrentHealth <= 0) if (CurrentHealth <= 0)
@ -117,6 +117,8 @@ void AEndlessVendettaCharacter::TakeDamage(const float DamageAmount)
CurrentHealth = 0; CurrentHealth = 0;
UE_LOG(LogTemp, Warning, TEXT("Player is dead")); UE_LOG(LogTemp, Warning, TEXT("Player is dead"));
} }
return Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
} }
void AEndlessVendettaCharacter::ToggleRecon() void AEndlessVendettaCharacter::ToggleRecon()

View File

@ -74,7 +74,7 @@ public:
float MaxHealth = 100.0f; float MaxHealth = 100.0f;
UPROPERTY(EditDefaultsOnly, Category = "Stats") UPROPERTY(EditDefaultsOnly, Category = "Stats")
float DefaultHealth = 100.0f; float DefaultHealth = 100.0f;
protected: protected:
virtual void BeginPlay() override; virtual void BeginPlay() override;
@ -144,5 +144,5 @@ public:
UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; } UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }
UFUNCTION(BlueprintCallable, Category = "Damage Control") UFUNCTION(BlueprintCallable, Category = "Damage Control")
void TakeDamage(float DamageAmount); virtual float TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
}; };