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();
|
Super::BeginPlay();
|
||||||
|
|
||||||
CurrentHealth = MaxHealth;
|
CurrentHealth = GetEffectiveMaxHealth();
|
||||||
}
|
}
|
||||||
|
|
||||||
float UHealthComponent::GetHealth() const
|
float UHealthComponent::GetHealth() const
|
||||||
@@ -22,18 +22,28 @@ float UHealthComponent::GetMaxHealth() const
|
|||||||
return MaxHealth;
|
return MaxHealth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float UHealthComponent::GetHealthDebuff() const
|
||||||
|
{
|
||||||
|
return HealthDebuff;
|
||||||
|
}
|
||||||
|
|
||||||
|
float UHealthComponent::GetEffectiveMaxHealth() const
|
||||||
|
{
|
||||||
|
return MaxHealth * (1.0f - HealthDebuff);
|
||||||
|
}
|
||||||
|
|
||||||
void UHealthComponent::SetMaxHealth(float NewMaxHealth)
|
void UHealthComponent::SetMaxHealth(float NewMaxHealth)
|
||||||
{
|
{
|
||||||
MaxHealth = FMath::Max(NewMaxHealth, 0.0f);
|
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)
|
void UHealthComponent::SetHealth(float NewHealth)
|
||||||
{
|
{
|
||||||
const float PreviousHealth = CurrentHealth;
|
const float PreviousHealth = CurrentHealth;
|
||||||
|
|
||||||
CurrentHealth = FMath::Clamp(NewHealth, 0.0f, MaxHealth);
|
CurrentHealth = FMath::Clamp(NewHealth, 0.0f, GetEffectiveMaxHealth());
|
||||||
|
|
||||||
OnHealthChanged.Broadcast(CurrentHealth);
|
OnHealthChanged.Broadcast(CurrentHealth);
|
||||||
|
|
||||||
@@ -63,3 +73,17 @@ void UHealthComponent::RemoveHealth(float Amount)
|
|||||||
|
|
||||||
SetHealth(CurrentHealth - 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"
|
#include "HealthComponent.generated.h"
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChanged, float, NewHealth);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthDebuffChanged, float, NewHealthDebuff);
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnDeath);
|
||||||
|
|
||||||
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
|
UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
|
||||||
@@ -23,9 +24,14 @@ public:
|
|||||||
UFUNCTION(BlueprintPure, Category = "Health")
|
UFUNCTION(BlueprintPure, Category = "Health")
|
||||||
float GetHealth() const;
|
float GetHealth() const;
|
||||||
|
|
||||||
|
/** Nominal cap, unaffected by HealthDebuff. Feeds the health bar's total width. */
|
||||||
UFUNCTION(BlueprintPure, Category = "Health")
|
UFUNCTION(BlueprintPure, Category = "Health")
|
||||||
float GetMaxHealth() const;
|
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")
|
UFUNCTION(BlueprintCallable, Category = "Health")
|
||||||
void SetMaxHealth(float NewMaxHealth);
|
void SetMaxHealth(float NewMaxHealth);
|
||||||
|
|
||||||
@@ -38,17 +44,30 @@ public:
|
|||||||
UFUNCTION(BlueprintCallable, Category = "Health")
|
UFUNCTION(BlueprintCallable, Category = "Health")
|
||||||
void RemoveHealth(float Amount);
|
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:
|
protected:
|
||||||
|
/** MaxHealth minus whatever HealthDebuff currently locks away - what Health is actually clamped against. */
|
||||||
|
float GetEffectiveMaxHealth() const;
|
||||||
|
|
||||||
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health")
|
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Health")
|
||||||
float MaxHealth = 100.0f;
|
float MaxHealth = 100.0f;
|
||||||
|
|
||||||
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
|
||||||
float CurrentHealth = 100.0f;
|
float CurrentHealth = 100.0f;
|
||||||
|
|
||||||
|
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Health")
|
||||||
|
float HealthDebuff = 0.0f;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
UPROPERTY(BlueprintAssignable, Category = "Health")
|
UPROPERTY(BlueprintAssignable, Category = "Health")
|
||||||
FOnHealthChanged OnHealthChanged;
|
FOnHealthChanged OnHealthChanged;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable, Category = "Health")
|
||||||
|
FOnHealthDebuffChanged OnHealthDebuffChanged;
|
||||||
|
|
||||||
UPROPERTY(BlueprintAssignable, Category = "Health")
|
UPROPERTY(BlueprintAssignable, Category = "Health")
|
||||||
FOnDeath OnDeath;
|
FOnDeath OnDeath;
|
||||||
};
|
};
|
||||||
@@ -69,8 +69,9 @@ void AKingshearthLegacyCharacter::Tick(float DeltaSeconds)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const bool bIsMoving = GetVelocity().SizeSquared() > FMath::Square(SprintMovementThreshold);
|
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;
|
GetCharacterMovement()->MaxWalkSpeed = BaseWalkSpeed * SprintSpeedMultiplier;
|
||||||
StaminaComponent->RemoveStamina(SprintStaminaDrainRate * DeltaSeconds);
|
StaminaComponent->RemoveStamina(SprintStaminaDrainRate * DeltaSeconds);
|
||||||
|
|||||||
@@ -11,16 +11,18 @@ void UHealthBarWidget::InitializeHealthBar(UHealthComponent* InHealthComponent)
|
|||||||
if (HealthComponent)
|
if (HealthComponent)
|
||||||
{
|
{
|
||||||
HealthComponent->OnHealthChanged.RemoveDynamic(this, &UHealthBarWidget::HandleHealthChanged);
|
HealthComponent->OnHealthChanged.RemoveDynamic(this, &UHealthBarWidget::HandleHealthChanged);
|
||||||
|
HealthComponent->OnHealthDebuffChanged.RemoveDynamic(this, &UHealthBarWidget::HandleHealthDebuffChanged);
|
||||||
HealthComponent->OnDeath.RemoveDynamic(this, &UHealthBarWidget::HandleDeath);
|
HealthComponent->OnDeath.RemoveDynamic(this, &UHealthBarWidget::HandleDeath);
|
||||||
}
|
}
|
||||||
|
|
||||||
HealthComponent = InHealthComponent;
|
HealthComponent = InHealthComponent;
|
||||||
|
|
||||||
HealthComponent->OnHealthChanged.AddDynamic(this, &UHealthBarWidget::HandleHealthChanged);
|
HealthComponent->OnHealthChanged.AddDynamic(this, &UHealthBarWidget::HandleHealthChanged);
|
||||||
|
HealthComponent->OnHealthDebuffChanged.AddDynamic(this, &UHealthBarWidget::HandleHealthDebuffChanged);
|
||||||
HealthComponent->OnDeath.AddDynamic(this, &UHealthBarWidget::HandleDeath);
|
HealthComponent->OnDeath.AddDynamic(this, &UHealthBarWidget::HandleDeath);
|
||||||
|
|
||||||
SetStatValue(HealthComponent->GetHealth(), HealthComponent->GetMaxHealth());
|
SetStatValue(HealthComponent->GetHealth(), HealthComponent->GetMaxHealth());
|
||||||
SetMaxHealthDebuff(DefaultMaxHealthDebuffPercent);
|
SetMaxHealthDebuff(HealthComponent->GetHealthDebuff());
|
||||||
}
|
}
|
||||||
|
|
||||||
void UHealthBarWidget::SetMaxHealthDebuff(float InDebuffPercent)
|
void UHealthBarWidget::SetMaxHealthDebuff(float InDebuffPercent)
|
||||||
@@ -36,6 +38,11 @@ void UHealthBarWidget::HandleHealthChanged(float NewHealth)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UHealthBarWidget::HandleHealthDebuffChanged(float NewHealthDebuff)
|
||||||
|
{
|
||||||
|
SetMaxHealthDebuff(NewHealthDebuff);
|
||||||
|
}
|
||||||
|
|
||||||
void UHealthBarWidget::HandleDeath()
|
void UHealthBarWidget::HandleDeath()
|
||||||
{
|
{
|
||||||
OnHealthDepleted();
|
OnHealthDepleted();
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ protected:
|
|||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void HandleHealthChanged(float NewHealth);
|
void HandleHealthChanged(float NewHealth);
|
||||||
|
|
||||||
|
UFUNCTION()
|
||||||
|
void HandleHealthDebuffChanged(float NewHealthDebuff);
|
||||||
|
|
||||||
UFUNCTION()
|
UFUNCTION()
|
||||||
void HandleDeath();
|
void HandleDeath();
|
||||||
|
|
||||||
@@ -36,8 +39,4 @@ protected:
|
|||||||
|
|
||||||
UPROPERTY(BlueprintReadOnly, Category = "Health")
|
UPROPERTY(BlueprintReadOnly, Category = "Health")
|
||||||
TObjectPtr<UHealthComponent> HealthComponent;
|
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