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:
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -62,4 +72,18 @@ 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;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user