164 lines
4.1 KiB
C++
164 lines
4.1 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
|
|
#include "Components/StatsComponent.h"
|
|
#include "Components/StateManagerComponent.h"
|
|
#include "Math/UnrealMathUtility.h"
|
|
#include "Kismet/KismetSystemLibrary.h"
|
|
|
|
// Sets default values for this component's properties
|
|
UStatsComponent::UStatsComponent()
|
|
{
|
|
// Set this component to be initialized when the game starts, and to be ticked every frame. You can turn these features
|
|
// off to improve performance if you don't need them.
|
|
PrimaryComponentTick.bCanEverTick = true;
|
|
|
|
// ...
|
|
StaminaRegenRate = 2.f;
|
|
}
|
|
|
|
|
|
// Called when the game starts
|
|
void UStatsComponent::BeginPlay()
|
|
{
|
|
Super::BeginPlay();
|
|
|
|
// ...
|
|
|
|
}
|
|
|
|
|
|
// Called every frame
|
|
void UStatsComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
|
{
|
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
|
|
|
// ...
|
|
}
|
|
|
|
void UStatsComponent::InitializeStats()
|
|
{
|
|
for (auto& stat : BaseStats)
|
|
SetCurrentStatValue(stat.Key, stat.Value.BaseValue);
|
|
}
|
|
|
|
void UStatsComponent::SetCurrentStatValue(EStats stat, float value)
|
|
{
|
|
CurrentStats.Add(stat, value);
|
|
OnCurrentStatValueUpdated.Broadcast(stat, value);
|
|
}
|
|
|
|
float UStatsComponent::GetCurrentStatValue(EStats stat)
|
|
{
|
|
return *CurrentStats.Find(stat);
|
|
}
|
|
|
|
void UStatsComponent::ModifyCurrentStatValue(EStats stat, float value, bool bShouldRegenerate)
|
|
{
|
|
if (FMath::IsNearlyEqual(value, 0.f))
|
|
return;
|
|
|
|
float currentValue = GetCurrentStatValue(stat) + value;
|
|
currentValue = FMath::Clamp(currentValue, 0.f, currentValue);
|
|
SetCurrentStatValue(stat, currentValue);
|
|
|
|
if (bShouldRegenerate)
|
|
StartRegen(stat);
|
|
}
|
|
|
|
void UStatsComponent::TakeDamageOnStat(float inDamage)
|
|
{
|
|
float calDamage;
|
|
float armor = GetCurrentStatValue(EStats::Armor);
|
|
calDamage = (inDamage / (inDamage + armor)) * inDamage;
|
|
calDamage = FMath::Clamp(calDamage, 0.f, calDamage);
|
|
ModifyCurrentStatValue(EStats::Health, -calDamage, false);
|
|
|
|
FString debugStr = FString::Printf(TEXT("Damage : %f"), calDamage);
|
|
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr);
|
|
|
|
if (GetCurrentStatValue(EStats::Health) <= 0.f)
|
|
GetOwner()->GetComponentByClass<UStateManagerComponent>()->SetCurrentState(ECharacterState::Dead);
|
|
}
|
|
|
|
void UStatsComponent::StartRegen(EStats statType)
|
|
{
|
|
switch (statType)
|
|
{
|
|
case EStats::None:
|
|
break;
|
|
case EStats::Health:
|
|
break;
|
|
case EStats::Stamina:
|
|
{
|
|
if (GEngine)
|
|
{
|
|
UWorld* World = GEngine->GetWorldFromContextObjectChecked(this);
|
|
if (World)
|
|
{
|
|
World->GetTimerManager().ClearTimer(RegenTimerHandle);
|
|
World->GetTimerManager().SetTimer(AfterRegenTimerHandle, this, &UStatsComponent::AfterDelayExecuteRegenStamina, 1.5f, false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case EStats::Armor:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void UStatsComponent::AfterDelayExecuteRegenStamina()
|
|
{
|
|
if (GEngine)
|
|
{
|
|
UWorld* World = GEngine->GetWorldFromContextObjectChecked(this);
|
|
if (World)
|
|
{
|
|
World->GetTimerManager().ClearTimer(RegenTimerHandle);
|
|
World->GetTimerManager().SetTimer(RegenTimerHandle, this, &UStatsComponent::RegenerateStamina, 0.1f, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void UStatsComponent::RegenerateStamina()
|
|
{
|
|
float curStamina = StaminaRegenRate + GetCurrentStatValue(EStats::Stamina);
|
|
curStamina = FMath::Clamp(curStamina, 0.f, GetMaxStatValue(EStats::Stamina));
|
|
SetCurrentStatValue(EStats::Stamina, curStamina);
|
|
|
|
//FString debugStr = FString::Printf(TEXT("Stamina %f"), curStamina);
|
|
//GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Blue, debugStr);
|
|
|
|
if (GetCurrentStatValue(EStats::Stamina) >= GetMaxStatValue(EStats::Stamina))
|
|
{
|
|
UWorld* World = GEngine->GetWorldFromContextObjectChecked(this);
|
|
if (World)
|
|
World->GetTimerManager().ClearTimer(RegenTimerHandle);
|
|
}
|
|
}
|
|
|
|
float UStatsComponent::GetBaseStatValue(EStats stat)
|
|
{
|
|
return BaseStats.Find(stat)->BaseValue;
|
|
}
|
|
|
|
float UStatsComponent::GetMaxStatValue(EStats stat)
|
|
{
|
|
return BaseStats.Find(stat)->MaxValue;
|
|
}
|
|
|
|
void UStatsComponent::SetBaseStatValue(EStats stat, float value)
|
|
{
|
|
if (BaseStats.Contains(stat))
|
|
BaseStats.Find(stat)->BaseValue = value;
|
|
}
|
|
|
|
void UStatsComponent::SetMaxStatValue(EStats stat, float value)
|
|
{
|
|
if (BaseStats.Contains(stat))
|
|
BaseStats.Find(stat)->MaxValue = value;
|
|
}
|
|
|