Implemented hitboxes and health system for ennemies
This commit is contained in:
parent
8a385a3f86
commit
879fb83f0e
62
Source/LegumeMix/Private/Player/LMHealthComponent.cpp
Normal file
62
Source/LegumeMix/Private/Player/LMHealthComponent.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Player/LMHealthComponent.h"
|
||||||
|
|
||||||
|
#include "Player/LMHitBox.h"
|
||||||
|
|
||||||
|
|
||||||
|
ULMHealthComponent::ULMHealthComponent()
|
||||||
|
{
|
||||||
|
PrimaryComponentTick.bCanEverTick = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULMHealthComponent::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
if (bMaxHealthOnStart)
|
||||||
|
Health = MaxHealth;
|
||||||
|
|
||||||
|
RegisterHitBoxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULMHealthComponent::RegisterHitBoxes()
|
||||||
|
{
|
||||||
|
GetOwner()->GetComponents<ULMHitBox>(HitBoxes);
|
||||||
|
for (const auto HitBox : HitBoxes)
|
||||||
|
{
|
||||||
|
HitBox->OnHitBoxHit.AddUniqueDynamic(this, &ULMHealthComponent::HitBoxHit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULMHealthComponent::TakeDamage_Implementation(const float Damage)
|
||||||
|
{
|
||||||
|
if (Damage <= 0.0f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnHit(Damage);
|
||||||
|
OnHealthChanged.Broadcast(Health, Damage);
|
||||||
|
|
||||||
|
if (Health <= 0.0f)
|
||||||
|
Kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULMHealthComponent::OnHit_Implementation(const float Damage)
|
||||||
|
{
|
||||||
|
Health = FMath::Clamp(Health - Damage, 0.0f, MaxHealth);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ULMHealthComponent::Kill()
|
||||||
|
{
|
||||||
|
OnKill();
|
||||||
|
OnDeath.Broadcast();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULMHealthComponent::HitBoxHit(ULMHitBox* HitBox, float Damage)
|
||||||
|
{
|
||||||
|
TakeDamage(Damage);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
38
Source/LegumeMix/Private/Player/LMHitBox.cpp
Normal file
38
Source/LegumeMix/Private/Player/LMHitBox.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
|
||||||
|
#include "Player/LMHitBox.h"
|
||||||
|
|
||||||
|
#include "Player/LMBulletInfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
ULMHitBox::ULMHitBox()
|
||||||
|
{
|
||||||
|
PrimaryComponentTick.bCanEverTick = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ULMHitBox::OnHit(const FLMBulletInfo& BulletInfo)
|
||||||
|
{
|
||||||
|
const float Damage = BulletInfo.Damage;
|
||||||
|
const double Distance = FVector::Distance(BulletInfo.Origin, GetComponentLocation());
|
||||||
|
|
||||||
|
const float TotalDamage = CalculateDamage(Damage, Distance, BulletInfo.Falloff, BulletInfo.MaxDistance);
|
||||||
|
OnHitBoxHit.Broadcast(this, TotalDamage);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ULMHitBox::CalculateDamage_Implementation(const float Damage, const float Distance, UCurveFloat* Falloff, const float MaxDistance)
|
||||||
|
{
|
||||||
|
const float Absorption = Damage - FlatDamageAbsorption;
|
||||||
|
const float FalloffModifier = Falloff->GetFloatValue(Distance / MaxDistance);
|
||||||
|
UE_LOG(LogTemp, Display, TEXT("Falloff : %f"), FalloffModifier);
|
||||||
|
|
||||||
|
const float FalloffDamage = Absorption * FalloffModifier;
|
||||||
|
UE_LOG(LogTemp, Display, TEXT("Damage With Fallof: %f"), FalloffDamage)
|
||||||
|
|
||||||
|
const float FinalDamage = FalloffDamage * DamageModifier;
|
||||||
|
UE_LOG(LogTemp, Display, TEXT("Final Damages: %f"), FinalDamage)
|
||||||
|
|
||||||
|
return FinalDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
|||||||
#include "Camera/CameraComponent.h"
|
#include "Camera/CameraComponent.h"
|
||||||
#include "Ammo/LMAmmo.h"
|
#include "Ammo/LMAmmo.h"
|
||||||
#include "Player/LMBulletInfo.h"
|
#include "Player/LMBulletInfo.h"
|
||||||
|
#include "Player/LMHitBox.h"
|
||||||
#include "Weapon/LMWeaponManager.h"
|
#include "Weapon/LMWeaponManager.h"
|
||||||
|
|
||||||
ALMPlayer::ALMPlayer()
|
ALMPlayer::ALMPlayer()
|
||||||
@ -84,6 +85,19 @@ void ALMPlayer::FireBullets(const FLMBulletInfo Settings)
|
|||||||
|
|
||||||
const bool HasHit = GetWorld()->LineTraceSingleByChannel(OutHit, Settings.Origin, EndLocation, ECC_Camera);
|
const bool HasHit = GetWorld()->LineTraceSingleByChannel(OutHit, Settings.Origin, EndLocation, ECC_Camera);
|
||||||
DrawDebugLineTraceSingle(GetWorld(), Settings.Origin, EndLocation, EDrawDebugTrace::ForDuration, HasHit, OutHit, FColor::Green, FColor::Red, 2.f);
|
DrawDebugLineTraceSingle(GetWorld(), Settings.Origin, EndLocation, EDrawDebugTrace::ForDuration, HasHit, OutHit, FColor::Green, FColor::Red, 2.f);
|
||||||
|
|
||||||
|
if (!HasHit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
FString Hit = FString::Printf(TEXT("Hit %s"), *OutHit.Component->GetName());
|
||||||
|
// GEngine->AddOnScreenDebugMessage(INDEX_NONE, 2.f, FColor::Red, Hit);
|
||||||
|
UE_LOG(LogTemp, Display, TEXT("%s"), *Hit);
|
||||||
|
|
||||||
|
if (ULMHitBox* HitBox = Cast<ULMHitBox>(OutHit.Component))
|
||||||
|
{
|
||||||
|
UE_LOG(LogTemp, Warning, TEXT("Hit Hitbox"));
|
||||||
|
HitBox->OnHit(Settings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
103
Source/LegumeMix/Public/Player/LMHealthComponent.h
Normal file
103
Source/LegumeMix/Public/Player/LMHealthComponent.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "LMHealthComponent.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
class ULMHitBox;
|
||||||
|
|
||||||
|
UCLASS(Blueprintable, ClassGroup=(Legumix), meta=(BlueprintSpawnableComponent))
|
||||||
|
class LEGUMEMIX_API ULMHealthComponent : public UActorComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnHealthChangedSignature, float, Health, float, Damage);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeathSignature);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ULMHealthComponent();
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
void Kill();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Applies an amount of damage to the component.
|
||||||
|
* @param Damage The damage to apply the Health to.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category=Legumix)
|
||||||
|
void TakeDamage(float Damage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called automatically when the component hits zero health.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category=Legumix)
|
||||||
|
void OnKill();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register all hitboxes associated with this component owner.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category=Legumix, CallInEditor)
|
||||||
|
void RegisterHitBoxes();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called automatically when a hitbox is hit.
|
||||||
|
* @param HitBox The hitbox that was hit.
|
||||||
|
* @param Damage The damage received by the hitbox.
|
||||||
|
*/
|
||||||
|
UFUNCTION()
|
||||||
|
void HitBoxHit(ULMHitBox* HitBox, float Damage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies the amount of damage received to the component.
|
||||||
|
*
|
||||||
|
* Called automatically when one of this component's LMHitBox is hit.
|
||||||
|
* @param Damage The damage received.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category=Legumix)
|
||||||
|
void OnHit(float Damage);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an amount of health to the character.
|
||||||
|
* @param AddedHealth The amount of health to add.
|
||||||
|
* @param NoLimits If sets, ignore the component's MaxHealth value.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category=Legumix, meta=(Keywords = "Refill, Health"))
|
||||||
|
void AddHealth(const float AddedHealth, const bool NoLimits = false) { Health = FMath::Clamp(Health + AddedHealth, 0.0f, NoLimits ? INT_MAX : MaxHealth); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Completely refill the health of the component.
|
||||||
|
*/
|
||||||
|
UFUNCTION(BlueprintCallable, Category=Legumix, meta=(Keywords = "Refill, Health"))
|
||||||
|
void FillHealth() { Health = MaxHealth; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Delegate called when this component receives damages. */
|
||||||
|
UPROPERTY(BlueprintAssignable, Category=Legumix)
|
||||||
|
FOnHealthChangedSignature OnHealthChanged;
|
||||||
|
|
||||||
|
/** Delegate called when this component is killed, aka. Health reaches 0.*/
|
||||||
|
UPROPERTY(BlueprintAssignable, Category=Legumix)
|
||||||
|
FOnDeathSignature OnDeath;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* If set, the Health will be initialized to MaxHealth.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Legumix, meta=(AllowPrivateAccess=true))
|
||||||
|
bool bMaxHealthOnStart = true;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Legumix, meta=(AllowPrivateAccess=true, ClampMin=0, UIMin=0))
|
||||||
|
float Health = 100.f;
|
||||||
|
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Legumix, meta=(AllowPrivateAccess=true, ClampMin=0, UIMin=0, UIMax=1000))
|
||||||
|
float MaxHealth = 100.f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of all associated LMHitboxes.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Legumix, meta=(AllowPrivateAccess=true))
|
||||||
|
TArray<TObjectPtr<ULMHitBox>> HitBoxes;
|
||||||
|
};
|
46
Source/LegumeMix/Public/Player/LMHitBox.h
Normal file
46
Source/LegumeMix/Public/Player/LMHitBox.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Fill out your copyright notice in the Description page of Project Settings.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "LMBulletInfo.h"
|
||||||
|
#include "Components/CapsuleComponent.h"
|
||||||
|
#include "LMHitBox.generated.h"
|
||||||
|
|
||||||
|
|
||||||
|
UCLASS(Blueprintable, ClassGroup=(Legumix), meta=(BlueprintSpawnableComponent))
|
||||||
|
class LEGUMEMIX_API ULMHitBox : public UCapsuleComponent
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FHitBoxHitSignature, ULMHitBox*, HitBox, float, Damage);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ULMHitBox();
|
||||||
|
void OnHit(const FLMBulletInfo& BulletInfo);
|
||||||
|
|
||||||
|
public:
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category=Legumix)
|
||||||
|
float CalculateDamage(float Damage, float Distance, UCurveFloat* Falloff, float MaxDistance);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Delegate called when the hitbox is hit.
|
||||||
|
* @param HitBox: The Hitbox that was hit.
|
||||||
|
* @param Damage: The amount of damage done to the hitbox.
|
||||||
|
*/
|
||||||
|
UPROPERTY(BlueprintAssignable, BlueprintCallable)
|
||||||
|
FHitBoxHitSignature OnHitBoxHit;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* A value to multiply the damage received by.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Legumix, meta=(AllowPrivateAccess=true))
|
||||||
|
float DamageModifier = 1.0f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Amount of damage removed when hit.
|
||||||
|
*/
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Legumix, meta=(AllowPrivateAccess=true, ClampMin=0.0f, UIMin=0.0f))
|
||||||
|
float FlatDamageAbsorption = 0.f;
|
||||||
|
};
|
Reference in New Issue
Block a user