// © 2024 Long Ly. All rights reserved. Any unauthorized use, reproduction, or distribution of this trademark is strictly prohibited and may result in legal action. #pragma once #include "CoreMinimal.h" #include "Components/GameFrameworkComponent.h" #include "OLSHealthComponent.generated.h" DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOLSDeathEventDynamicDelegate, class AActor*, owningActor); DECLARE_MULTICAST_DELEGATE_OneParam(FOLSDeathEventNativeDelegate, class AActor* /* owningActor */) DECLARE_DYNAMIC_MULTICAST_DELEGATE_FourParams(FOLSAttributeChangedDynamicDelegate, class UOLSHealthComponent*, healthComponent, float, oldValue, float, newValue, class AActor*, instigator); DECLARE_MULTICAST_DELEGATE_FourParams(FOLSAttributeChangedNativeDelegate, class UOLSHealthComponent* /* healthComponent */, float /* oldValue */, float /* newValue */, class AActor* /* instigator */) DECLARE_LOG_CATEGORY_EXTERN(LogOLSHealthComponent, Verbose, All); /** * EOLSDeathState * * Defines current state of death. */ UENUM(BlueprintType) enum class EOLSDeathState : uint8 { NotDead = 0, DeathStarted, DeathFinished }; /** * UOLSHealthComponent * * An actor component used to handle anything related to health. */ UCLASS(Blueprintable, Meta=(BlueprintSpawnableComponent)) class OLS_API UOLSHealthComponent : public UGameFrameworkComponent { GENERATED_BODY() public: // Sets default values for this component's properties UOLSHealthComponent(const FObjectInitializer& objectInitializer); //~ Begin UActorComponent interface. virtual void GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const override; //~ End UActorComponent interface. // Returns the health component if one exists on the specified actor. UFUNCTION(BlueprintPure, Category = "OLS|Health") static class UOLSHealthComponent* FindHealthComponent(const AActor* actor); // Initialize the component using an ability system component. UFUNCTION(BlueprintCallable, Category = "OLS|Health") void InitializeWithAbilitySystem(class UOLSAbilitySystemComponent* asc); // Uninitialize the component, clearing any references to the ability system. UFUNCTION(BlueprintCallable, Category = "OLS|Health") void UninitializeFromAbilitySystem(); // Returns the current health value. UFUNCTION(BlueprintCallable, Category = "OLS|Health") float GetHealth() const; // Returns the current maximum health value. UFUNCTION(BlueprintCallable, Category = "OLS|Health") float GetMaxHealth() const; // Returns the current health in the range [0.0, 1.0]. UFUNCTION(BlueprintCallable, Category = "OLS|Health") float GetHealthNormalized() const; UFUNCTION(BlueprintCallable, Category = "OLS|Health") EOLSDeathState GetDeathState() const; UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "OLS|Health", Meta = (ExpandBoolAsExecs = "ReturnValue")) bool IsDeadOrDying() const; // Begins the death sequence for the owner. virtual void StartDeath(); // Ends the death sequence for the owner. virtual void FinishDeath(); // Applies enough damage to kill the owner. virtual void DamageSelfDestruct(bool isFellOutOfWorld = false); public: // Delegate fired when the health value has changed. This is called on the client but the instigator may not be valid UPROPERTY(BlueprintAssignable) FOLSAttributeChangedDynamicDelegate OnHealthChangedDynamicDelegate; FOLSAttributeChangedNativeDelegate OnHealthChangedNativeDelegate; // Delegate fired when the max health value has changed. This is called on the client but the instigator may not be valid UPROPERTY(BlueprintAssignable) FOLSAttributeChangedDynamicDelegate OnMaxHealthChangedDynamicDelegate; FOLSAttributeChangedNativeDelegate OnMaxHealthChangedNativeDelegate; // Delegate fired when the death sequence has started. UPROPERTY(BlueprintAssignable) FOLSDeathEventDynamicDelegate OnDeathStartedDynamicDelegate; FOLSDeathEventNativeDelegate OnDeathStartNativeDelegate; // Delegate fired when the death sequence has finished. UPROPERTY(BlueprintAssignable) FOLSDeathEventDynamicDelegate OnDeathFinishedDynamicDelegate; FOLSDeathEventNativeDelegate OnDeathFinishedNativeDelegate; void Broadcast_OnHealthChanged(UOLSHealthComponent* healthComponent, float oldValue, float newValue, AActor* instigator) const; void Broadcast_OnMaxHealthChanged(UOLSHealthComponent* healthComponent, float oldValue, float newValue, AActor* instigator) const; void Broadcast_OnDeathStarted(class AActor* owningActor) const; void Broadcast_OnDeathFinished(class AActor* owningActor) const; protected: virtual void OnUnregister() override; void ClearGameplayTags(); virtual void HandleHealthChanged(AActor* damageInstigator, AActor* damageCauser, const struct FGameplayEffectSpec* damageEffectSpec, float damageMagnitude, float oldValue, float newValue); virtual void HandleMaxHealthChanged(AActor* damageInstigator, AActor* damageCauser, const struct FGameplayEffectSpec* damageEffectSpec, float damageMagnitude, float dldValue, float newValue); virtual void HandleOutOfHealth(AActor* damageInstigator, AActor* damageCauser, const struct FGameplayEffectSpec* damageEffectSpec, float damageMagnitude, float oldValue, float newValue); UFUNCTION() virtual void OnRep_DeathState(EOLSDeathState oldDeathState = EOLSDeathState::NotDead); protected: // Ability system used by this component. UPROPERTY() TObjectPtr AbilitySystemComponent = nullptr; // Health set used by this component. UPROPERTY() TObjectPtr HealthSet = nullptr; // Replicated state used to handle dying. UPROPERTY(ReplicatedUsing = OnRep_DeathState) EOLSDeathState DeathState = EOLSDeathState::NotDead; };