Skip to content

Damage And Mitigation

Applying Damage

First, let's discuss how damage is applied in the system.

First and foremost, to apply damage, you simply need to apply a Gameplay Effect to a Target that adds (or overrides) the value of the PendingDamage attribute. Once this Gameplay Effect is received by the Attribute Set, the damage processing (including the defense system), will be triggered.

Here's an example where the source's BaseDamage attribute is being added to the target's PendingDamage attribute.

Pending Damage

Add or Override Pending Damage

Adding will append this damage to any other damage that is being already added in this tick. Overriding will ensure that the actual damage is exclusively handled, and other potential amounts of damage are discarded. You may choose one or the other depending on your design. If you are unsure, adding is the safest approach.

Also, if you want to categorize this damage, so it can be properly identified later on during the Hit Reaction or Death phases, or even consider the damage type while defending it, make sure to add a Gameplay Tag that properly identifies this damage type.

Damage Tags

Damage Calculation

The Calculation can be more elaborate than just adding the value of BaseDamage. The system also supports attributes for Critical Damage: CriticalHitChance and CriticalHitMultiplier. You can use the provided Calculation Class, UCombatExecution_Damage, to account for these attributes. In which case, the calculation would be:

if critical_damage_chance_test 
then:
    pending_damage += base_damage * critical_damage_multiplier
else:
    pending_damage += base_damage

This calculation class also supports SetByCaller magnitudes, using the following Data Tags:

Gameplay Tag Description
Combat.Data.Damage Overrides the BaseDamage attribute.
Combat.Data.CriticalHitChance Overrides the CriticalHitChanceattribute.
Combat.Data.CriticalHitMultiplier Overrides the CriticalHitMultiplierattribute.

Furthermore, each step in this is broken down into proper functions, which can be extended in case you want to add more elements to the damage calculation.

This is how a Gameplay Effect using the Calculation Class looks like. Once again, note the presence of the Damage Tags, mentioned before, used to identify the damage. They might be useful in the Damage Calculation as well!

Damage Calculation

Breaking Defense and Breaking Stance

Damage effects can eventually break a target's defense/blocking stance. The most common reason for that is because they ran out of stamina to soak incoming damage. In which case, the damage will trigger a breaker hit.

Incoming damage can also reduce the target's poise. Once the target's poise reaches zero, it will be staggered, cancelling any ongoing action (attacks or evades).

If you want your attacks to affect poise, make sure to reduce the proper Poise attribute and to also apply the Tag_Combat_Effect_Cancel_Regeneration_Poise for a certain duration, which will cancel the immediate poise regeneration.

Base Effect Classes

The system provides two base Gameplay Effect classes that can be used to configure your Damage Effects. They are optional, but if used, they'll be properly setup with the Tags component and Calculation.

Base Class Description
UCombatEffect_MeleeHit Represents a hit resulting from a Melee Hit.
UCombatEffect_RangedHit Represents a hit resulting from a Ranged Hit.

Defending Damage

Once the PendingDamage change is received by the Attribute Set, it will invoke the owner's Defense Manager to defend against the incoming damage. This will consider the target's Block, Defense and Armor, plus the global Damage Modifier that we will check next.

Damage Mitigation

A combatant has a few layers of possible damage mitigation:

Mitigation Description
Invulnerability Completely ignores damage if the character is currently invulnerable.
Block Usually related to the usage of shields. Has a chance, reduction percent, limit, angle and stamina cost.
Defense Extra defense that can be applied from other sources. Has a chance, reduction percent, limit and stamina cost.
Armor Flat damage reduction from armor.
LastStand An "extra life" effect that can revert fatal damage. Has charges and a percent of max health returned.
Poise Not necessarily related to direct mitigation, but hits can affect poise. If poise reaches zero, the character is staggered.

Damage is defended in the following order:

if block_chance_test and block_stamina_test and block_angle_test
then:
    incoming_damage -= Min(incoming_damage * block_reduction, block_cap)
    mitigation_cost += block_cost * incoming_damage

if defense_chance_test and defense_stamina_test
then:
    incoming_damage -= Min(incoming_damage * defense_reduction, defense_cap)
    mitigation_cost += block_cost * incoming_damage

incoming_damage -= armor_mitigation

if is_fatal_damage then:
    apply_last_stand

By properly adjusting your attributes you can accomplish things like:

  • If the block or defense chances are 1 (meaning 100%), then the character always blocks.
  • If the block angle is 360, then the character can block damage from behind.
  • If the block or defense costs are 0, then no stamina is required to block or defend.
  • If the block or defense limits are 0, then they can mitigate as much damage as possible.

Invincibility

To make your character invincible, you simply need to apply the UCombatEffect_Invulnerability Effect.

If you want to create Invincibility Frames, commonly seen in abilities like rolling, then you can use the appropriate Gameplay Effect, which will communicate back to the ability (UCombatAbility_Evade) and apply the effect.

Global Damage Modifier

The system provides an interface, ICombatDamageModifierInterface that can be implemented by your Game Mode or Game State. If you do that, then every damage being applied can be modified by these classes, at the very first step of the damage mitigation.

Friendly Fire

This is useful if you want to remove something like "Friendly Fire". For example, let's say that you have the Ninja Factions plugin and can determine that two actors are members of the same faction. You can use this extension point to modify any damage between these actors, so it's always "zero".

The ICombatDamageModifierInterface has one function to be implemented: Modify Damage, with the following properties:

Property Description
Damage Final damage being tentativelly applied.
Instigator Instigator applying the damage.
Target Target receiving the damage.
Source Tags All gameplay tags collected from the incoming damage.
Target Tags All gameplay tags collected from the target.

Handling Received Damage

Now let's discuss how damage is received and processed.

Damage Manager Component

This component receives incoming damage and orchestrates the handling of these events.

The default implementation, UNinjaCombatDamageManagerComponent, is an implementation of the appropriate interface, ICombatDamageManagerInterface and added to the combatant via the Combat Manager (or reused if such component is already present in the owner).

This component is integrated with the Combat Attribute Set, since it applies damage and sends the event to the component. It's also responsible for broadcasting incoming damage to the "Receive Hit" and "Death" abilities, based on the damage being fatal or not.

Finally, this component is also responsible for providing a Hit Reaction system, via Gameplay Cues, but using a replicated list of recent damage, thus allowing these cues to be added locally and yet being fully replicated, without relying on Multicast RPCs.

Hit Reactions

Hit Reactions are implemented by the CombatAbility_ReceiveHit Gameplay Ability. This ability, by default, is activated by a Gameplay Event trigger. The event itself is broadcast by the Damage Manager, whenever necessary.

Whenever damage is applied to the Damage Component, not only Hit Reactions will be triggered for non-fatal damage, but the OnDamageReceived Multicast Delegate will broadcast with the damage information.

Stagger

If the Poise attribute has been fully depleted from a hit, a different type of Hit Reaction will be triggered. Instead of the default Hit Reaction, which may not interrupt actions, the CombatAbility_Stagger Gameplay Ability is triggered. This version of a Hit Reaction will interrupt actions.

Death

Hit Reactions are implemented by the CombatAbility_Death Gameplay Ability. This ability, by default, is activated by a Gameplay Event trigger. The event itself is broadcast by the Damage Manager, whenever necessary.

Death is also partially handled by the Damage Manager component, and if you decide to implement your own component, then make sure to account for this fact.

Whenever fatal damage is applied to the Damage Component, the Death Ability will be triggered and the OnOwnerDeath Multicast Delegate will broadcast the damage information.

Damage Entry

This Struct is commonly used by the Damage System. It aggregates damage information, for damage events that have been accepted and processed by the Damage Manager Component. When the Damage Manager stores recent damage (based on the setting from the Ninja Combat plugin), this is the struct used to do so.

Hit and Death Gameplay Cues

Damage events, non-fatal and fatal, can have cosmetics presented via the Gameplay Cue system. The Damage Manager component will use the GameplayCue.Combat.Hit and GameplayCue.Combat.Death cues for these events, respectivelly. In the GAS Integration page, there's a dedicated section explaining how to configure the systems default Combat Cue Manager to handle these events.

Damage Handlers

When damage is applied and accepted, a chain of Damage Handlers is triggered. These are defined by a UNinjaCombatDamageHandlerData asset assigned to your Damage Manager Component. This allows you to create a damage reaction via aggregation os small behaviors.

You can create Damage Handlers by extending the UNinjaCombatDamageHandler. By default, the system provides the following handlers:

  • Cosmetics: Allows a damage causer to handle damage cosmetics, via the proper ICombatMeleeInterface and ICombatProjectileInterface interface functions: HandleMeleeDamageCosmetics and HandleImpactCosmetics, respectivelly.

  • Damage Sense: Triggers the Damage AI sense to notify the AI Perception System about damage received. The actor who applied the damage (Instigator) is used in the Perception Event and the total amount of damage is used as the strength.

  • Physical Animation: Invokes the Physical Animation Component to play a physical animation.

  • Widget Component: Forwards the damage event to a widget component in the owner. This componnet must be the class provided by the Ninja Combat plugin, UNinjaCombatWidgetComponent, which is specialized to receive the Gameplay Cue and to properly set the Combat Actor as the component owner. More information is available in this page.