How-To: Drive Combos from AI
Goal: have an NPC run the same authored combo graph a player runs - starting it, choosing its follow-ups and finishing it - from whatever AI you already use, with no input, no prediction and no special graph authoring.
UCrimsonComboController, exactly like a player pawn.No Behavior Tree nodes ship with this plugin, and none are needed: these are ordinary Blueprint-callable functions on the combo controller. Call them from a BTTask, a StateTree task, an AI controller or a plain component - anywhere that runs on the server.
1. Give the NPC a combo controller and a grant
Add a Crimson Combo Controller component to the NPC pawn. Then, on the server, grant it the combo: a drive request only starts a combo that is granted and unlocked on that controller.
On the NPC pawn: Event BeginPlay -> Switch Has Authority (Authority) -> Get Component By Class (CrimsonComboController) -> Grant Dynamic Combo (Root Ability Class = the ability the combo hangs off in the graph, Combo = your graph asset).
If the combo is already a Default Combo on an ability the NPC is granted, call Unlock Combo Grant with the same two pins instead of granting a new one.
UNLOCKED.2. Pre-flight the step abilities
Every step of the combo activates a real ability on the NPC's ability system component, and a driven combo tears itself down on the first step ability it cannot activate. Two calls make that a checked condition instead of a surprise.
| Call | Does |
|---|---|
| Preload Combo Abilities | Warms every step ability class the combo references, so the first step is a pointer read instead of a blocking package load mid-frame. Safe to call repeatedly. |
| Get Ungranted Step Abilities | Returns every step ability of that combo that is not currently granted on the bound ability system component. Call it after the preload and let a frame or two pass: a class that is not resident yet is reported as ungranted, because its grant state cannot be read. |
Get Component By Class (CrimsonComboController) -> Preload Combo Abilities (Combo = your graph asset) -> Get Ungranted Step Abilities (same asset) -> Length. Anything above 0 is a step the NPC cannot perform - add those abilities to the ability set the NPC is granted.
3. Start the combo
Start Combo By Asset begins the combo at its first step. No starting handshake is matched and no rooting ability is canceled, because there is no press. A combo already running on that controller is ended first, with reset reason Manual. It returns false and sets its Out Result pin on every refusal - see the result table below. A step node that lists Manual in its Reset Ignore Reasons does not see that teardown and survives it, so keep Manual off any node a driven start has to be able to interrupt.
Get Component By Class (CrimsonComboController) -> Start Combo By Asset (Combo = your graph asset) -> Branch on the return value. The Out Result pin carries an ECrimsonComboDriveResult you can switch on when it fails.
IDLE and the Active Step Timeline starts running the first step.4. Chain to the next step
Request Transition To Node fires the active step's transition whose target is the node you name - or an end point, since a step may wire straight into one. When several edges target the same node, the highest-priority eligible one wins. Get Available Combo Inputs is where the candidate targets come from: each entry carries its Target Node ID, its Priority and whether it would fire right now.
| Timing | Behavior |
|---|---|
Immediate | Fires only if the transition window is open at this moment. If it is not, the request fails, returns false, and nothing is stored. |
WhenWindowOpens | Fires now if the window is already open. Otherwise it latches the request on the active step and fires the instant the window opens, returning true with a result of Latched. One latch per step - a second request replaces it - and the latch is dropped when the step ends for any reason. Cancel Pending Drive Request drops it early. |
A drive request is not a synthetic button press, and the edge is read accordingly:
| Part of the edge | On a drive request |
|---|---|
| Input action | Ignored. There is no press to match. |
Kind (Tap, Hold, Release) | Ignored. |
Fire Mode (IASA, PressBuffer, HoldBuffer) | Ignored. A driven transition fires when the request is granted. |
| Direction | Ignored. |
| Modifier chords | Ignored. |
| The transition window, including Cancel Open Override and Cancel Close Override | Respected. No ping leniency is applied on either side - the requester and the authority are the same machine, so the authority's own clock is the whole rule. |
| Edge Required Tags Query | Respected, evaluated against the NPC's current ability system tags - which include the live Combo.Phase.* tag and the active node's Node Tags. See How-To: Drive Behavior from Step Phases. |
| Transition conditions | Never block a transition in this system, for players or AI alike. They only select conditional augments - see How-To: Gate Combo Branches with Conditions. |
Get Available Combo Inputs -> For Each Loop, and keep the entries whose Availability is Continuation and whose Would Fire If Pressed Now is true. Feed the chosen entry's Target Node ID into Request Transition To Node with Timing = Immediate, then break out of the loop.
To commit to a follow-up before the window opens, call Request Transition To Node with Timing = WhenWindowOpens as soon as the step begins. Cancel Pending Drive Request takes it back if the NPC changes its mind.
WindowNotOpen or WindowClosed and changes nothing.5. Know when the combo finished
There are no drive-specific delegates, because polled AI does not need them. Get Completion Counter is bumped every time the controller reaches an End node. Snapshot it before starting; when Is Combo Active goes false, a counter that changed means the combo finished cleanly and a counter that did not means it was reset. Compare for inequality only - the underlying value is a byte and wraps.
Before Start Combo By Asset, store Get Completion Counter in a variable. Each tick afterwards: Is Combo Active -> Branch (False) -> Get Completion Counter -> Not Equal (integer) against the stored value. True is a clean finish; false is a reset.
Drive result codes
Every drive call sets an ECrimsonComboDriveResult. These are distinct from the server's rejection reasons for a client's predicted transition - these describe a request the authority made itself.
| Result | Means |
|---|---|
Success | The request was granted. |
ComboSystemDisabled | The combo system is off in Project Settings -> Crimson -> Crimson Ability System. |
NotAuthority | The caller is not authoritative. |
OwnerIsPlayerControlled | The owning pawn is player-controlled, so the drive was refused. |
NoASC | No ability system component is bound to the controller. |
ComboNotGranted | The combo is not granted, or not unlocked, on this controller. Also reported when the combo ended during its first step, which usually means a step ability the NPC was never granted. |
ComboNotActive | No combo is running, so there is nothing to transition out of. |
NoMatchingTransition | The active step has no transition toward that target. |
TargetNotReachable | The target node or end point is not in this combo. |
WindowNotOpen | The transition window has not opened yet. |
WindowClosed | The transition window already closed. |
EdgeTagsNotSatisfied | The edge's Edge Required Tags Query is not satisfied by the NPC's current tags. |
Latched | Timing was WhenWindowOpens and the request is now latched on the active step. It fires when the window opens. |
What clients see
What you will not see on a client is any of the NPC's combo controller state - no grants, no current node. That is correct, not a bug: the state is owner-only and an AI pawn has no owning connection.
See also
- How-To: Author a Combo - the graph an NPC runs is the same graph a player runs.
- How-To: Drive Behavior from Step Phases - the tag query a driven transition respects.
- How-To: Gate Combo Branches with Conditions - why conditions never block a transition.
- How-To: Debug Combos (Dev Tools) - watching a driven combo live.
- Concept: Combo System - the model behind the graph.