Füge HealthDebuff-Mechanik hinzu

Die HealthComponent wurde erweitert, um einen neuen `HealthDebuff`-Wert zu unterstützen, der einen Teil der maximalen Gesundheit des Charakters unbrauchbar macht.

- Neue Methoden `GetHealthDebuff`, `SetHealthDebuff` und `GetEffectiveMaxHealth` hinzugefügt.
- `CurrentHealth` wird nun gegen den effektiven Maximalwert (`GetEffectiveMaxHealth`) begrenzt.
- Neues Event `OnHealthDebuffChanged` implementiert, um Änderungen am Debuff zu signalisieren.
- HealthBar-Widget aktualisiert, um den `HealthDebuff` dynamisch anzuzeigen.
- Sprint-Logik verbessert: Sprinten nur möglich, wenn der Charakter am Boden ist.
- Binärdateien (`BP_ThirdPersonCharacter.uasset`, `WBP_StaminaBar.uasset`) geändert.
This commit is contained in:
2026-08-28 00:01:16 +02:00
parent 83cc8f592e
commit 495424a2b2
7 changed files with 60 additions and 10 deletions
Binary file not shown.
+27 -3
View File
@@ -9,7 +9,7 @@ void UHealthComponent::BeginPlay()
{
Super::BeginPlay();
CurrentHealth = MaxHealth;
CurrentHealth = GetEffectiveMaxHealth();
}
float UHealthComponent::GetHealth() const
@@ -22,18 +22,28 @@ float UHealthComponent::GetMaxHealth() const
return MaxHealth;
}
float UHealthComponent::GetHealthDebuff() const
{
return HealthDebuff;
}
float UHealthComponent::GetEffectiveMaxHealth() const
{
return MaxHealth * (1.0f - HealthDebuff);
}
void UHealthComponent::SetMaxHealth(float NewMaxHealth)
{
MaxHealth = FMath::Max(NewMaxHealth, 0.0f);
CurrentHealth = FMath::Clamp(CurrentHealth, 0.0f, MaxHealth);
CurrentHealth = FMath::Clamp(CurrentHealth, 0.0f, GetEffectiveMaxHealth());
}
void UHealthComponent::SetHealth(float NewHealth)
{
const float PreviousHealth = CurrentHealth;
CurrentHealth = FMath::Clamp(NewHealth, 0.0f, MaxHealth);
CurrentHealth = FMath::Clamp(NewHealth, 0.0f, GetEffectiveMaxHealth());
OnHealthChanged.Broadcast(CurrentHealth);
@@ -63,3 +73,17 @@ void UHealthComponent::RemoveHealth(float Amount)
SetHealth(CurrentHealth - Amount);
}
void UHealthComponent::SetHealthDebuff(float NewHealthDebuff)
{
HealthDebuff = FMath::Clamp(NewHealthDebuff, 0.0f, 1.0f);
const float ClampedHealth = FMath::Clamp(CurrentHealth, 0.0f, GetEffectiveMaxHealth());
if (!FMath::IsNearlyEqual(ClampedHealth, CurrentHealth))
{
CurrentHealth = ClampedHealth;
OnHealthChanged.Broadcast(CurrentHealth);
}
OnHealthDebuffChanged.Broadcast(HealthDebuff);
}
@@ -5,6 +5,7 @@
#include "HealthComponent.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthDebuffChanged, float, NewHealthDebuff);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
@@ -23,9 +24,14 @@ public:
UFUNCTION(BlueprintPure, Category = "Health")
float GetHealth() const;
/** Nominal cap, unaffected by HealthDebuff. Feeds the health bar's total width. */
UFUNCTION(BlueprintPure, Category = "Health")
float GetMaxHealth() const;
/** 0-1 fraction of MaxHealth currently locked/unusable (curses, status effects, ...). */
UFUNCTION(BlueprintPure, Category = "Health")
float GetHealthDebuff() const;
UFUNCTION(BlueprintCallable, Category = "Health")
void SetMaxHealth(float NewMaxHealth);
@@ -38,17 +44,30 @@ public:
UFUNCTION(BlueprintCallable, Category = "Health")
void RemoveHealth(float Amount);
/** Sets how much of MaxHealth is currently locked away (0-1). Not driven by anything yet - a future debuff/curse/status-effect system calls this. */
UFUNCTION(BlueprintCallable, Category = "Health")
void SetHealthDebuff(float NewHealthDebuff);
protected:
/** MaxHealth minus whatever HealthDebuff currently locks away - what Health is actually clamped against. */
float GetEffectiveMaxHealth() const;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health")
float MaxHealth = 100.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
float CurrentHealth = 100.0f;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
float HealthDebuff = 0.0f;
public:
UPROPERTY(BlueprintAssignable, Category = "Health")
FOnHealthChanged OnHealthChanged;
UPROPERTY(BlueprintAssignable, Category = "Health")
FOnHealthDebuffChanged OnHealthDebuffChanged;
UPROPERTY(BlueprintAssignable, Category = "Health")
FOnDeath OnDeath;
};
@@ -69,8 +69,9 @@ void AKingshearthLegacyCharacter::Tick(float DeltaSeconds)
}
const bool bIsMoving = GetVelocity().SizeSquared() > FMath::Square(SprintMovementThreshold);
const bool bIsGrounded = GetCharacterMovement()->IsMovingOnGround();
if (bWantsToSprint && bIsMoving && StaminaComponent->GetStamina() > 0.0f)
if (bWantsToSprint && bIsMoving && bIsGrounded && StaminaComponent->GetStamina() > 0.0f)
{
GetCharacterMovement()->MaxWalkSpeed = BaseWalkSpeed * SprintSpeedMultiplier;
StaminaComponent->RemoveStamina(SprintStaminaDrainRate * DeltaSeconds);
@@ -11,16 +11,18 @@ void UHealthBarWidget::InitializeHealthBar(UHealthComponent* InHealthComponent)
if (HealthComponent)
{
HealthComponent->OnHealthChanged.RemoveDynamic(this, &UHealthBarWidget::HandleHealthChanged);
HealthComponent->OnHealthDebuffChanged.RemoveDynamic(this, &UHealthBarWidget::HandleHealthDebuffChanged);
HealthComponent->OnDeath.RemoveDynamic(this, &UHealthBarWidget::HandleDeath);
}
HealthComponent = InHealthComponent;
HealthComponent->OnHealthChanged.AddDynamic(this, &UHealthBarWidget::HandleHealthChanged);
HealthComponent->OnHealthDebuffChanged.AddDynamic(this, &UHealthBarWidget::HandleHealthDebuffChanged);
HealthComponent->OnDeath.AddDynamic(this, &UHealthBarWidget::HandleDeath);
SetStatValue(HealthComponent->GetHealth(), HealthComponent->GetMaxHealth());
SetMaxHealthDebuff(DefaultMaxHealthDebuffPercent);
SetMaxHealthDebuff(HealthComponent->GetHealthDebuff());
}
void UHealthBarWidget::SetMaxHealthDebuff(float InDebuffPercent)
@@ -36,6 +38,11 @@ void UHealthBarWidget::HandleHealthChanged(float NewHealth)
}
}
void UHealthBarWidget::HandleHealthDebuffChanged(float NewHealthDebuff)
{
SetMaxHealthDebuff(NewHealthDebuff);
}
void UHealthBarWidget::HandleDeath()
{
OnHealthDepleted();
@@ -27,6 +27,9 @@ protected:
UFUNCTION()
void HandleHealthChanged(float NewHealth);
UFUNCTION()
void HandleHealthDebuffChanged(float NewHealthDebuff);
UFUNCTION()
void HandleDeath();
@@ -36,8 +39,4 @@ protected:
UPROPERTY(BlueprintReadOnly, Category = "Health")
TObjectPtr<UHealthComponent> HealthComponent;
/** 0-1 starting max-health debuff applied in InitializeHealthBar, e.g. 0.1 = 10% of max health locked/unusable. Defaults to 0 since this bar reflects a live component. */
UPROPERTY(EditDefaultsOnly, Category = "Health")
float DefaultMaxHealthDebuffPercent = 0.0f;
};