Lyra Shield, how to switch to health?

I managed to add a “Shield” attribute. I added it to healthset. I also have the variables in Health component for Shield change and other functions that the health has. I managed to link a “Shield” bar onto the UI. It has the same functions as the health bar. As I have the C++ set atm. Instead of the character losing health on damage from guns or damage pad. They lose Shield. Everything to that point works. I have very limited knowledge of c++

So, my question. What do I add to the c++?
I want the bOutOfShield to be called when shield is equal to 0. and Damage to be subtracted from Health instead.

HealthSet.h

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

include “AbilitySystemComponent.h”
include “LyraAttributeSet.h”
include “NativeGameplayTags.h”

include “LyraHealthSet.generated.h”

class UObject;
struct FFrame;

UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_Damage);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_DamageImmunity);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_DamageSelfDestruct);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Gameplay_FellOutOfWorld);
UE_DECLARE_GAMEPLAY_TAG_EXTERN(TAG_Lyra_Damage_Message);

struct FGameplayEffectModCallbackData;

/**

  • ULyraHealthSet
  • Class that defines attributes that are necessary for taking damage.
  • Attribute examples include: health, shields, and resistances.
    */
    UCLASS(BlueprintType)
    class ULyraHealthSet : public ULyraAttributeSet
    {
    GENERATED_BODY()

public:

ULyraHealthSet();

ATTRIBUTE_ACCESSORS(ULyraHealthSet, Health);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, MaxHealth);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, Shield);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, MaxShield);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, Healing);
ATTRIBUTE_ACCESSORS(ULyraHealthSet, Damage);

// Delegate to broadcast when the health attribute reaches zero.
mutable FLyraAttributeEvent OnOutOfHealth;
mutable FLyraAttributeEvent OnOutOfShield;

protected:

UFUNCTION()
void OnRep_Health(const FGameplayAttributeData& OldValue);

UFUNCTION()
void OnRep_MaxHealth(const FGameplayAttributeData& OldValue);

UFUNCTION()
void OnRep_Shield(const FGameplayAttributeData& OldValue);

UFUNCTION()
void OnRep_MaxShield(const FGameplayAttributeData& OldValue);

virtual bool PreGameplayEffectExecute(FGameplayEffectModCallbackData& Data) override;
virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;

virtual void PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const override;
virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
virtual void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override;

void ClampAttribute(const FGameplayAttribute& Attribute, float& NewValue) const;

private:

// The current health attribute.  The health will be capped by the max health attribute.  Health is hidden from modifiers so only executions can modify it.
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Lyra|Health", Meta = (HideFromModifiers, AllowPrivateAccess = true))
FGameplayAttributeData Health;

// The current max health attribute.  Max health is an attribute since gameplay effects can modify it.
UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_MaxHealth, Category = "Lyra|Health", Meta = (AllowPrivateAccess = true))
FGameplayAttributeData MaxHealth;

UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Lyra|Health", Meta = (HideFromModifiers, AllowPrivateAccess = true))
	FGameplayAttributeData Shield;

UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_Health, Category = "Lyra|Health", Meta = (HideFromModifiers, AllowPrivateAccess = true))
	FGameplayAttributeData MaxShield;


// Used to track when the health reaches 0.
bool bOutOfHealth;
bool bOutOfShield;

// -------------------------------------------------------------------
//	Meta Attribute (please keep attributes that aren't 'stateful' below 
// -------------------------------------------------------------------

private:
// Incoming healing. This is mapped directly to +Health
UPROPERTY(BlueprintReadOnly, Category=“Lyra|Health”, Meta=(AllowPrivateAccess=true))
FGameplayAttributeData Healing;

// Incoming damage. This is mapped directly to -Health
UPROPERTY(BlueprintReadOnly, Category="Lyra|Health", Meta=(HideFromModifiers, AllowPrivateAccess=true))
FGameplayAttributeData Damage;

};

HealthSet.cpp

// Copyright Epic Games, Inc. All Rights Reserved.

include “LyraHealthSet.h”
include “AbilitySystem/Attributes/LyraAttributeSet.h”
include “LyraGameplayTags.h”
include “Net/UnrealNetwork.h”
include “AbilitySystem/LyraAbilitySystemComponent.h”
include “Engine/World.h”
include “GameplayEffectExtension.h”
include “Messages/LyraVerbMessage.h”
include “GameFramework/GameplayMessageSubsystem.h”

include UE_INLINE_GENERATED_CPP_BY_NAME(LyraHealthSet)

UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_Damage, “Gameplay.Damage”);
UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_DamageImmunity, “Gameplay.DamageImmunity”);
UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_DamageSelfDestruct, “Gameplay.Damage.SelfDestruct”);
UE_DEFINE_GAMEPLAY_TAG(TAG_Gameplay_FellOutOfWorld, “Gameplay.Damage.FellOutOfWorld”);
UE_DEFINE_GAMEPLAY_TAG(TAG_Lyra_Damage_Message, “Lyra.Damage.Message”);

ULyraHealthSet::ULyraHealthSet()
: Health(100.0f)
, MaxHealth(100.0f)
, Shield(100.0f)
, MaxShield(100.0f)

{
bOutOfHealth = false;
bOutOfShield = false;
}

void ULyraHealthSet::GetLifetimeReplicatedProps(TArray& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps);

DOREPLIFETIME_CONDITION_NOTIFY(ULyraHealthSet, Health, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ULyraHealthSet, MaxHealth, COND_None, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ULyraHealthSet, Shield, COND_OwnerOnly, REPNOTIFY_Always);
DOREPLIFETIME_CONDITION_NOTIFY(ULyraHealthSet, MaxShield, COND_OwnerOnly, REPNOTIFY_Always);

}

void ULyraHealthSet::OnRep_Health(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULyraHealthSet, Health, OldValue);
}

void ULyraHealthSet::OnRep_MaxHealth(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULyraHealthSet, MaxHealth, OldValue);
}

void ULyraHealthSet::OnRep_Shield(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULyraHealthSet, Shield, OldValue);
}

void ULyraHealthSet::OnRep_MaxShield(const FGameplayAttributeData& OldValue)
{
GAMEPLAYATTRIBUTE_REPNOTIFY(ULyraHealthSet, MaxShield, OldValue);
}

bool ULyraHealthSet::PreGameplayEffectExecute(FGameplayEffectModCallbackData &Data)
{
if (!Super::PreGameplayEffectExecute(Data))
{
return false;
}

// Handle modifying incoming normal damage
if (Data.EvaluatedData.Attribute == GetDamageAttribute())
{
	if (Data.EvaluatedData.Magnitude > 0.0f)
	{
		const bool bIsDamageFromSelfDestruct = Data.EffectSpec.GetDynamicAssetTags().HasTagExact(TAG_Gameplay_DamageSelfDestruct);

		if (Data.Target.HasMatchingGameplayTag(TAG_Gameplay_DamageImmunity) && !bIsDamageFromSelfDestruct)
		{
			// Do not take away any health.
			Data.EvaluatedData.Magnitude = 0.0f;
			return false;
		}

#if !UE_BUILD_SHIPPING
// Check GodMode cheat, unlimited health is checked below
if (Data.Target.HasMatchingGameplayTag(LyraGameplayTags::Cheat_GodMode) && !bIsDamageFromSelfDestruct)
{
// Do not take away any health.
Data.EvaluatedData.Magnitude = 0.0f;
return false;
}
#endif // #if !UE_BUILD_SHIPPING
}
}

return true;

}

void ULyraHealthSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);

const bool bIsDamageFromSelfDestruct = Data.EffectSpec.GetDynamicAssetTags().HasTagExact(TAG_Gameplay_DamageSelfDestruct);
float MinimumShield = 0.0f;
float MinimumHealth = 0.0f;

#if !UE_BUILD_SHIPPING
// Godmode and unlimited health stop death unless it’s a self destruct
if (!bIsDamageFromSelfDestruct &&
(Data.Target.HasMatchingGameplayTag(LyraGameplayTags::Cheat_GodMode) || Data.Target.HasMatchingGameplayTag(LyraGameplayTags::Cheat_UnlimitedHealth) ))
{
MinimumHealth = 1.0f;
}
#endif // #if !UE_BUILD_SHIPPING

if (Data.EvaluatedData.Attribute == GetDamageAttribute())
{
	// Send a standardized verb message that other systems can observe
	if (Data.EvaluatedData.Magnitude > 0.0f)
	{
		FLyraVerbMessage Message;
		Message.Verb = TAG_Lyra_Damage_Message;
		Message.Instigator = Data.EffectSpec.GetEffectContext().GetEffectCauser();
		Message.InstigatorTags = *Data.EffectSpec.CapturedSourceTags.GetAggregatedTags();
		Message.Target = GetOwningActor();
		Message.TargetTags = *Data.EffectSpec.CapturedTargetTags.GetAggregatedTags();
		//@TODO: Fill out context tags, and any non-ability-system source/instigator tags
		//@TODO: Determine if it's an opposing team kill, self-own, team kill, etc...
		Message.Magnitude = Data.EvaluatedData.Magnitude;

		UGameplayMessageSubsystem& MessageSystem = UGameplayMessageSubsystem::Get(GetWorld());
		MessageSystem.BroadcastMessage(Message.Verb, Message);
	}

	// Convert into -Health and then clamp
	SetShield(FMath::Clamp(GetShield() - GetDamage(), MinimumShield, GetMaxShield()));
	SetDamage(0.0f);

}
else if (Data.EvaluatedData.Attribute == GetHealingAttribute())
{
	// Convert into +Health and then clamo
	SetShield(FMath::Clamp(GetShield() + GetHealing(), MinimumShield, GetMaxShield()));
	SetHealing(0.0f);
}
else if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
	// Clamp and fall into out of health handling below
	SetHealth(FMath::Clamp(GetHealth(), MinimumHealth, GetMaxHealth()));
}
if ((GetShield() <= 0.0f) && !bOutOfShield)
{
	if (OnOutOfShield.IsBound())
	{
		const FGameplayEffectContextHandle& EffectContext = Data.EffectSpec.GetEffectContext();
		AActor* Instigator = EffectContext.GetOriginalInstigator();
		AActor* Causer = EffectContext.GetEffectCauser();

		OnOutOfShield.Broadcast(Instigator, Causer, Data.EffectSpec, Data.EvaluatedData.Magnitude);
	}
}
if ((GetHealth() <= 0.0f) && !bOutOfHealth)
{
	if (OnOutOfHealth.IsBound())
	{
		const FGameplayEffectContextHandle& EffectContext = Data.EffectSpec.GetEffectContext();
		AActor* Instigator = EffectContext.GetOriginalInstigator();
		AActor* Causer = EffectContext.GetEffectCauser();

		OnOutOfHealth.Broadcast(Instigator, Causer, Data.EffectSpec, Data.EvaluatedData.Magnitude);
	}
}

// Check health again in case an event above changed it.
bOutOfHealth = (GetHealth() <= 0.0f);
bOutOfShield = (GetShield() <= 0.0f);

}

void ULyraHealthSet::PreAttributeBaseChange(const FGameplayAttribute& Attribute, float& NewValue) const
{
Super::PreAttributeBaseChange(Attribute, NewValue);

ClampAttribute(Attribute, NewValue);

}

void ULyraHealthSet::PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue)
{
Super::PreAttributeChange(Attribute, NewValue);

ClampAttribute(Attribute, NewValue);

}

void ULyraHealthSet::PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue)
{
Super::PostAttributeChange(Attribute, OldValue, NewValue);

if (Attribute == GetMaxHealthAttribute())
{
	// Make sure current health is not greater than the new max health.
	if (GetHealth() > NewValue)
	{
		ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent();
		check(LyraASC);

		LyraASC->ApplyModToAttribute(GetHealthAttribute(), EGameplayModOp::Override, NewValue);
	}
}

if (Attribute == GetMaxShieldAttribute())
{
	// Make sure current Shield is not greater than the new max Shield.
	if (GetShield() > NewValue)
	{
		ULyraAbilitySystemComponent* LyraASC = GetLyraAbilitySystemComponent();
		check(LyraASC);

		LyraASC->ApplyModToAttribute(GetShieldAttribute(), EGameplayModOp::Override, NewValue);
	}
}

if (bOutOfHealth && (GetHealth() > 0.0f))
{
	bOutOfHealth = false;
}
if (bOutOfShield && (GetShield() > 0.0f))
{
	bOutOfShield = false;
}

}

void ULyraHealthSet::ClampAttribute(const FGameplayAttribute& Attribute, float& NewValue) const
{
if (Attribute == GetHealthAttribute())
{
// Do not allow health to go negative or above max health.
NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxHealth());
}
else if (Attribute == GetMaxHealthAttribute())
{
// Do not allow max health to drop below 1.
NewValue = FMath::Max(NewValue, 1.0f);
}

if (Attribute == GetShieldAttribute())
{
	// Do not allow Shield to go negative or above max health.
	NewValue = FMath::Clamp(NewValue, 0.0f, GetMaxShield());
}
else if (Attribute == GetMaxShieldAttribute())
{
	// Do not allow max Shield to drop below 1.
	NewValue = FMath::Max(NewValue, 1.0f);
}

}

	if (!bOutOfShield)
	{
		// Convert into -Shield and then clamp
		SetShield(FMath::Clamp(GetShield() - GetDamage(), MinimumShield, GetMaxShield()));
		SetDamage(0.0f);
	}
	if (bOutOfShield)
	{
		// Convert into -Health and then clamp
		SetHealth(FMath::Clamp(GetHealth() - GetDamage(), MinimumHealth, GetMaxHealth()));
		SetDamage(0.0f);
	}

Set in .cpp
seems to be working for switching from one to the other. Still working on remaining damage being carried over from shield.