[박치영] Stat Component 작업 중

main
PCYPC\pcy35 2023-08-10 19:06:02 +09:00
parent 5706b3a1bf
commit 312cf74de4
12 changed files with 189 additions and 26 deletions

Binary file not shown.

Binary file not shown.

View File

@ -9,7 +9,8 @@
"Type": "Runtime", "Type": "Runtime",
"LoadingPhase": "Default", "LoadingPhase": "Default",
"AdditionalDependencies": [ "AdditionalDependencies": [
"Engine" "Engine",
"UMG"
] ]
} }
], ],

View File

@ -20,13 +20,29 @@ ABaseWeapon::ABaseWeapon()
InputCollisionObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn)); InputCollisionObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
CollisionComponent->SetCollisionObjectTypes(InputCollisionObjectTypes); CollisionComponent->SetCollisionObjectTypes(InputCollisionObjectTypes);
CollisionComponent->SetDrawDebugType(EDrawDebugTrace::None); CollisionComponent->SetDrawDebugType(EDrawDebugTrace::None);
ActionStatCost.Add(ECharacterAction::LightAttack, 10.f);
ActionStatCost.Add(ECharacterAction::HeavyAttack, 15.f);
ActionStatCost.Add(ECharacterAction::ChargedAttack, 20.f);
ActionStatCost.Add(ECharacterAction::FallingAttack, 10.f);
ActionStatCost.Add(ECharacterAction::SprintAttack, 10.f);
ActionStatCost.Add(ECharacterAction::Dodge, 20.f);
ActionDamageMultiplier.Add(ECharacterAction::LightAttack, 1.f);
ActionDamageMultiplier.Add(ECharacterAction::HeavyAttack, 1.4f);
ActionDamageMultiplier.Add(ECharacterAction::ChargedAttack, 1.5f);
ActionDamageMultiplier.Add(ECharacterAction::FallingAttack, 1.2f);
ActionDamageMultiplier.Add(ECharacterAction::SprintAttack, 1.2f);
} }
void ABaseWeapon::OnEquipped() void ABaseWeapon::OnEquipped()
{ {
SetIsEquipped(true); SetIsEquipped(true);
AActor* owner = GetOwner(); AActor* owner = GetOwner();
if (!owner)
return;
CombatComponent = owner->GetComponentByClass<UCombatComponent>(); CombatComponent = owner->GetComponentByClass<UCombatComponent>();
OwnerStateManager = owner->GetComponentByClass<UStateManagerComponent>();
if (CombatComponent->GetCombatEnabled()) if (CombatComponent->GetCombatEnabled())
AttachActor(HandSocketName); AttachActor(HandSocketName);
@ -62,6 +78,24 @@ void ABaseWeapon::SimulateWeaponPhysics()
GetItemMesh()->SetSimulatePhysics(true); GetItemMesh()->SetSimulatePhysics(true);
} }
float ABaseWeapon::GetStatCostForAction()
{
if (!IsValid(OwnerStateManager))
return 0.f;
return *ActionStatCost.Find(OwnerStateManager->GetCurrentAction());
}
float ABaseWeapon::GetDamage()
{
if (!IsValid(OwnerStateManager))
return Damage;
float outDamage = *ActionDamageMultiplier.Find(OwnerStateManager->GetCurrentAction());
outDamage = FMath::Clamp(outDamage, 1.f, outDamage) * Damage;
return outDamage;
}
TArray<UAnimMontage*> ABaseWeapon::GetActionMontage(ECharacterAction characterAction) TArray<UAnimMontage*> ABaseWeapon::GetActionMontage(ECharacterAction characterAction)
{ {
TArray<UAnimMontage*> outputArr; TArray<UAnimMontage*> outputArr;

View File

@ -32,6 +32,8 @@ public:
public: public:
//Normal //Normal
void SimulateWeaponPhysics(); void SimulateWeaponPhysics();
float GetStatCostForAction();
float GetDamage();
public: public:
TArray<UAnimMontage*> GetActionMontage(ECharacterAction characterAction); TArray<UAnimMontage*> GetActionMontage(ECharacterAction characterAction);
@ -45,6 +47,8 @@ protected:
TObjectPtr<class UCombatComponent> CombatComponent; TObjectPtr<class UCombatComponent> CombatComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components") UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components")
TObjectPtr<class UCollisionComponent> CollisionComponent; TObjectPtr<class UCollisionComponent> CollisionComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components")
TObjectPtr<UStateManagerComponent> OwnerStateManager;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Montages")
TObjectPtr<UAnimMontage> EnterCombat; TObjectPtr<UAnimMontage> EnterCombat;
@ -65,4 +69,9 @@ protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat") UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat")
float Damage; float Damage;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat")
TMap<ECharacterAction, float> ActionStatCost;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stat")
TMap<ECharacterAction, float> ActionDamageMultiplier;
}; };

View File

@ -12,6 +12,7 @@
#include "Interface/Interact.h" #include "Interface/Interact.h"
#include "Actor/BaseWeapon.h" #include "Actor/BaseWeapon.h"
#include "Components/CombatComponent.h" #include "Components/CombatComponent.h"
#include "Components/StatsComponent.h"
#include "Engine/DamageEvents.h" #include "Engine/DamageEvents.h"
#include "Kismet/KismetSystemLibrary.h" #include "Kismet/KismetSystemLibrary.h"
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
@ -71,6 +72,10 @@ ACombatCharacter::ACombatCharacter()
StateManagerComponent->OnActionBegin.AddUObject(this, &ACombatCharacter::CharacterActionBegin); StateManagerComponent->OnActionBegin.AddUObject(this, &ACombatCharacter::CharacterActionBegin);
StateManagerComponent->OnActionEnd.AddUObject(this, &ACombatCharacter::CharacterActionEnd); StateManagerComponent->OnActionEnd.AddUObject(this, &ACombatCharacter::CharacterActionEnd);
// Setting StatsComponent
StatsComponent = CreateDefaultSubobject<UStatsComponent>(TEXT("StatsComponent"));
StatsComponent->OnCurrentStatValueUpdated.AddUObject(this, &ACombatCharacter::CharacterCurrentStatValueUpdated);
//Setting MovementSpeed //Setting MovementSpeed
MovementSpeedMode = EMovementSpeedMode::Jogging; MovementSpeedMode = EMovementSpeedMode::Jogging;
WalkingSpeed = 200.f; WalkingSpeed = 200.f;
@ -103,6 +108,8 @@ void ACombatCharacter::BeginPlay()
ABaseEquippable* SpawnItem = Cast<ABaseEquippable>(GetWorld()->SpawnActor(Weapon, &GetActorTransform(), spawnParam)); ABaseEquippable* SpawnItem = Cast<ABaseEquippable>(GetWorld()->SpawnActor(Weapon, &GetActorTransform(), spawnParam));
if (SpawnItem) if (SpawnItem)
SpawnItem->OnEquipped(); SpawnItem->OnEquipped();
StatsComponent->InitializeStats();
} }
float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
@ -113,7 +120,7 @@ float ACombatCharacter::TakeDamage(float Damage, FDamageEvent const& DamageEvent
{ {
const FPointDamageEvent* PointDamageEvent = static_cast<const FPointDamageEvent*>(&DamageEvent); const FPointDamageEvent* PointDamageEvent = static_cast<const FPointDamageEvent*>(&DamageEvent);
CharacterTakeDamage(fDamage); StatsComponent->TakeDamageOnStat(Damage);
//Play Sound //Play Sound
UGameplayStatics::PlaySoundAtLocation(this, HitSound, PointDamageEvent->HitInfo.Location); UGameplayStatics::PlaySoundAtLocation(this, HitSound, PointDamageEvent->HitInfo.Location);
@ -200,7 +207,6 @@ void ACombatCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerIn
EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Triggered, this, &ACombatCharacter::LightChargeAttack); EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Triggered, this, &ACombatCharacter::LightChargeAttack);
EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Completed, this, &ACombatCharacter::LightAttack); EnhancedInputComponent->BindAction(LightAttackAction, ETriggerEvent::Completed, this, &ACombatCharacter::LightAttack);
//HeavyAttack //HeavyAttack
EnhancedInputComponent->BindAction(HeavyAttackAction, ETriggerEvent::Started, this, &ACombatCharacter::HeavyAttack); EnhancedInputComponent->BindAction(HeavyAttackAction, ETriggerEvent::Started, this, &ACombatCharacter::HeavyAttack);
@ -308,7 +314,15 @@ void ACombatCharacter::LightChargeAttack(const FInputActionInstance& Instance)
if (bAttackCharged) if (bAttackCharged)
{ {
if (CanPerformAttack()) if (CanPerformAttack())
{
PerformAttack(ECharacterAction::ChargedAttack, CombatComponent->GetAttackCount()); PerformAttack(ECharacterAction::ChargedAttack, CombatComponent->GetAttackCount());
ABaseWeapon* pBaseWeapon = CombatComponent->GetMainWeapon();
if (IsValid(pBaseWeapon))
{
StatsComponent->ModifyCurrentStatValue(EStats::Stamina, -1.f * pBaseWeapon->GetStatCostForAction());
}
}
} }
} }
@ -326,7 +340,15 @@ void ACombatCharacter::HeavyAttack(const FInputActionValue& Value)
void ACombatCharacter::Dodge(const FInputActionValue& Value) void ACombatCharacter::Dodge(const FInputActionValue& Value)
{ {
if (CanPerformDodge()) if (CanPerformDodge())
{
PerformDodge(); PerformDodge();
ABaseWeapon* pBaseWeapon = CombatComponent->GetMainWeapon();
if (IsValid(pBaseWeapon))
{
StatsComponent->ModifyCurrentStatValue(EStats::Stamina, -1.f * pBaseWeapon->GetStatCostForAction());
}
}
} }
void ACombatCharacter::ToggleWalk(const FInputActionValue& Value) void ACombatCharacter::ToggleWalk(const FInputActionValue& Value)
@ -339,14 +361,19 @@ void ACombatCharacter::ToggleWalk(const FInputActionValue& Value)
} }
void ACombatCharacter::StartSprint(const FInputActionValue& Value) void ACombatCharacter::StartSprint(const FInputActionValue& Value)
{
if (CanPerformSprint())
{ {
SetMovementSpeedMode(EMovementSpeedMode::Sprinting); SetMovementSpeedMode(EMovementSpeedMode::Sprinting);
UWorld* World = GEngine->GetWorldFromContextObjectChecked(this);
if (World)
World->GetTimerManager().SetTimer(StaminaTimerHandle, this, &ACombatCharacter::SprintStaminaCost, 0.1f, true);
}
} }
void ACombatCharacter::StopSprint(const FInputActionValue& Value) void ACombatCharacter::StopSprint(const FInputActionValue& Value)
{ {
if (GetMovementSpeedMode() == EMovementSpeedMode::Sprinting) DisableSprint();
SetMovementSpeedMode(EMovementSpeedMode::Jogging);
} }
void ACombatCharacter::CharacterStateBegin(ECharacterState CharState) void ACombatCharacter::CharacterStateBegin(ECharacterState CharState)
@ -450,6 +477,14 @@ void ACombatCharacter::CharacterActionEnd(ECharacterAction CharAction)
} }
} }
void ACombatCharacter::CharacterCurrentStatValueUpdated(EStats statType, float value)
{
if (!(statType == EStats::Health) || value > 0.f)
return;
StateManagerComponent->SetCurrentState(ECharacterState::Dead);
}
void ACombatCharacter::ToggleCombatEvent() void ACombatCharacter::ToggleCombatEvent()
{ {
ABaseWeapon* baseWeapon = CombatComponent->GetMainWeapon(); ABaseWeapon* baseWeapon = CombatComponent->GetMainWeapon();
@ -471,20 +506,15 @@ void ACombatCharacter::AttackEvent()
return; return;
if (CombatComponent->GetCombatEnabled()) if (CombatComponent->GetCombatEnabled())
{
PerformAttack(GetDesiredAttackType(), CombatComponent->GetAttackCount()); PerformAttack(GetDesiredAttackType(), CombatComponent->GetAttackCount());
if (IsValid(CombatComponent->GetMainWeapon()))
StatsComponent->ModifyCurrentStatValue(EStats::Stamina, -1.f * CombatComponent->GetMainWeapon()->GetStatCostForAction());
}
else else
ToggleCombatEvent(); ToggleCombatEvent();
} }
void ACombatCharacter::CharacterTakeDamage(float InDamage)
{
float tmp = Health - InDamage;
Health = UKismetMathLibrary::Clamp(tmp, 0, Health);
if (Health <= 0)
StateManagerComponent->SetCurrentState(ECharacterState::Dead);
}
void ACombatCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed) void ACombatCharacter::ApplyHitReactionPhysicsVelocity(float InitialSpeed)
{ {
if (!GetMesh()) if (!GetMesh())
@ -540,6 +570,32 @@ bool ACombatCharacter::ResetChargeAttack()
return true; return true;
} }
void ACombatCharacter::DisableSprint()
{
UWorld* World = GEngine->GetWorldFromContextObjectChecked(this);
if (World)
World->GetTimerManager().ClearTimer(StaminaTimerHandle);
if (GetMovementSpeedMode() == EMovementSpeedMode::Sprinting)
SetMovementSpeedMode(EMovementSpeedMode::Jogging);
}
void ACombatCharacter::SprintStaminaCost()
{
if (!CanPerformSprint())
{
DisableSprint();
return;
}
StatsComponent->ModifyCurrentStatValue(EStats::Stamina, -2.f);
if (StatsComponent->GetCurrentStatValue(EStats::Stamina) < 10.f)
{
DisableSprint();
return;
}
}
void ACombatCharacter::PerformAttack(ECharacterAction attackType, int32 attackIndex) void ACombatCharacter::PerformAttack(ECharacterAction attackType, int32 attackIndex)
{ {
ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon(); ABaseWeapon* CurrentWeapon = CombatComponent->GetMainWeapon();
@ -677,6 +733,8 @@ bool ACombatCharacter::CanPerformAttack()
ECharacterState::GeneralActionState ECharacterState::GeneralActionState
}; };
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr); ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
ReturnValue &= (StatsComponent->GetCurrentStatValue(EStats::Stamina) >= 10.f);
return ReturnValue; return ReturnValue;
} }
@ -691,6 +749,7 @@ bool ACombatCharacter::CanPerformDodge()
}; };
ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr); ReturnValue &= !StateManagerComponent->IsCurrentStateEqualToAny(inputArr);
ReturnValue &= !GetCharacterMovement()->IsFalling(); ReturnValue &= !GetCharacterMovement()->IsFalling();
ReturnValue &= (StatsComponent->GetCurrentStatValue(EStats::Stamina) >= 10.f);
return ReturnValue; return ReturnValue;
} }
@ -718,6 +777,11 @@ bool ACombatCharacter::CanReceiveHitReaction()
return ReturnValue; return ReturnValue;
} }
bool ACombatCharacter::CanPerformSprint()
{
return (FMath::IsNearlyEqual(GetVelocity().Length(), 0.f)) == false;
}
ECharacterAction ACombatCharacter::GetDesiredAttackType() ECharacterAction ACombatCharacter::GetDesiredAttackType()
{ {
if (GetCharacterMovement()->IsFalling()) if (GetCharacterMovement()->IsFalling())

View File

@ -8,6 +8,7 @@
#include "InputAction.h" #include "InputAction.h"
#include "Interface/CombatInterface.h" #include "Interface/CombatInterface.h"
#include "Components/StateManagerComponent.h" #include "Components/StateManagerComponent.h"
#include "Components/StatsComponent.h"
#include "Definitions/GameEnums.h" #include "Definitions/GameEnums.h"
#include "CombatCharacter.generated.h" #include "CombatCharacter.generated.h"
@ -119,16 +120,18 @@ private://Delegate
void CharacterStateEnd(ECharacterState CharState); void CharacterStateEnd(ECharacterState CharState);
void CharacterActionBegin(ECharacterAction CharAction); void CharacterActionBegin(ECharacterAction CharAction);
void CharacterActionEnd(ECharacterAction CharAction); void CharacterActionEnd(ECharacterAction CharAction);
void CharacterCurrentStatValueUpdated(EStats statType, float value);
private: private:
void ToggleCombatEvent(); void ToggleCombatEvent();
void AttackEvent(); void AttackEvent();
void CharacterTakeDamage(float InDamage);
void ApplyHitReactionPhysicsVelocity(float InitialSpeed); void ApplyHitReactionPhysicsVelocity(float InitialSpeed);
void EnableRagdoll(); void EnableRagdoll();
void SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode); void SetMovementSpeedMode(EMovementSpeedMode NewSpeedMode);
FORCEINLINE EMovementSpeedMode GetMovementSpeedMode() const { return MovementSpeedMode; } FORCEINLINE EMovementSpeedMode GetMovementSpeedMode() const { return MovementSpeedMode; }
bool ResetChargeAttack(); bool ResetChargeAttack();
void DisableSprint();
void SprintStaminaCost();
private: private:
void PerformAttack(ECharacterAction attackType, int32 attackIndex); void PerformAttack(ECharacterAction attackType, int32 attackIndex);
@ -142,13 +145,17 @@ private:
bool CanPerformDodge(); bool CanPerformDodge();
bool CanJumping(); bool CanJumping();
bool CanReceiveHitReaction(); bool CanReceiveHitReaction();
bool CanPerformSprint();
ECharacterAction GetDesiredAttackType(); ECharacterAction GetDesiredAttackType();
public: public:
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true")) UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
TObjectPtr<class UCombatComponent> CombatComponent; TObjectPtr<class UCombatComponent> CombatComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true")) UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
TObjectPtr<class UStateManagerComponent> StateManagerComponent; TObjectPtr<UStateManagerComponent> StateManagerComponent;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Components", meta=(AllowPrivateAccess="true"))
TObjectPtr<UStatsComponent> StatsComponent;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon", meta = (AllowPrivateAccess = "true")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Weapon", meta = (AllowPrivateAccess = "true"))
TSubclassOf<class ABaseEquippable> Weapon; TSubclassOf<class ABaseEquippable> Weapon;
@ -180,6 +187,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats", meta = (AllowPrivateAccess = "true")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats", meta = (AllowPrivateAccess = "true"))
float Health; float Health;
private:
FTimerHandle StaminaTimerHandle;
private: private:
bool IsHeavyAttack; bool IsHeavyAttack;
float AttackHeldTime; float AttackHeldTime;

View File

@ -13,6 +13,7 @@ UStatsComponent::UStatsComponent()
PrimaryComponentTick.bCanEverTick = true; PrimaryComponentTick.bCanEverTick = true;
// ... // ...
StaminaRegenRate = 2.f;
} }
@ -70,9 +71,9 @@ void UStatsComponent::TakeDamageOnStat(float inDamage)
float armor = GetCurrentStatValue(EStats::Armor); float armor = GetCurrentStatValue(EStats::Armor);
calDamage = (inDamage / (inDamage + armor)) * inDamage; calDamage = (inDamage / (inDamage + armor)) * inDamage;
calDamage = FMath::Clamp(calDamage, 0.f, calDamage); calDamage = FMath::Clamp(calDamage, 0.f, calDamage);
ModifyCurrentStatValue(EStats::Health, -calDamage); ModifyCurrentStatValue(EStats::Health, -calDamage, false);
FString debugStr = FString::Printf(TEXT("Damage : %d"), calDamage); FString debugStr = FString::Printf(TEXT("Damage : %f"), calDamage);
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr); GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Red, debugStr);
if (GetCurrentStatValue(EStats::Health) <= 0.f) if (GetCurrentStatValue(EStats::Health) <= 0.f)
@ -109,12 +110,20 @@ void UStatsComponent::StartRegen(EStats statType)
void UStatsComponent::RegenerateStamina() void UStatsComponent::RegenerateStamina()
{ {
//TODO : 여기부터 시작 float curStamina = StaminaRegenRate + GetCurrentStatValue(EStats::Stamina);
curStamina = FMath::Clamp(curStamina, 0.f, GetMaxStatValue(EStats::Stamina));
SetCurrentStatValue(EStats::Stamina, curStamina);
if (GetCurrentStatValue(EStats::Stamina) >= GetMaxStatValue(EStats::Stamina))
{
UWorld* World = GEngine->GetWorldFromContextObjectChecked(this);
if (World)
World->GetTimerManager().ClearTimer(RegenTimerHandle);
}
} }
float UStatsComponent::GetBaseStatValue(EStats stat) float UStatsComponent::GetBaseStatValue(EStats stat)
{ {
return BaseStats.Find(stat)->BaseValue; return BaseStats.Find(stat)->BaseValue;
} }

View File

@ -24,7 +24,10 @@ struct FBaseStat
FBaseStat() : BaseValue(0.f), MaxValue(0.f) {} FBaseStat() : BaseValue(0.f), MaxValue(0.f) {}
FBaseStat(float InputBaseValue, float InputMaxValue) : BaseValue(InputBaseValue), MaxValue(InputMaxValue) {} FBaseStat(float InputBaseValue, float InputMaxValue) : BaseValue(InputBaseValue), MaxValue(InputMaxValue) {}
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = BaseStat, meta = (AllowPrivateAccess = "true"))
float BaseValue; float BaseValue;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = BaseStat, meta = (AllowPrivateAccess = "true"))
float MaxValue; float MaxValue;
}; };
@ -64,14 +67,15 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = BaseStats, meta = (AllowPrivateAccess = "true")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = BaseStats, meta = (AllowPrivateAccess = "true"))
TMap<EStats, FBaseStat> BaseStats; TMap<EStats, FBaseStat> BaseStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Stats, meta = (AllowPrivateAccess = "true"))
TMap<EStats, float> CurrentStats;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = StatRegen, meta = (AllowPrivateAccess = "true")) UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = StatRegen, meta = (AllowPrivateAccess = "true"))
float StaminaRegenRate; float StaminaRegenRate;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = Stats, meta = (AllowPrivateAccess = "true"))
TMap<EStats, float> CurrentStats;
public: //Delegate
FOnCurrentStatValueUpdated OnCurrentStatValueUpdated;
private: private:
FTimerHandle RegenTimerHandle; FTimerHandle RegenTimerHandle;
private:
FOnCurrentStatValueUpdated OnCurrentStatValueUpdated;
}; };

View File

@ -0,0 +1,10 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "UI/UI_StatBar.h"
#include "Components/ProgressBar.h"
void UUI_StatBar::PreConstruct()
{
}

View File

@ -0,0 +1,22 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "UI_StatBar.generated.h"
/**
*
*/
UCLASS()
class D1_API UUI_StatBar : public UUserWidget
{
GENERATED_BODY()
protected:
virtual void PreConstruct() override;
public:
UPROPERTY(EditAnywhere, meta = (BindWidget))
class UProgressBar* StatBar;
};