Modes & Runtime Swap
Multi-grip weapons in one Definition + runtime moveset swap with combo continuity
A MovesetDefinition is one asset per weapon TYPE — Sword, Dagger, Spear, Unarmed — and every grip / stance of that weapon lives inside as separate Modes. This page covers when to use Modes, how runtime swaps preserve combo state, and how shared ComboGraph assets enable cross-weapon combo continuity.
Single-mode weapon
The simplest case — a weapon that's always held one way. A one-handed dagger, an unarmed combat moveset, a fixed-stance gun.
In the Definition:
- Fill
DefaultModewith{ ComboGraph, AnimationChooser, Hitbox, Config }. - Leave
AlternateModesempty.
At runtime:
- Component's
ActiveSelection.Modestays empty. - Runtime always resolves to
DefaultMode.
Multi-mode weapon
A sword that works one-handed, two-handed, and as a paired dual-wield. One Definition covers all three grips:
DefaultModeis the "primary" / fallback variant (typically one-handed).AlternateModesmaps the other Mode tags to their ownFMovesetModeData:Moveset.Mode.TwoHanded→ two-handed grip's combo graph + chooser + hitbox.Moveset.Mode.DualWield→ paired-stance variant.
Equipment system picks the active Mode based on what's equipped (one weapon → DefaultMode, two of the same → DualWield, two-handed grip key held → TwoHanded), then calls:
MovesetComponent->SetActiveMode(FGameplayTag::RequestGameplayTag("Moveset.Mode.TwoHanded"));
Native Mode tags shipped with the plugin: Moveset.Mode.OneHanded, Moveset.Mode.TwoHanded, Moveset.Mode.DualWield. You're free to add your own (Moveset.Mode.Reverse, Moveset.Mode.Shielded, etc.) — they're just gameplay tags.
If the active Mode tag isn't in AlternateModes, the runtime silently falls back to DefaultMode. This is intentional — an unfamiliar Mode shouldn't crash the moveset.
Cross-weapon combo continuity
If two Definitions share the same UComboGraphAsset in their relevant Mode's data, the component's swap API preserves the combo cursor across the swap. This is how "LMB → LMB → RMB" carries as a single chain when the player swaps weapons mid-combo.
MovesetDefinition: MD_Sword
DefaultMode = { CG_MeleeCombo, CT_Sword, Hitbox_Sword, Config }
MovesetDefinition: MD_Axe
DefaultMode = { CG_MeleeCombo, CT_Axe, Hitbox_Axe, Config }
^^^^^^^^^^^^^
Same graph asset
Equip sword → SetActiveMoveset(MD_Sword) → cursor is at Root. Press LMB → cursor advances to Attack.A on the sword's chooser. Mid-attack, equip axe → SetActiveMoveset(MD_Axe) → cursor preserved (graph matches) → next press advances to Attack.B on the axe's chooser. Same combo timing, different weapon visuals.
Runtime swap API
After Apply Moveset initialised the component, change the active selection mid-game with:
| Method | Behaviour |
|---|---|
SetActiveMoveset(NewDefinition, bPreserveComboState) |
Swap Definition. Mode preserved. |
SetActiveMode(NewMode, bPreserveComboState) |
Swap Mode tag, same Definition. Useful for grip flip on the same weapon. |
SetActiveSelection({Definition, Mode}, bPreserveComboState) |
Atomic swap of both — single replicated transition. |
RequestSelectionSwap(NewSelection, InitialInput) |
Defers swap until the current attack's Combo Window resolves, then applies. Keeps mid-attack swaps from cancelling the playing animation. |
bPreserveComboState=true keeps the combo cursor + Enhanced Input bindings + ComboInstance only when the resolved ComboGraph asset is the same in old and new selection. If the graph differs, combo state is reset regardless of the flag (a different graph means different chains; the old cursor would refer to nodes that don't exist).
When to use which
SetActiveMoveset— equipment system swaps one weapon for another. Both weapons live in the same Mode tag.SetActiveMode— the weapon stays the same but the player flipped grips (Y-button to two-hand a greatsword). Combo state usually resets (different graph), Enhanced Input bindings re-setup automatically.SetActiveSelection— both Definition and Mode change at once and you need an atomic, single-replicated transition (e.g. weapon stowed → fists → fists Mode in one operation).RequestSelectionSwap— same as the above but you don't want the swap to cancel the in-flight attack. The runtime queues the swap untilCombo Windowresolves, then applies.
Authoring patterns by genre
Souls-like — different weapons share combo structure
Combo Graph: CG_MeleeCombo (shared across weapons)
Root → [Light] → Attack1 → [Light] → Attack2 → [Light] → Attack3
→ [Heavy] → HeavyFinisher
Chooser Table: CT_Sword
Moveset.Attack.Light1 → AM_Sword_Slash1
Moveset.Attack.Light2 → AM_Sword_Slash2
…
Chooser Table: CT_Axe
Moveset.Attack.Light1 → AM_Axe_Chop1
Moveset.Attack.Light2 → AM_Axe_Chop2
…
MovesetDefinition: MD_Sword.DefaultMode = { CG_MeleeCombo, CT_Sword, Hitbox_Sword, Config }
MovesetDefinition: MD_Axe.DefaultMode = { CG_MeleeCombo, CT_Axe, Hitbox_Axe, Config }
Equip sword → SetActiveMoveset(MD_Sword). Equip axe → SetActiveMoveset(MD_Axe). Same combo graph, different montages, different hitbox geometry, combo cursor survives the swap.
Greatsword grip flip
MovesetDefinition: MD_Greatsword
DefaultMode = { CG_OneHandedCombo, CT_Greatsword_OneHanded, Hitbox_OneHanded, Config }
AlternateModes:
Moveset.Mode.TwoHanded = { CG_TwoHandedCombo, CT_Greatsword_TwoHanded, Hitbox_TwoHanded, Config }
Player presses Y → SetActiveMode(Moveset.Mode.TwoHanded). Same Definition, different combo graph, combo state resets (different graph asset) but Enhanced Input bindings re-setup automatically.
Dual-wield with paired stance
MovesetDefinition: MD_DualDaggers
DefaultMode = { CG_SingleDaggerCombo, CT_LeftDagger, Hitbox_Single, Config }
AlternateModes:
Moveset.Mode.DualWield = { CG_DualCombo, CT_BothDaggers, Hitbox_Both, Config }
Player picks up second dagger → SetActiveMode(Moveset.Mode.DualWield) → graph swaps to dual-wield variant with paired-attack chains.
What gets reset on swap
| Swap kind | Cursor | Bindings | Active hitboxes | In-flight montage |
|---|---|---|---|---|
bPreserveComboState=true, same graph |
preserved | preserved | preserved | preserved |
bPreserveComboState=true, graph changed |
reset | re-setup | cancelled | cancelled |
bPreserveComboState=false |
reset | re-setup | cancelled | cancelled |
RequestSelectionSwap during Combo Window |
deferred | deferred | preserved | preserved (until window closes) |
When the in-flight montage is cancelled, the new Mode's first eligible transition fires immediately if InitialInput was passed to Apply Moveset / RequestSelectionSwap.