How-To: Query Attitude & Gate Damage

Goal: decide friend/foe, block friendly fire, and filter ability targets by attitude.

Prerequisites
Actors with team agent components and tags (Quick Start / How-To: Make an Actor a Team Agent).

1. Attitude & damage

cpp
// Full attitude (Hostile / Friendly / Neutral):
const ETeamAttitude::Type Att = UCrimsonTeamStatics::GetTeamAttitudeBetween(Source, Target);
// Friendly fire gate (true for Hostile or Neutral; false for Friendly):
const bool bCanDamage = UCrimsonTeamStatics::ShouldCauseDamageToTarget(Source, Target);
// Subsystem variant with a self-damage flag:
UCrimsonTeamSubsystem* TS = GetWorld()->GetSubsystem<UCrimsonTeamSubsystem>();
const bool bCan = TS->CanCauseDamage(Instigator, Target, /*bAllowDamageToSelf*/ true);
// Asking the opposite question - is this actor an ally? Use the direct query:
const bool bFriendly = TS->IsActorFriendly(Source, Other);
Do not negate the damage gate
IsActorFriendly is not !CanCauseDamage. CanCauseDamage returns true for self-damage, so negating it reports an actor as not friendly to itself; it also returns false for null actors. IsActorFriendly treats null and self as friendly and asks the attitude directly. Remember that Neutral is not friendly - an actor with no team agent component is reported as not friendly, even though damage against it is permitted.
Check at apply-time, not activation-time
Attitude is dynamic - a target can change teams mid-ability. Evaluate it when the hit actually lands, not when the ability starts, so a freshly-turned enemy (or ally) is judged correctly.

2. Filter ability targets by attitude

MakeFilteredTargetDataFromActors keeps only actors matching a filter and packages them as a FGameplayAbilityTargetDataHandle (self and nulls always excluded) - ideal for AoE.

ECrimsonTargetFilterKeeps
HostileAndNeutralDamage abilities (default)
HostileOnlyEnemy-only attacks
FriendlyAndNeutralSupport abilities
FriendlyOnlyHeals / buffs
AllIndiscriminate effects
cpp
FGameplayAbilityTargetDataHandle Data =
UCrimsonTeamStatics::MakeFilteredTargetDataFromActors(
AbilityOwner, OverlappingActors, ECrimsonTargetFilter::HostileAndNeutral);

3. Gate an interaction option by attitude

Putting the same attitude test on an interaction option (only allies may revive a downed player, only enemies may finish one off) joins this plugin to an interaction system, so that glue is not part of CrimsonTeams. Whatever gates your options, ask UCrimsonTeamStatics::GetTeamAttitudeBetween(Instigator, Target) and compare the result with an ECrimsonTargetFilter. Friendly already covers party members; Neutral is a separate answer, so accept FriendlyAndNeutral when you mean "not an enemy".

Ready-made: the Team Attitude condition
(CrimsonCore - requires all Crimson plugins; listed for orientation.) CrimsonCore ships UCrimsonInteractionCondition_TeamAttitude ("Team Attitude" in the condition picker, header Integration/Teams/CrimsonInteractionCondition_TeamAttitude.h): add it to an interaction option's conditions and set AllowedAttitudes. Without CrimsonCore, write the equivalent condition in your own interaction code around GetTeamAttitudeBetween, as shown below.

In your own condition or option check: Get Team Attitude Between (Source = the instigator, Target = the downed or targeted actor) -> compare the result with Friendly for a revive, or Hostile for a finishing move. Return false to hide or gray out the option for the wrong viewer.

Verify
Approach the interactable as a party mate and the option is offered; approach it on a hostile team and it is gone. Evaluate the check on the server as well as for the client-side prompt, so a client that fakes the option is refused.

See also

  • How-To: Debug at Runtime (Dev Tools) - the Attitude Matrix tab visualizes every pairing at once
  • API Reference - UCrimsonTeamStatics, UCrimsonTeamSubsystem