How-To: Add Your Own Augment Event
Augment events are not a fixed list in C++. Any gameplay tag under Augment.Event is an event. Declare the tag, broadcast it when your game knows the thing happened, and it appears in the augment editor's event picker with no registration step and no plugin change.
OnGranted, OnRemoved, OnActivate, OnEnd and OnEffectApplying - the moments it genuinely controls. It does not ship OnCrit or OnKill, because it has no idea what a crit is in your game and could never fire them. A tag that looks authorable but never runs is worse than no tag: the augment reads as correctly configured and silently does nothing.The two effect-application events
Applying a gameplay effect to targets is two distinct moments, and the plugin broadcasts both. Knowing which one you want is most of the work.
OnEffectApplying | OnEffectResolved | |
|---|---|---|
| When | Before application | After application, per target |
| Outcome known? | No - the execution has not run | Yes - crit, blocked, immune, damage type |
EventMagnitude | The spec's base value | The resolved value, post-mitigation |
ContextTags | Spec asset tags + ability family tags | The execution's outcome tags |
SpecHandleToModify | Valid - change the spec here | Unset; the effect has already landed |
| Runs on | Server, or a predicting client | Server only |
OnEffectResolved and set the gate's Required Context Tags to Damage.Result.Crit. The actions then run only on crits. The same works for Damage.Result.Blocked, a damage type, or any combination - those tags are already in the outcome, so no C++ is involved.OnHit until recently. That was wrong twice: the plugin has no concept of a "hit" - it applies effects, and whether an effect is damage is the effect's business - and the one broadcast happened before application, so it could never report an outcome. Splitting them means each carries data that is actually true at the moment it fires.Step 1 - declare the tag
Anywhere under Augment.Event. Nesting is allowed, so Augment.Event.Combat.OnParry works if you would rather group them than keep them flat.
Project Settings > Project > GameplayTags > Manage Gameplay Tags, then Add New Gameplay Tag. Name it Augment.Event.OnCrit and put a comment in the Dev Comment field - that comment becomes the tooltip in the augment editor's event picker, so write when it fires.
Step 2 - broadcast it
Call BroadcastAugmentEvent on the UCrimsonGameplayAbility that caused the thing. The payload carries whatever an augment reacting to the event will need: the targets, a magnitude, and context tags an action gate can test.
A working example: OnCrit
CrimsonCore ships this, and it is a good template because it shows the reasoning about where a broadcast belongs. A crit is decided by UCrimsonDamageExecution, which cannot broadcast - it is a calculation, not an ability. What it can do is stamp the outcome onto the effect context. The attribute set then sees that stamp while the damage is applied, on the server, with the instigating ability reachable.
CrimsonDamageExecution.cpp - the execution records the outcome:
// Stamped onto the shared context, which travels with the effect.if (bCrit) { Ctx->PopTag.AddTag(CrimsonGameplayTags::Damage_Result_Crit); }
CrimsonHealthSet.cpp - the attribute set broadcasts it:
// Inside PostGameplayEffectExecute, damage branch, already authority-gated.if (Ctx && Ctx->PopTag.HasTagExact(CrimsonGameplayTags::Damage_Result_Crit)){const UGameplayAbility* SourceAbility = Ctx->GetAbilityInstance_NotReplicated();if (UCrimsonGameplayAbility* CrimsonAbility =Cast<UCrimsonGameplayAbility>(const_cast<UGameplayAbility*>(SourceAbility))){FCrimsonAugmentEventPayload Payload;Payload.EventMagnitude = IncomingDamage;Payload.ContextTags = Ctx->PopTag; // gates can test Damage.Type.Fire, etc.// The victim, so an augment can target whoever was hit.if (AActor* HitActor = OwnerASC->GetAvatarActor_Direct()){FGameplayAbilityTargetData_ActorArray* Data = new FGameplayAbilityTargetData_ActorArray();Data->TargetActorArray.Add(HitActor);Payload.TargetData.Add(Data);}CrimsonAbility->BroadcastAugmentEvent(FGameplayTagContainer(CrimsonGameplayTags::Augment_Event_OnCrit), Payload);}}
GetAbilityInstance_NotReplicated() is populated by MakeOutgoingGameplayEffectSpec, so it is set whenever the spec was built through an ability. It is not replicated, which is fine here - this code runs on the server. If your broadcast site already has the ability in hand, use that instead.Step 3 - use it
Open any augment, press + on the EVENTS section, and your tag is in the list under Augment events, labeled from the tag leaf (OnCrit shows as "On Crit") with your Dev Comment as its tooltip. Add actions to the group and they run whenever you broadcast.
Augment.Event tag in the project, including yours. Select an ability in PIE and click the button to fire the event by hand.What the payload carries
| Field | What to put in it |
|---|---|
TargetData | Who the event happened to. Non-empty means actions run once per target - a 3-target hit executes an action three times, each with one target. |
EventMagnitude | A number the event is about - the damage dealt, the stacks consumed. Actions can scale off it. |
ContextTags | Tags describing this occurrence. Action gates test these, so an augment can react to a fire crit specifically. |
OptionalObject | Anything else an action needs. Untyped, so cast on the receiving side. |
Events that only reach listeners
The plugin does not ship defensive events. Deciding when a dodge or a block has happened is your game's job, so Augment.Event.OnOwnerDodge, OnOwnerBlock and OnOwnerDamageTaken are yours to declare and to fire with UCrimsonAbilitySystemComponent::BroadcastDefensiveAugmentEvents, which takes any tag. Use those three names and the editor still recognizes them: they describe something happening to the owner rather than something an ability did, so they reach stateful listeners only, and are hidden from the event picker and rejected by validation rather than being authored into a group that would silently never run.
See also
- Concept: Augment System - event groups, gates and actions
- How-To: Write a Stateful Augment - for events that need to accumulate across occurrences
- How-To: Write Augment Tooltips - describing what your event does to the player