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 "Ammo/LMAmmo.h"
|
||||
#include "Player/LMBulletInfo.h"
|
||||
#include "Player/LMHitBox.h"
|
||||
#include "Weapon/LMWeaponManager.h"
|
||||
|
||||
ALMPlayer::ALMPlayer()
|
||||
@ -84,6 +85,19 @@ void ALMPlayer::FireBullets(const FLMBulletInfo Settings)
|
||||
|
||||
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);
|
||||
|
||||
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