Combo System
Chains discrete GAS abilities into branching, designer-authored sequences (light-light-heavy, charge attacks, directional finishers). Structured the OPPOSITE way from most UE combo solutions: each combo step is its own `UCrimsonGameplayAbility`, and a combo graph asset describes how steps chain. The combo system owns none of the animation, damage, costs, or augments - those live on each step's ability where GAS already handles them.
How it differs
| Aspect | Most UE combo solutions | CrimsonAbilitySystem combo |
|---|---|---|
| What's a combo? | One ability + big montage with notify transitions | A graph; each node IS a step, each step IS its own ability |
| Per-step granularity | All steps share one ability's costs/cooldowns/augments | Each step inherits the FULL GAS surface - own cost, cancellable, augmentable independently |
| Input source of truth | Anim notifies parsed at runtime | Designer-authored phase boundaries in seconds, inline montage timeline |
| Multiplayer | Author manually | Built-in: server-authoritative CurrentNodeID, client-predicted next step, ping-leniency cancel check |
| Branching | Hardcoded in the montage | First-class - every transition is an edge; steps can branch into combos rooted on their own ability |
Concepts
| Term | What it is |
|---|---|
Combo Graph Asset (UCrimsonComboGraphAsset) | The asset designers create - the graph of step nodes + transitions + a starting handshake |
Step Node (FCrimsonComboRuntimeNode) | One step: references a UCrimsonGameplayAbility + phase boundaries + outgoing transitions |
Transition (FCrimsonComboTransition) | An edge between steps: input + priority + target + conditional augment grants |
Starting Handshake (FCrimsonComboStartingHandshake) | How a rooting ability enters a combo asset |
Combo Extension (FCrimsonComboExtension) | UPROPERTY on UCrimsonGameplayAbility listing DefaultCombos + the transition window for chaining INTO a combo |
Combo Controller (UCrimsonComboController) | Runtime driver on the pawn - input buffer, grants, state machine, prediction RPCs |
Transition Condition (UCrimsonComboTransitionCondition) | Blueprintable observer that watches the prior step and decides whether the transition's augment grants apply |
UInputAction set drives normal activation AND combo transitions. Designers pick combo inputs from a closed catalog (the project IMC in UCrimsonAbilitySystemSettings) so they can't reference inputs that don't exist.Input buffer TTL - override chain
The resolved TTL walks this chain, returning the first non-sentinel value:
| # | Source | Sentinel that defers |
|---|---|---|
| 1 | Step override - FCrimsonComboRuntimeNode::InputBufferTTLOverride | -1 |
| 2 | Asset default - UCrimsonComboGraphAsset::InputBufferTTLSeconds | 0 |
| 3 | Rooting ability override - FCrimsonComboExtension::InputBufferTTLOverride | -1 |
| 4 | Per-character - UCrimsonComboController::DefaultInputBufferTTL | 0 |
| 5 | Project setting - UCrimsonAbilitySystemSettings::DefaultInputBufferTTL | n/a (0.1 default) |
Grants - runtime API
Combos are granted to the controller at runtime, not hardcoded. ComboExtension.DefaultCombos is the seed; the controller's replicated FCrimsonComboGrantContainer is the authority:
Controller->UnlockComboGrant(RootAbilityClass, ComboAsset);Controller->LockComboGrant(RootAbilityClass, ComboAsset);Controller->GrantDynamicCombo(RootAbilityClass, ComboAsset); // returns a handleController->RevokeComboGrant(Handle);Controller->IsComboGranted(RootAbilityClass, ComboAsset);
Save support: mirror dynamic grants via Controller->GetSaveData() / ApplySaveData(Data). Default grants regenerate on every ASC init.
Conditional augments
Every transition carries (UCrimsonComboTransitionCondition, Augments[]) pairs. Conditions are stateful observers receiving lifecycle hooks during the prior step, then pure-returning true/false at fire time:
| Hook | When it fires |
|---|---|
OnObservationBegin | Step ability activates; reset accumulators |
OnEffectAppliedToTarget | Step applies a GE to a target |
OnObservedAttributeChanged | A declared observed attribute changes |
OnAugmentEvent | An augment event broadcasts from the observed ability |
OnObservationEnd | Step ends (cancelled or completed) |
EvaluateCondition | Pure evaluation at fire time - returns whether the augments are granted |
When a transition fires, augments behind any true condition are equipped onto the receiving step's ability via the slot system, and auto-unequipped when that step ends.
UCrimsonComboTransitionCondition (Blueprintable, EditInlineNew, Abstract); its default EvaluateCondition returns true. Real conditions are your project's to subclass.Multiplayer - per-step prediction
| Role | What runs |
|---|---|
| Owning client | Buffers input, predicts the next step locally, sends Server_RequestTransition. Rolls back on Client_RejectTransition. |
| Server | Validates (current node matches, transition exists, input matches, cancel window open with bounded ping leniency <= 80 ms). Commits CurrentNodeID. Activates the next step's ability. |
| Simulated proxies | No controller logic. See montages via GAS replication; CurrentNodeID read only for cosmetic cues. |