Community Tutorial: LYRA: Friendly fire + damage from NPCs

Add an option for free-for-all and NPC damage.

https://dev.epicgames.com/community/learning/tutorials/3XXd/unreal-engine-lyra-friendly-fire-damage-from-npcs

Very nice implementation, simple but effective. I have optimized and remastered the code.
But Credits to you.

LyraExperienceDefinition.h

// _SR Start - Enables FriendlyFire -> Credit to Astaraa
	UPROPERTY(EditDefaultsOnly, Category=Gameplay, meta=(
		DisplayName="Enable Friendly Fire",
		ToolTip="TeamDamage active, SelfDamage optional, Minion-siblings blocked",
		EditCondition="!bEnableTrueFriendlyAndNPCDamage"
	))
	bool bEnableFriendlyAndNPCDamage = false;

	UPROPERTY(EditDefaultsOnly, Category=Gameplay, meta=(
		DisplayName="Enable True Friendly Fire",
		ToolTip="All damage allowedTeamDamage active, SelfDamage active, Minion-siblings active"
	))
	bool bEnableTrueFriendlyAndNPCDamage = false;

	UPROPERTY(EditDefaultsOnly, Category=Gameplay, meta=(
		DisplayName="Allow Self Damage when no Friend Fire",
		ToolTip="TeamDamage active, SelfDamage optional, Minion-siblings blocked",
		EditCondition="!bEnableTrueFriendlyAndNPCDamage"
	))
	bool bAllowSelfDamageWhenNoFriendlyFire = false;
	// _SR End

LyraDamageExecution.cpp

if (HitActor)
	{
		// _SR Start - Handles (True)friendly fire, SelfDamage and Minion-Siblings Damage- Credits for Base to Astaraa / Optimized SR
		bool bFriendlyFireEnabled = false;
		bool bTrueFriendlyFireEnabled = false;
		bool bAllowSelfDamageWhenFFOff = false;
		
		if (const AGameStateBase* GameState = HitActor->GetWorld()->GetGameState())
		{
			if (const auto* ExperienceManager = GameState->FindComponentByClass<ULyraExperienceManagerComponent>())
			{
				if (ExperienceManager->IsExperienceLoaded())
				{
					const ULyraExperienceDefinition* Experience = ExperienceManager->GetCurrentExperienceChecked(); 
					// Get variables from the LyraExperienceDefinition (can be configured/set there)
					bFriendlyFireEnabled = Experience->bEnableFriendlyAndNPCDamage;
					bTrueFriendlyFireEnabled = Experience->bEnableTrueFriendlyAndNPCDamage;
					bAllowSelfDamageWhenFFOff = Experience->bAllowSelfDamageWhenNoFriendlyFire;
				}
			}
		}

		// _SR Logic
		// SR - Precedence: TrueFriendly overrides Friendly
		const bool bUseTrueFriendly = bTrueFriendlyFireEnabled;
		const bool bUseFriendly = !bUseTrueFriendly && bFriendlyFireEnabled;

		// SR - Helpers to
		const AActor* CauserInst = EffectCauser ? EffectCauser->GetInstigator() : nullptr;
		const AActor* HitInst = HitActor ? HitActor->GetInstigator() : nullptr;
		const bool bIsSelfDamage = (EffectCauser == HitActor || CauserInst == HitActor);
		const bool bIsMinionSibling = CauserInst && HitInst && (CauserInst == HitInst);

		if (bUseTrueFriendly)
		{
			// SR Allows all damage to all, selfDamage, MinionSiblings damage
			DamageInteractionAllowedMultiplier = 1.0f;
		}
		// SR Allow friendly fire, selfDamage Optional, MinionSiblings damage
		else if (bUseFriendly)
		{
			if (bIsSelfDamage)
			{
				DamageInteractionAllowedMultiplier = (bAllowSelfDamageWhenFFOff) ? 1.0f : 0.0f;
			}
			else
			{
				DamageInteractionAllowedMultiplier = (!bIsMinionSibling) ? 1.0f : 0.0f;
			}
			
		}
		// SR - Default Damage from CanCauseDamage Function, SelfDamage Optional, MinionSiblings damage Blocked
		else
		{
			ULyraTeamSubsystem* TeamSubsystem = HitActor->GetWorld()->GetSubsystem<ULyraTeamSubsystem>();
			if (ensure(TeamSubsystem))
			{
				DamageInteractionAllowedMultiplier = TeamSubsystem->CanCauseDamage(EffectCauser, HitActor, bAllowSelfDamageWhenFFOff) ? 1.0f : 0.0f;
			}
		}
		// _SR End
		
	}

You could update the tutorial, just a possibility :slight_smile: