관리 메뉴

기억을 위한 기록들

[UE CPP] 체력관리 컴포넌트 (HealthManageComponent) 본문

UnrealEngine/UnrealEngine C++ 관련

[UE CPP] 체력관리 컴포넌트 (HealthManageComponent)

에드윈H 2023. 7. 16. 23:39
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "HealthManageComponent.generated.h"


DECLARE_MULTICAST_DELEGATE_OneParam(FUpdateHealthPoint, int);
DECLARE_MULTICAST_DELEGATE_OneParam(FAddtiveHealthPoint, int);
DECLARE_MULTICAST_DELEGATE_OneParam(FMinusHealthPoint, int);
DECLARE_MULTICAST_DELEGATE(FDeathDelegate);

class FHealthPoint
{
public:
	FHealthPoint()
	{
		MaxHealth = TNumericLimits< uint16 >::Max();
		CurHealth = MaxHealth;
	}
	FHealthPoint(const int newMaxHealth)
		: MaxHealth(newMaxHealth),
		  CurHealth(newMaxHealth)
	{}

	FHealthPoint(const FHealthPoint& rhs)
		: MaxHealth(rhs.MaxHealth),
		  CurHealth(rhs.CurHealth)
	{}

	void	InitData(const int newMaxHealth)
	{
		MaxHealth = newMaxHealth;
		CurHealth = newMaxHealth;
	}

	FORCEINLINE void	ResetHP()
	{
		CurHealth = MaxHealth;
	}

	void	AddHP(const int additiveValue)
	{
		if (MaxHealth < CurHealth + additiveValue)
		{
			CurHealth = MaxHealth;
		}
		else
		{
			CurHealth += additiveValue;
		}

	}

	void	MinHP(const int taragetValue)
	{
		if (CurHealth - taragetValue < MinHealth)
		{
			CurHealth = MinHealth;
		}
		else
		{
			CurHealth -= CurHealth;
		}
	}

	FORCEINLINE bool	IsZero() const {
		return CurHealth == 0;
	}

	uint16  GetMaxHP() const { return MaxHealth; }
	int     GetCurrentHP() const { return CurHealth; }
private:
	uint16 MaxHealth = 0;
	int CurHealth = 0;
	static const int MinHealth = 0;
};

UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class STUDYCPP_API UHealthManageComponent : public UActorComponent
{
	GENERATED_BODY()
public:		
	UHealthManageComponent();
protected:
	
	virtual void BeginPlay() override;

	UFUNCTION(BlueprintCallable, Category = "Manage")
	void		   InitData(const int maxHP);

	void		   InitData(const FHealthPoint& newHPData);

	UFUNCTION(BlueprintCallable, Category="Manage")
	void		   AddHP(const int addtiveHP);

	UFUNCTION(BlueprintCallable, Category = "Manage")
	void		   MinHP(const int minusHP);

	UFUNCTION(BlueprintCallable, Category = "Manage")
	void		   ResetHP();

	UFUNCTION(BlueprintPure, Category = "Manage")
	bool		   IsDead() const;

	UFUNCTION(BlueprintPure, Category = "Manage")
	int			   GetCurrentHP() const;

public:
	FUpdateHealthPoint&	       OnUpdateHealthDelegate() {return UpdateHealthDelegate;}
	FAddtiveHealthPoint&	   OnAddHealthDelegate() {return AddtiveHealthDelegate;}
	FMinusHealthPoint&		   OnMinusHealthDelegate() {return MinusHealthDelegate;}
	FDeathDelegate&			   OnDeathDelegate() {return DeathUpdateDelegate;}

private:
	FUpdateHealthPoint		   UpdateHealthDelegate;
	FAddtiveHealthPoint		   AddtiveHealthDelegate;
	FMinusHealthPoint		   MinusHealthDelegate;
	FDeathDelegate			   DeathUpdateDelegate;

	TUniquePtr<FHealthPoint>   mHealthPoint;
};
#include "HealthManageComponent.h"


UHealthManageComponent::UHealthManageComponent()
{	
	PrimaryComponentTick.bCanEverTick = false;
	mHealthPoint = MakeUnique<FHealthPoint>();
}


// Called when the game starts
void UHealthManageComponent::BeginPlay()
{
	Super::BeginPlay();

	// 외부 데이터를 통해 hp 세팅
	InitData(1000);	
}



void UHealthManageComponent::InitData(const int maxHP)
{
	mHealthPoint->InitData(maxHP);

	UpdateHealthDelegate.Broadcast(GetCurrentHP());
}

void UHealthManageComponent::InitData(const FHealthPoint& newHPData)
{
	mHealthPoint.Reset();
	mHealthPoint = MakeUnique<FHealthPoint>(newHPData);

	UpdateHealthDelegate.Broadcast(GetCurrentHP());
}

void UHealthManageComponent::AddHP(const int addtiveHP)
{
	mHealthPoint->AddHP(addtiveHP);

	UpdateHealthDelegate.Broadcast(GetCurrentHP());
	AddtiveHealthDelegate.Broadcast(GetCurrentHP());
}

void UHealthManageComponent::MinHP(const int minusHP)
{
	mHealthPoint->MinHP(minusHP);

	UpdateHealthDelegate.Broadcast(GetCurrentHP());
	MinusHealthDelegate.Broadcast(GetCurrentHP());

	if (true == IsDead())
	{
		if (DeathUpdateDelegate.IsBound())
		{
			DeathUpdateDelegate.Broadcast();
		}
	}
}

void UHealthManageComponent::ResetHP()
{
	mHealthPoint->ResetHP();

	UpdateHealthDelegate.Broadcast(GetCurrentHP());
}

bool UHealthManageComponent::IsDead() const
{
	return mHealthPoint->IsZero();
}

int UHealthManageComponent::GetCurrentHP() const
{
	return mHealthPoint->GetCurrentHP();
}