Bind HUD status to GAS and player state
This commit is contained in:
@@ -109,5 +109,11 @@ UCommonActivatableWidget* APHYHUD::PushDefaultHUDWidget(APlayerController* Ownin
|
|||||||
}
|
}
|
||||||
|
|
||||||
const FGameplayTag HUDLayerTag = (UISettings && UISettings->HUDLayerTag.IsValid()) ? UISettings->HUDLayerTag : PHYGameplayTags::UI_Layer_HUD;
|
const FGameplayTag HUDLayerTag = (UISettings && UISettings->HUDLayerTag.IsValid()) ? UISettings->HUDLayerTag : PHYGameplayTags::UI_Layer_HUD;
|
||||||
return RootLayout->PushWidgetToLayerStack<UCommonActivatableWidget>(HUDLayerTag, HUDWidgetClass);
|
UCommonActivatableWidget* PushedWidget = RootLayout->PushWidgetToLayerStack<UCommonActivatableWidget>(HUDLayerTag, HUDWidgetClass);
|
||||||
|
if (UPHYHUDStatusWidget* StatusWidget = Cast<UPHYHUDStatusWidget>(PushedWidget))
|
||||||
|
{
|
||||||
|
StatusWidget->InitializeFromPlayer(OwningPlayerController);
|
||||||
|
}
|
||||||
|
|
||||||
|
return PushedWidget;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "Class/PHYClassComponent.h"
|
#include "Class/PHYClassComponent.h"
|
||||||
#include "Class/PHYClassSettings.h"
|
#include "Class/PHYClassSettings.h"
|
||||||
#include "GGA_AbilitySystemComponent.h"
|
#include "GGA_AbilitySystemComponent.h"
|
||||||
|
#include "Net/UnrealNetwork.h"
|
||||||
|
|
||||||
APHYPlayerState::APHYPlayerState(const FObjectInitializer& ObjectInitializer)
|
APHYPlayerState::APHYPlayerState(const FObjectInitializer& ObjectInitializer)
|
||||||
: Super(ObjectInitializer)
|
: Super(ObjectInitializer)
|
||||||
@@ -28,7 +29,69 @@ APHYPlayerState::APHYPlayerState(const FObjectInitializer& ObjectInitializer)
|
|||||||
ClassComponent->SetClassTag(GetDefault<UPHYClassSettings>()->DefaultPlayerClassTag);
|
ClassComponent->SetClassTag(GetDefault<UPHYClassSettings>()->DefaultPlayerClassTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
|
||||||
|
{
|
||||||
|
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
|
||||||
|
|
||||||
|
DOREPLIFETIME(ThisClass, PlayerLevel);
|
||||||
|
DOREPLIFETIME(ThisClass, Experience);
|
||||||
|
DOREPLIFETIME(ThisClass, ExperienceForNextLevel);
|
||||||
|
}
|
||||||
|
|
||||||
UAbilitySystemComponent* APHYPlayerState::GetAbilitySystemComponent() const
|
UAbilitySystemComponent* APHYPlayerState::GetAbilitySystemComponent() const
|
||||||
{
|
{
|
||||||
return AbilitySystemComponent;
|
return AbilitySystemComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::SetPlayerLevel(const int32 NewLevel)
|
||||||
|
{
|
||||||
|
SetProgression(NewLevel, Experience, ExperienceForNextLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::SetExperience(const int32 NewExperience)
|
||||||
|
{
|
||||||
|
SetProgression(PlayerLevel, NewExperience, ExperienceForNextLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::AddExperience(const int32 DeltaExperience)
|
||||||
|
{
|
||||||
|
SetExperience(Experience + DeltaExperience);
|
||||||
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::SetExperienceForNextLevel(const int32 NewExperienceForNextLevel)
|
||||||
|
{
|
||||||
|
SetProgression(PlayerLevel, Experience, NewExperienceForNextLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::SetProgression(const int32 NewLevel, const int32 NewExperience, const int32 NewExperienceForNextLevel)
|
||||||
|
{
|
||||||
|
if (!HasAuthority())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int32 ClampedLevel = FMath::Max(1, NewLevel);
|
||||||
|
const int32 ClampedExperience = FMath::Max(0, NewExperience);
|
||||||
|
const int32 ClampedExperienceForNextLevel = FMath::Max(1, NewExperienceForNextLevel);
|
||||||
|
|
||||||
|
if (PlayerLevel == ClampedLevel && Experience == ClampedExperience && ExperienceForNextLevel == ClampedExperienceForNextLevel)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerLevel = ClampedLevel;
|
||||||
|
Experience = ClampedExperience;
|
||||||
|
ExperienceForNextLevel = ClampedExperienceForNextLevel;
|
||||||
|
|
||||||
|
BroadcastProgressionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::OnRep_Progression()
|
||||||
|
{
|
||||||
|
BroadcastProgressionChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void APHYPlayerState::BroadcastProgressionChanged()
|
||||||
|
{
|
||||||
|
OnProgressionChanged.Broadcast(PlayerLevel, Experience, ExperienceForNextLevel);
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYHUDStatusWidget)
|
#include UE_INLINE_GENERATED_CPP_BY_NAME(PHYHUDStatusWidget)
|
||||||
|
|
||||||
|
#include "AbilitySystemComponent.h"
|
||||||
|
#include "AbilitySystem/Attributes/PHYCombatAttributeSet.h"
|
||||||
#include "Blueprint/WidgetTree.h"
|
#include "Blueprint/WidgetTree.h"
|
||||||
#include "Components/Overlay.h"
|
#include "Components/Overlay.h"
|
||||||
#include "Components/OverlaySlot.h"
|
#include "Components/OverlaySlot.h"
|
||||||
@@ -13,6 +15,9 @@
|
|||||||
#include "Components/VerticalBox.h"
|
#include "Components/VerticalBox.h"
|
||||||
#include "Components/VerticalBoxSlot.h"
|
#include "Components/VerticalBoxSlot.h"
|
||||||
#include "Fonts/SlateFontInfo.h"
|
#include "Fonts/SlateFontInfo.h"
|
||||||
|
#include "GameFramework/PlayerController.h"
|
||||||
|
#include "GameplayEffectTypes.h"
|
||||||
|
#include "Player/PHYPlayerState.h"
|
||||||
#include "Styling/CoreStyle.h"
|
#include "Styling/CoreStyle.h"
|
||||||
#include "Widgets/SWidget.h"
|
#include "Widgets/SWidget.h"
|
||||||
|
|
||||||
@@ -23,10 +28,29 @@ namespace
|
|||||||
return FText::FromString(FString::Printf(TEXT("%s %.0f / %.0f"), Label, FMath::Max(0.0f, Value), FMath::Max(0.0f, MaxValue)));
|
return FText::FromString(FString::Printf(TEXT("%s %.0f / %.0f"), Label, FMath::Max(0.0f, Value), FMath::Max(0.0f, MaxValue)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FText MakeProgressionText(const int32 CurrentExperience, const int32 RequiredExperience)
|
||||||
|
{
|
||||||
|
return FText::FromString(FString::Printf(TEXT("XP %d / %d"), FMath::Max(0, CurrentExperience), FMath::Max(1, RequiredExperience)));
|
||||||
|
}
|
||||||
|
|
||||||
float MakeResourcePercent(const float Value, const float MaxValue)
|
float MakeResourcePercent(const float Value, const float MaxValue)
|
||||||
{
|
{
|
||||||
return MaxValue > UE_SMALL_NUMBER ? FMath::Clamp(Value / MaxValue, 0.0f, 1.0f) : 0.0f;
|
return MaxValue > UE_SMALL_NUMBER ? FMath::Clamp(Value / MaxValue, 0.0f, 1.0f) : 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float MakeProgressionPercent(const int32 CurrentExperience, const int32 RequiredExperience)
|
||||||
|
{
|
||||||
|
return RequiredExperience > 0 ? FMath::Clamp(static_cast<float>(CurrentExperience) / static_cast<float>(RequiredExperience), 0.0f, 1.0f) : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoveAttributeChangedDelegate(UAbilitySystemComponent* AbilitySystemComponent, const FGameplayAttribute& Attribute, FDelegateHandle& DelegateHandle)
|
||||||
|
{
|
||||||
|
if (AbilitySystemComponent && DelegateHandle.IsValid())
|
||||||
|
{
|
||||||
|
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(Attribute).Remove(DelegateHandle);
|
||||||
|
DelegateHandle.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UPHYHUDStatusWidget::UPHYHUDStatusWidget(const FObjectInitializer& ObjectInitializer)
|
UPHYHUDStatusWidget::UPHYHUDStatusWidget(const FObjectInitializer& ObjectInitializer)
|
||||||
@@ -47,6 +71,35 @@ void UPHYHUDStatusWidget::SynchronizeProperties()
|
|||||||
UpdateResourceWidgets();
|
UpdateResourceWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::InitializeFromPlayer(APlayerController* InPlayerController)
|
||||||
|
{
|
||||||
|
if (!InPlayerController)
|
||||||
|
{
|
||||||
|
BoundPlayerController.Reset();
|
||||||
|
UnbindFromPlayerState();
|
||||||
|
UnbindFromAbilitySystem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundPlayerController = InPlayerController;
|
||||||
|
RefreshFromBoundSources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::RefreshFromBoundSources()
|
||||||
|
{
|
||||||
|
APlayerController* PlayerController = BoundPlayerController.Get();
|
||||||
|
if (!PlayerController)
|
||||||
|
{
|
||||||
|
UnbindFromPlayerState();
|
||||||
|
UnbindFromAbilitySystem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
APHYPlayerState* PHYPlayerState = PlayerController->GetPlayerState<APHYPlayerState>();
|
||||||
|
BindToPlayerState(PHYPlayerState);
|
||||||
|
BindToAbilitySystem(PHYPlayerState ? PHYPlayerState->GetAbilitySystemComponent() : nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
void UPHYHUDStatusWidget::SetHealth(const float NewHealth, const float NewMaxHealth)
|
void UPHYHUDStatusWidget::SetHealth(const float NewHealth, const float NewMaxHealth)
|
||||||
{
|
{
|
||||||
Health = NewHealth;
|
Health = NewHealth;
|
||||||
@@ -54,6 +107,13 @@ void UPHYHUDStatusWidget::SetHealth(const float NewHealth, const float NewMaxHea
|
|||||||
UpdateResourceWidgets();
|
UpdateResourceWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::SetMana(const float NewMana, const float NewMaxMana)
|
||||||
|
{
|
||||||
|
Mana = NewMana;
|
||||||
|
MaxMana = NewMaxMana;
|
||||||
|
UpdateResourceWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
void UPHYHUDStatusWidget::SetStamina(const float NewStamina, const float NewMaxStamina)
|
void UPHYHUDStatusWidget::SetStamina(const float NewStamina, const float NewMaxStamina)
|
||||||
{
|
{
|
||||||
Stamina = NewStamina;
|
Stamina = NewStamina;
|
||||||
@@ -61,6 +121,54 @@ void UPHYHUDStatusWidget::SetStamina(const float NewStamina, const float NewMaxS
|
|||||||
UpdateResourceWidgets();
|
UpdateResourceWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::SetProgression(const int32 NewLevel, const int32 NewExperience, const int32 NewExperienceForNextLevel)
|
||||||
|
{
|
||||||
|
Level = FMath::Max(1, NewLevel);
|
||||||
|
Experience = FMath::Max(0, NewExperience);
|
||||||
|
ExperienceForNextLevel = FMath::Max(1, NewExperienceForNextLevel);
|
||||||
|
UpdateResourceWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::NativeConstruct()
|
||||||
|
{
|
||||||
|
Super::NativeConstruct();
|
||||||
|
|
||||||
|
if (!BoundPlayerController.IsValid())
|
||||||
|
{
|
||||||
|
InitializeFromPlayer(GetOwningPlayer());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RefreshFromBoundSources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::NativeDestruct()
|
||||||
|
{
|
||||||
|
UnbindFromPlayerState();
|
||||||
|
UnbindFromAbilitySystem();
|
||||||
|
BoundPlayerController.Reset();
|
||||||
|
|
||||||
|
Super::NativeDestruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::NativeTick(const FGeometry& MyGeometry, const float InDeltaTime)
|
||||||
|
{
|
||||||
|
Super::NativeTick(MyGeometry, InDeltaTime);
|
||||||
|
|
||||||
|
APlayerController* PlayerController = BoundPlayerController.Get();
|
||||||
|
if (!PlayerController)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
APHYPlayerState* CurrentPlayerState = PlayerController->GetPlayerState<APHYPlayerState>();
|
||||||
|
if (CurrentPlayerState != BoundPlayerState.Get() || !BoundAbilitySystemComponent.IsValid())
|
||||||
|
{
|
||||||
|
RefreshFromBoundSources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UPHYHUDStatusWidget::BuildNativeWidgetTree()
|
void UPHYHUDStatusWidget::BuildNativeWidgetTree()
|
||||||
{
|
{
|
||||||
if (!WidgetTree)
|
if (!WidgetTree)
|
||||||
@@ -68,7 +176,7 @@ void UPHYHUDStatusWidget::BuildNativeWidgetTree()
|
|||||||
WidgetTree = NewObject<UWidgetTree>(this, TEXT("WidgetTree"), RF_Transient);
|
WidgetTree = NewObject<UWidgetTree>(this, TEXT("WidgetTree"), RF_Transient);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WidgetTree->RootWidget && TitleText && HealthText && HealthBar && StaminaText && StaminaBar)
|
if (WidgetTree->RootWidget && TitleText && LevelText && HealthText && HealthBar && ManaText && ManaBar && StaminaText && StaminaBar && ExperienceText && ExperienceBar)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -93,7 +201,15 @@ void UPHYHUDStatusWidget::BuildNativeWidgetTree()
|
|||||||
TitleText->SetColorAndOpacity(FSlateColor(FLinearColor(0.85f, 0.95f, 1.0f, 1.0f)));
|
TitleText->SetColorAndOpacity(FSlateColor(FLinearColor(0.85f, 0.95f, 1.0f, 1.0f)));
|
||||||
if (UVerticalBoxSlot* TitleSlot = StatusBox->AddChildToVerticalBox(TitleText))
|
if (UVerticalBoxSlot* TitleSlot = StatusBox->AddChildToVerticalBox(TitleText))
|
||||||
{
|
{
|
||||||
TitleSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 8.0f));
|
TitleSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 4.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
LevelText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("LevelText"));
|
||||||
|
LevelText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16));
|
||||||
|
LevelText->SetColorAndOpacity(FSlateColor(FLinearColor(0.95f, 0.95f, 0.95f, 1.0f)));
|
||||||
|
if (UVerticalBoxSlot* LevelSlot = StatusBox->AddChildToVerticalBox(LevelText))
|
||||||
|
{
|
||||||
|
LevelSlot->SetPadding(FMargin(0.0f, 0.0f, 0.0f, 8.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
HealthText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("HealthText"));
|
HealthText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("HealthText"));
|
||||||
@@ -108,6 +224,18 @@ void UPHYHUDStatusWidget::BuildNativeWidgetTree()
|
|||||||
HealthBarSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 8.0f));
|
HealthBarSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 8.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ManaText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("ManaText"));
|
||||||
|
ManaText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16));
|
||||||
|
ManaText->SetColorAndOpacity(FSlateColor(FLinearColor(0.95f, 0.95f, 0.95f, 1.0f)));
|
||||||
|
StatusBox->AddChildToVerticalBox(ManaText);
|
||||||
|
|
||||||
|
ManaBar = WidgetTree->ConstructWidget<UProgressBar>(UProgressBar::StaticClass(), TEXT("ManaBar"));
|
||||||
|
ManaBar->SetFillColorAndOpacity(FLinearColor(0.26f, 0.34f, 0.86f, 1.0f));
|
||||||
|
if (UVerticalBoxSlot* ManaBarSlot = StatusBox->AddChildToVerticalBox(ManaBar))
|
||||||
|
{
|
||||||
|
ManaBarSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 8.0f));
|
||||||
|
}
|
||||||
|
|
||||||
StaminaText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("StaminaText"));
|
StaminaText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("StaminaText"));
|
||||||
StaminaText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16));
|
StaminaText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16));
|
||||||
StaminaText->SetColorAndOpacity(FSlateColor(FLinearColor(0.95f, 0.95f, 0.95f, 1.0f)));
|
StaminaText->SetColorAndOpacity(FSlateColor(FLinearColor(0.95f, 0.95f, 0.95f, 1.0f)));
|
||||||
@@ -117,14 +245,146 @@ void UPHYHUDStatusWidget::BuildNativeWidgetTree()
|
|||||||
StaminaBar->SetFillColorAndOpacity(FLinearColor(0.12f, 0.62f, 0.86f, 1.0f));
|
StaminaBar->SetFillColorAndOpacity(FLinearColor(0.12f, 0.62f, 0.86f, 1.0f));
|
||||||
if (UVerticalBoxSlot* StaminaBarSlot = StatusBox->AddChildToVerticalBox(StaminaBar))
|
if (UVerticalBoxSlot* StaminaBarSlot = StatusBox->AddChildToVerticalBox(StaminaBar))
|
||||||
{
|
{
|
||||||
StaminaBarSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 0.0f));
|
StaminaBarSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 8.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
ExperienceText = WidgetTree->ConstructWidget<UTextBlock>(UTextBlock::StaticClass(), TEXT("ExperienceText"));
|
||||||
|
ExperienceText->SetFont(FSlateFontInfo(FCoreStyle::GetDefaultFont(), 16));
|
||||||
|
ExperienceText->SetColorAndOpacity(FSlateColor(FLinearColor(0.95f, 0.95f, 0.95f, 1.0f)));
|
||||||
|
StatusBox->AddChildToVerticalBox(ExperienceText);
|
||||||
|
|
||||||
|
ExperienceBar = WidgetTree->ConstructWidget<UProgressBar>(UProgressBar::StaticClass(), TEXT("ExperienceBar"));
|
||||||
|
ExperienceBar->SetFillColorAndOpacity(FLinearColor(0.93f, 0.62f, 0.18f, 1.0f));
|
||||||
|
if (UVerticalBoxSlot* ExperienceBarSlot = StatusBox->AddChildToVerticalBox(ExperienceBar))
|
||||||
|
{
|
||||||
|
ExperienceBarSlot->SetPadding(FMargin(0.0f, 2.0f, 0.0f, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateResourceWidgets();
|
UpdateResourceWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::BindToPlayerState(APHYPlayerState* NewPlayerState)
|
||||||
|
{
|
||||||
|
if (BoundPlayerState.Get() == NewPlayerState)
|
||||||
|
{
|
||||||
|
RefreshProgressionFromPlayerState();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnbindFromPlayerState();
|
||||||
|
BoundPlayerState = NewPlayerState;
|
||||||
|
|
||||||
|
if (NewPlayerState)
|
||||||
|
{
|
||||||
|
NewPlayerState->OnProgressionChanged.AddUniqueDynamic(this, &UPHYHUDStatusWidget::HandleProgressionChanged);
|
||||||
|
RefreshProgressionFromPlayerState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::UnbindFromPlayerState()
|
||||||
|
{
|
||||||
|
if (APHYPlayerState* PlayerState = BoundPlayerState.Get())
|
||||||
|
{
|
||||||
|
PlayerState->OnProgressionChanged.RemoveDynamic(this, &UPHYHUDStatusWidget::HandleProgressionChanged);
|
||||||
|
}
|
||||||
|
BoundPlayerState.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::BindToAbilitySystem(UAbilitySystemComponent* NewAbilitySystemComponent)
|
||||||
|
{
|
||||||
|
if (BoundAbilitySystemComponent.Get() == NewAbilitySystemComponent && HealthChangedHandle.IsValid())
|
||||||
|
{
|
||||||
|
RefreshResourcesFromAbilitySystem();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnbindFromAbilitySystem();
|
||||||
|
BoundAbilitySystemComponent = NewAbilitySystemComponent;
|
||||||
|
|
||||||
|
if (!NewAbilitySystemComponent)
|
||||||
|
{
|
||||||
|
UpdateResourceWidgets();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
HealthChangedHandle = NewAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UPHYCombatAttributeSet::GetHealthAttribute()).AddUObject(this, &UPHYHUDStatusWidget::HandleAttributeChanged);
|
||||||
|
MaxHealthChangedHandle = NewAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UPHYCombatAttributeSet::GetMaxHealthAttribute()).AddUObject(this, &UPHYHUDStatusWidget::HandleAttributeChanged);
|
||||||
|
ManaChangedHandle = NewAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UPHYCombatAttributeSet::GetManaAttribute()).AddUObject(this, &UPHYHUDStatusWidget::HandleAttributeChanged);
|
||||||
|
MaxManaChangedHandle = NewAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UPHYCombatAttributeSet::GetMaxManaAttribute()).AddUObject(this, &UPHYHUDStatusWidget::HandleAttributeChanged);
|
||||||
|
StaminaChangedHandle = NewAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UPHYCombatAttributeSet::GetStaminaAttribute()).AddUObject(this, &UPHYHUDStatusWidget::HandleAttributeChanged);
|
||||||
|
MaxStaminaChangedHandle = NewAbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(UPHYCombatAttributeSet::GetMaxStaminaAttribute()).AddUObject(this, &UPHYHUDStatusWidget::HandleAttributeChanged);
|
||||||
|
|
||||||
|
RefreshResourcesFromAbilitySystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::UnbindFromAbilitySystem()
|
||||||
|
{
|
||||||
|
if (UAbilitySystemComponent* AbilitySystemComponent = BoundAbilitySystemComponent.Get())
|
||||||
|
{
|
||||||
|
RemoveAttributeChangedDelegate(AbilitySystemComponent, UPHYCombatAttributeSet::GetHealthAttribute(), HealthChangedHandle);
|
||||||
|
RemoveAttributeChangedDelegate(AbilitySystemComponent, UPHYCombatAttributeSet::GetMaxHealthAttribute(), MaxHealthChangedHandle);
|
||||||
|
RemoveAttributeChangedDelegate(AbilitySystemComponent, UPHYCombatAttributeSet::GetManaAttribute(), ManaChangedHandle);
|
||||||
|
RemoveAttributeChangedDelegate(AbilitySystemComponent, UPHYCombatAttributeSet::GetMaxManaAttribute(), MaxManaChangedHandle);
|
||||||
|
RemoveAttributeChangedDelegate(AbilitySystemComponent, UPHYCombatAttributeSet::GetStaminaAttribute(), StaminaChangedHandle);
|
||||||
|
RemoveAttributeChangedDelegate(AbilitySystemComponent, UPHYCombatAttributeSet::GetMaxStaminaAttribute(), MaxStaminaChangedHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
HealthChangedHandle.Reset();
|
||||||
|
MaxHealthChangedHandle.Reset();
|
||||||
|
ManaChangedHandle.Reset();
|
||||||
|
MaxManaChangedHandle.Reset();
|
||||||
|
StaminaChangedHandle.Reset();
|
||||||
|
MaxStaminaChangedHandle.Reset();
|
||||||
|
BoundAbilitySystemComponent.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::RefreshResourcesFromAbilitySystem()
|
||||||
|
{
|
||||||
|
UAbilitySystemComponent* AbilitySystemComponent = BoundAbilitySystemComponent.Get();
|
||||||
|
if (!AbilitySystemComponent)
|
||||||
|
{
|
||||||
|
UpdateResourceWidgets();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Health = AbilitySystemComponent->GetNumericAttribute(UPHYCombatAttributeSet::GetHealthAttribute());
|
||||||
|
MaxHealth = AbilitySystemComponent->GetNumericAttribute(UPHYCombatAttributeSet::GetMaxHealthAttribute());
|
||||||
|
Mana = AbilitySystemComponent->GetNumericAttribute(UPHYCombatAttributeSet::GetManaAttribute());
|
||||||
|
MaxMana = AbilitySystemComponent->GetNumericAttribute(UPHYCombatAttributeSet::GetMaxManaAttribute());
|
||||||
|
Stamina = AbilitySystemComponent->GetNumericAttribute(UPHYCombatAttributeSet::GetStaminaAttribute());
|
||||||
|
MaxStamina = AbilitySystemComponent->GetNumericAttribute(UPHYCombatAttributeSet::GetMaxStaminaAttribute());
|
||||||
|
|
||||||
|
UpdateResourceWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::RefreshProgressionFromPlayerState()
|
||||||
|
{
|
||||||
|
APHYPlayerState* PlayerState = BoundPlayerState.Get();
|
||||||
|
if (!PlayerState)
|
||||||
|
{
|
||||||
|
UpdateResourceWidgets();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetProgression(PlayerState->GetPlayerLevel(), PlayerState->GetExperience(), PlayerState->GetExperienceForNextLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::HandleAttributeChanged(const FOnAttributeChangeData& /*ChangeData*/)
|
||||||
|
{
|
||||||
|
RefreshResourcesFromAbilitySystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UPHYHUDStatusWidget::HandleProgressionChanged(const int32 NewLevel, const int32 NewExperience, const int32 NewExperienceForNextLevel)
|
||||||
|
{
|
||||||
|
SetProgression(NewLevel, NewExperience, NewExperienceForNextLevel);
|
||||||
|
}
|
||||||
|
|
||||||
void UPHYHUDStatusWidget::UpdateResourceWidgets()
|
void UPHYHUDStatusWidget::UpdateResourceWidgets()
|
||||||
{
|
{
|
||||||
|
if (LevelText)
|
||||||
|
{
|
||||||
|
LevelText->SetText(FText::FromString(FString::Printf(TEXT("Lv %d"), FMath::Max(1, Level))));
|
||||||
|
}
|
||||||
if (HealthText)
|
if (HealthText)
|
||||||
{
|
{
|
||||||
HealthText->SetText(MakeResourceText(TEXT("HP"), Health, MaxHealth));
|
HealthText->SetText(MakeResourceText(TEXT("HP"), Health, MaxHealth));
|
||||||
@@ -133,6 +393,14 @@ void UPHYHUDStatusWidget::UpdateResourceWidgets()
|
|||||||
{
|
{
|
||||||
HealthBar->SetPercent(MakeResourcePercent(Health, MaxHealth));
|
HealthBar->SetPercent(MakeResourcePercent(Health, MaxHealth));
|
||||||
}
|
}
|
||||||
|
if (ManaText)
|
||||||
|
{
|
||||||
|
ManaText->SetText(MakeResourceText(TEXT("MP"), Mana, MaxMana));
|
||||||
|
}
|
||||||
|
if (ManaBar)
|
||||||
|
{
|
||||||
|
ManaBar->SetPercent(MakeResourcePercent(Mana, MaxMana));
|
||||||
|
}
|
||||||
if (StaminaText)
|
if (StaminaText)
|
||||||
{
|
{
|
||||||
StaminaText->SetText(MakeResourceText(TEXT("ST"), Stamina, MaxStamina));
|
StaminaText->SetText(MakeResourceText(TEXT("ST"), Stamina, MaxStamina));
|
||||||
@@ -141,4 +409,12 @@ void UPHYHUDStatusWidget::UpdateResourceWidgets()
|
|||||||
{
|
{
|
||||||
StaminaBar->SetPercent(MakeResourcePercent(Stamina, MaxStamina));
|
StaminaBar->SetPercent(MakeResourcePercent(Stamina, MaxStamina));
|
||||||
}
|
}
|
||||||
|
if (ExperienceText)
|
||||||
|
{
|
||||||
|
ExperienceText->SetText(MakeProgressionText(Experience, ExperienceForNextLevel));
|
||||||
|
}
|
||||||
|
if (ExperienceBar)
|
||||||
|
{
|
||||||
|
ExperienceBar->SetPercent(MakeProgressionPercent(Experience, ExperienceForNextLevel));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class UPHYCoreAttributeSet;
|
|||||||
class UPHYElementAttributeSet;
|
class UPHYElementAttributeSet;
|
||||||
class UPHYClassComponent;
|
class UPHYClassComponent;
|
||||||
|
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FPHYPlayerProgressionChangedSignature, int32, NewLevel, int32, NewExperience, int32, NewExperienceForNextLevel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PHY 玩家状态。
|
* @brief PHY 玩家状态。
|
||||||
*
|
*
|
||||||
@@ -27,6 +29,9 @@ public:
|
|||||||
/** @brief 构造玩家状态与 ASC。 */
|
/** @brief 构造玩家状态与 ASC。 */
|
||||||
APHYPlayerState(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
APHYPlayerState(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
||||||
|
|
||||||
|
/** @brief 注册 PlayerState 自身复制字段。 */
|
||||||
|
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
|
||||||
|
|
||||||
/** @brief 获取玩家持久 AbilitySystemComponent。 */
|
/** @brief 获取玩家持久 AbilitySystemComponent。 */
|
||||||
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
|
virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
|
||||||
|
|
||||||
@@ -50,7 +55,50 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Class")
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Class")
|
||||||
UPHYClassComponent* GetClassComponent() const { return ClassComponent; }
|
UPHYClassComponent* GetClassComponent() const { return ClassComponent; }
|
||||||
|
|
||||||
|
/** @brief 获取当前角色等级。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Progression")
|
||||||
|
int32 GetPlayerLevel() const { return PlayerLevel; }
|
||||||
|
|
||||||
|
/** @brief 获取当前经验值。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Progression")
|
||||||
|
int32 GetExperience() const { return Experience; }
|
||||||
|
|
||||||
|
/** @brief 获取升到下一级所需经验值。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintPure, Category="PHY|Progression")
|
||||||
|
int32 GetExperienceForNextLevel() const { return ExperienceForNextLevel; }
|
||||||
|
|
||||||
|
/** @brief 服务端设置角色等级。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="PHY|Progression")
|
||||||
|
void SetPlayerLevel(int32 NewLevel);
|
||||||
|
|
||||||
|
/** @brief 服务端设置当前经验值。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="PHY|Progression")
|
||||||
|
void SetExperience(int32 NewExperience);
|
||||||
|
|
||||||
|
/** @brief 服务端增加当前经验值。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="PHY|Progression")
|
||||||
|
void AddExperience(int32 DeltaExperience);
|
||||||
|
|
||||||
|
/** @brief 服务端设置下一级所需经验值。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="PHY|Progression")
|
||||||
|
void SetExperienceForNextLevel(int32 NewExperienceForNextLevel);
|
||||||
|
|
||||||
|
/** @brief 服务端一次性设置角色成长状态。 */
|
||||||
|
UFUNCTION(BlueprintCallable, BlueprintAuthorityOnly, Category="PHY|Progression")
|
||||||
|
void SetProgression(int32 NewLevel, int32 NewExperience, int32 NewExperienceForNextLevel);
|
||||||
|
|
||||||
|
/** @brief 等级或经验变化时通知本地 UI。 */
|
||||||
|
UPROPERTY(BlueprintAssignable, Category="PHY|Progression")
|
||||||
|
FPHYPlayerProgressionChangedSignature OnProgressionChanged;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/** @brief 复制后通知本地 UI 刷新成长信息。 */
|
||||||
|
UFUNCTION()
|
||||||
|
void OnRep_Progression();
|
||||||
|
|
||||||
|
/** @brief 广播当前成长状态。 */
|
||||||
|
void BroadcastProgressionChanged();
|
||||||
|
|
||||||
/** @brief 玩家持久 ASC。 */
|
/** @brief 玩家持久 ASC。 */
|
||||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|PlayerState")
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|PlayerState")
|
||||||
TObjectPtr<UGGA_AbilitySystemComponent> AbilitySystemComponent;
|
TObjectPtr<UGGA_AbilitySystemComponent> AbilitySystemComponent;
|
||||||
@@ -70,4 +118,16 @@ protected:
|
|||||||
/** @brief 玩家持久职业组件,职业不保存在 PlayerCharacter 上。 */
|
/** @brief 玩家持久职业组件,职业不保存在 PlayerCharacter 上。 */
|
||||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Class")
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="PHY|Class")
|
||||||
TObjectPtr<UPHYClassComponent> ClassComponent;
|
TObjectPtr<UPHYClassComponent> ClassComponent;
|
||||||
|
|
||||||
|
/** @brief 当前角色等级,由服务端复制给客户端 UI。 */
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, ReplicatedUsing=OnRep_Progression, Category="PHY|Progression")
|
||||||
|
int32 PlayerLevel = 1;
|
||||||
|
|
||||||
|
/** @brief 当前经验值,由服务端复制给客户端 UI。 */
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, ReplicatedUsing=OnRep_Progression, Category="PHY|Progression")
|
||||||
|
int32 Experience = 0;
|
||||||
|
|
||||||
|
/** @brief 当前等级升到下一级所需经验值,由服务端复制给客户端 UI。 */
|
||||||
|
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, ReplicatedUsing=OnRep_Progression, Category="PHY|Progression")
|
||||||
|
int32 ExperienceForNextLevel = 100;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,13 +6,17 @@
|
|||||||
#include "UI/GUIS_ActivatableWidget.h"
|
#include "UI/GUIS_ActivatableWidget.h"
|
||||||
#include "PHYHUDStatusWidget.generated.h"
|
#include "PHYHUDStatusWidget.generated.h"
|
||||||
|
|
||||||
|
class APlayerController;
|
||||||
|
class APHYPlayerState;
|
||||||
|
class UAbilitySystemComponent;
|
||||||
class UProgressBar;
|
class UProgressBar;
|
||||||
class UTextBlock;
|
class UTextBlock;
|
||||||
|
struct FOnAttributeChangeData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief PHY 默认 HUD 状态控件。
|
* @brief PHY 默认 HUD 状态控件。
|
||||||
*
|
*
|
||||||
* 作为基础 UI 的 C++ 可见占位,后续战斗、背包、队伍等系统可以替换或扩展为项目资产。
|
* 作为基础 UI 的 C++ 可见占位,绑定 PlayerState 上的 GAS 资源属性和成长状态。
|
||||||
*/
|
*/
|
||||||
UCLASS(BlueprintType, Blueprintable)
|
UCLASS(BlueprintType, Blueprintable)
|
||||||
class PHY_API UPHYHUDStatusWidget : public UGUIS_ActivatableWidget
|
class PHY_API UPHYHUDStatusWidget : public UGUIS_ActivatableWidget
|
||||||
@@ -29,19 +33,69 @@ public:
|
|||||||
/** @brief 同步文本和进度条显示。 */
|
/** @brief 同步文本和进度条显示。 */
|
||||||
virtual void SynchronizeProperties() override;
|
virtual void SynchronizeProperties() override;
|
||||||
|
|
||||||
|
/** @brief 绑定本地玩家控制器,随后从 PlayerState 和 GAS 拉取状态。 */
|
||||||
|
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
||||||
|
void InitializeFromPlayer(APlayerController* InPlayerController);
|
||||||
|
|
||||||
|
/** @brief 从当前绑定来源重新拉取 PlayerState、ASC、资源和成长信息。 */
|
||||||
|
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
||||||
|
void RefreshFromBoundSources();
|
||||||
|
|
||||||
/** @brief 设置生命值显示。 */
|
/** @brief 设置生命值显示。 */
|
||||||
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
||||||
void SetHealth(float NewHealth, float NewMaxHealth);
|
void SetHealth(float NewHealth, float NewMaxHealth);
|
||||||
|
|
||||||
|
/** @brief 设置法力值显示。 */
|
||||||
|
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
||||||
|
void SetMana(float NewMana, float NewMaxMana);
|
||||||
|
|
||||||
/** @brief 设置耐力值显示。 */
|
/** @brief 设置耐力值显示。 */
|
||||||
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
||||||
void SetStamina(float NewStamina, float NewMaxStamina);
|
void SetStamina(float NewStamina, float NewMaxStamina);
|
||||||
|
|
||||||
|
/** @brief 设置等级和经验显示。 */
|
||||||
|
UFUNCTION(BlueprintCallable, Category="PHY|UI")
|
||||||
|
void SetProgression(int32 NewLevel, int32 NewExperience, int32 NewExperienceForNextLevel);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/** @brief Widget 构造后尝试自动绑定 OwningPlayer。 */
|
||||||
|
virtual void NativeConstruct() override;
|
||||||
|
|
||||||
|
/** @brief Widget 销毁前解除 GAS 与 PlayerState 委托。 */
|
||||||
|
virtual void NativeDestruct() override;
|
||||||
|
|
||||||
|
/** @brief PlayerState 延迟到达时重试绑定。 */
|
||||||
|
virtual void NativeTick(const FGeometry& MyGeometry, float InDeltaTime) override;
|
||||||
|
|
||||||
/** @brief 构造原生 HUD 树。 */
|
/** @brief 构造原生 HUD 树。 */
|
||||||
void BuildNativeWidgetTree();
|
void BuildNativeWidgetTree();
|
||||||
|
|
||||||
/** @brief 刷新单条资源文本和进度条。 */
|
/** @brief 绑定新的 PlayerState 成长状态来源。 */
|
||||||
|
void BindToPlayerState(APHYPlayerState* NewPlayerState);
|
||||||
|
|
||||||
|
/** @brief 解除 PlayerState 成长状态来源。 */
|
||||||
|
void UnbindFromPlayerState();
|
||||||
|
|
||||||
|
/** @brief 绑定新的 AbilitySystemComponent 属性来源。 */
|
||||||
|
void BindToAbilitySystem(UAbilitySystemComponent* NewAbilitySystemComponent);
|
||||||
|
|
||||||
|
/** @brief 解除 AbilitySystemComponent 属性来源。 */
|
||||||
|
void UnbindFromAbilitySystem();
|
||||||
|
|
||||||
|
/** @brief 从 GAS 当前数值刷新生命、法力、耐力。 */
|
||||||
|
void RefreshResourcesFromAbilitySystem();
|
||||||
|
|
||||||
|
/** @brief 从 PlayerState 当前数值刷新等级、经验。 */
|
||||||
|
void RefreshProgressionFromPlayerState();
|
||||||
|
|
||||||
|
/** @brief GAS 属性变化后刷新资源条。 */
|
||||||
|
void HandleAttributeChanged(const FOnAttributeChangeData& ChangeData);
|
||||||
|
|
||||||
|
/** @brief PlayerState 成长信息变化后刷新显示。 */
|
||||||
|
UFUNCTION()
|
||||||
|
void HandleProgressionChanged(int32 NewLevel, int32 NewExperience, int32 NewExperienceForNextLevel);
|
||||||
|
|
||||||
|
/** @brief 刷新所有文本和进度条。 */
|
||||||
void UpdateResourceWidgets();
|
void UpdateResourceWidgets();
|
||||||
|
|
||||||
/** @brief 当前生命值。 */
|
/** @brief 当前生命值。 */
|
||||||
@@ -52,6 +106,14 @@ protected:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
float MaxHealth = 100.0f;
|
float MaxHealth = 100.0f;
|
||||||
|
|
||||||
|
/** @brief 当前法力值。 */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
|
float Mana = 100.0f;
|
||||||
|
|
||||||
|
/** @brief 当前最大法力值。 */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
|
float MaxMana = 100.0f;
|
||||||
|
|
||||||
/** @brief 当前耐力值。 */
|
/** @brief 当前耐力值。 */
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
float Stamina = 100.0f;
|
float Stamina = 100.0f;
|
||||||
@@ -60,10 +122,42 @@ protected:
|
|||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
float MaxStamina = 100.0f;
|
float MaxStamina = 100.0f;
|
||||||
|
|
||||||
|
/** @brief 当前角色等级。 */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
|
int32 Level = 1;
|
||||||
|
|
||||||
|
/** @brief 当前经验值。 */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
|
int32 Experience = 0;
|
||||||
|
|
||||||
|
/** @brief 当前等级升到下一级所需经验值。 */
|
||||||
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="PHY|UI")
|
||||||
|
int32 ExperienceForNextLevel = 100;
|
||||||
|
|
||||||
|
/** @brief 当前绑定的本地玩家控制器弱引用。 */
|
||||||
|
TWeakObjectPtr<APlayerController> BoundPlayerController;
|
||||||
|
|
||||||
|
/** @brief 当前绑定的玩家状态弱引用。 */
|
||||||
|
TWeakObjectPtr<APHYPlayerState> BoundPlayerState;
|
||||||
|
|
||||||
|
/** @brief 当前绑定的 ASC 弱引用。 */
|
||||||
|
TWeakObjectPtr<UAbilitySystemComponent> BoundAbilitySystemComponent;
|
||||||
|
|
||||||
|
FDelegateHandle HealthChangedHandle;
|
||||||
|
FDelegateHandle MaxHealthChangedHandle;
|
||||||
|
FDelegateHandle ManaChangedHandle;
|
||||||
|
FDelegateHandle MaxManaChangedHandle;
|
||||||
|
FDelegateHandle StaminaChangedHandle;
|
||||||
|
FDelegateHandle MaxStaminaChangedHandle;
|
||||||
|
|
||||||
/** @brief 标题文本。 */
|
/** @brief 标题文本。 */
|
||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
TObjectPtr<UTextBlock> TitleText;
|
TObjectPtr<UTextBlock> TitleText;
|
||||||
|
|
||||||
|
/** @brief 等级文本。 */
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TObjectPtr<UTextBlock> LevelText;
|
||||||
|
|
||||||
/** @brief 生命文本。 */
|
/** @brief 生命文本。 */
|
||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
TObjectPtr<UTextBlock> HealthText;
|
TObjectPtr<UTextBlock> HealthText;
|
||||||
@@ -72,6 +166,14 @@ protected:
|
|||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
TObjectPtr<UProgressBar> HealthBar;
|
TObjectPtr<UProgressBar> HealthBar;
|
||||||
|
|
||||||
|
/** @brief 法力文本。 */
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TObjectPtr<UTextBlock> ManaText;
|
||||||
|
|
||||||
|
/** @brief 法力进度条。 */
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TObjectPtr<UProgressBar> ManaBar;
|
||||||
|
|
||||||
/** @brief 耐力文本。 */
|
/** @brief 耐力文本。 */
|
||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
TObjectPtr<UTextBlock> StaminaText;
|
TObjectPtr<UTextBlock> StaminaText;
|
||||||
@@ -79,4 +181,12 @@ protected:
|
|||||||
/** @brief 耐力进度条。 */
|
/** @brief 耐力进度条。 */
|
||||||
UPROPERTY(Transient)
|
UPROPERTY(Transient)
|
||||||
TObjectPtr<UProgressBar> StaminaBar;
|
TObjectPtr<UProgressBar> StaminaBar;
|
||||||
|
|
||||||
|
/** @brief 经验文本。 */
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TObjectPtr<UTextBlock> ExperienceText;
|
||||||
|
|
||||||
|
/** @brief 经验进度条。 */
|
||||||
|
UPROPERTY(Transient)
|
||||||
|
TObjectPtr<UProgressBar> ExperienceBar;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user