Combat Flow
CombatFlow is a UObject , and each combat system component can specify a CombatFlow. You should inherit the built-in GCS_BaseCombatFlow and override the relevant functions to implement your custom logic, or reference existing CombatFlow and create a new one.
Handling Attribute Changes
As mentioned in the Gameplay Attribute part, The AttributeSystemComponent forwards all attribute change callbacks to the CombatFlow for processing. Therefore, you only need to override HandleGameplayEffectExecute.

How to handle attribute changes and what kind of attack results to produce is entirely determined by your own game mechanics, while the default implementation provides common mechanics found in soul-like games.
Generating Attack Results
After processing attribute changes in HandleGameplayEffectExecute, you should convert the information from that process into attack results based on your game logic and register them with the combat system component.

For example, after handlingIncomingDamage, you should construct the relevant information into anAttackResultstructure and register it with the combat system.TaggedValuesincludes some information generated during this process, such as "actual changed health." You can also customize this here.
Customizing Combat Flow
Attackers can initiate different attack requests, but each target may have a different "handling" for each attack request. You can implement different attack handling processes by customizing GCS_CombatFlow and configuring different CombatFlow classes on the CombatSystemComponent.
For example, if an arrow is shot at an enemy, it should typically trigger a hit reaction. However, if your enemy is very large and you do not want them to react, you can specify a different CombatFlow without needing extensive if/else checks at the attacker level.
When to Use Completely Different Combat Flows?
- You don't want a dog to deflect your attack.
- You don't want a gigantic boss to fall over just because you scratched its foot.
- You don't want a building to dodge your attack.
Access Attack Request in the Combat Flow
The attack request itself is passed through the GameplayEffectContext in different processes, meaning you can access various information configured in the attack request at any time. For instance, you can retrieve the attack request object via the context and access its associated attack definition.

Good to Know
- The attack request is an instantiated
UObject, meaning it is not created at runtime but is created in the editor and stored on disk, which is the secret to its efficient network transmission. - The attack request is of type
Const, meaning it can only store static data for game logic use, and you should not modify it during gameplay. - If you define a variable of type
AttackRequestin Blueprints, you will see that it allows you to inline create an instance and save it with the outer asset.


Attack Results
Whenever CombatFlow processes an attack, it generates an attack result and records it in the combat system component, synchronizing it with the client over the network.
When a combat result is generated, GCS triggers different combat feedback based on its content, such as playing hit reactions or generating visual effects through gameplay cues.
Handling Attack Results
In CombatFlow, you can configure different AttackResultProcessors (attack result processors) in a data-driven manner to handle different attack results accordingly.


You can refer to the GCS_BaseCombatFlow Blueprint to understand the specific usage.
Built-in Attack Result Processors
Send Gampelay Event
This one allows you to send different gameplay events to attacker/victims based on attack results.

You can also use TagQuery to route different logic.
For example: only trigger BlockHit when the attack results's source tags have Blocktag. Only trigger hit reaction when attack results's source tags have Hittag.
Custom Attack Result Processors
For example: You can write a "Dmage Statistics Processor" which keeps track of received damage to other log systems.
