Gates: locks & conditions¶
A gate decides whether an interaction is allowed to run. MovaInteract has
two gate mechanisms that share one address grammar: a group-level gate
(Gates, on the Group's More block) and a tag-level inline gate (?).
Save the real screenshot as: shot-debug-overlay-tags-gates.png
Group-level: Gates¶
Every Group's More block carries one list, TArray<FName> Gates, checked
when the group is asked to start:
Every entry must pass, ex:
Open,@Lock:!Off.A trailing
:!Statenegates that one entry: allow and block share this one list, there is no separate "must be true" vs "must be false" list.
Same address grammar as everywhere else (see Tag Grammar Reference) so an entry
reads Open (self state), @Lock:Off (internal component), or %Vault:Sealed
(external actor). This is the coarse gate: it decides whether the whole
group is even allowed to begin.
An entry that fails blocks the whole group and fires OnActionRejected with the
reason "gate <Condition> not met", so UI and debug tooling both get a
specific, per-token reason instead of a plain "no".
Tag-level: the inline ? gate¶
A ? token on an interaction tag gates a single target, evaluated before
that target runs, not the whole group:
!Open @Door ?@Lock:Off
└─┬─┘ └──┬─┘ └───┬────┘
flow target gate: run "Open" on @Door only if @Lock is Off
Use the group's Gates list when the condition should block the interaction
from being offered/started at all. Use ? when different targets in the
same tag need different conditions (a choice that shows a padlock icon
vs one that runs freely).
Other reasons a group can be rejected¶
ExecuteActionGroup checks three things in order, and OnActionRejected
reports which one fired:
Check |
Reason text |
Meaning |
|---|---|---|
|
|
A game-side hook said no, ex: needs a key the player does not have. |
|
|
One of the group's own Gates entries failed. |
|
(logged, see Groups & Cycles) |
The group is already at rest in a state its RepeatPolicy blocks re-triggering from. |
Cross-object gates¶
Because the condition grammar is the same address syntax used for targets, a gate reads state on another actor without any extra wiring:
@Lock:Locked my own Lock component
%Vault:Sealed the external =Vault actor, any component or its IC
%Vault@Bolt:Locked that Vault's Bolt component specifically
A door checks a keycard reader elsewhere in the level. A vault checks three separate bolts on three separate actors before it opens. No Blueprint casts, no event dispatchers: only an address the resolver walks.
RepeatPolicy and cycle rollback¶
When a Cycle-triggered group's gate blocks it, the cycle's step index is
unaffected, so the next press retries the same group instead of advancing:
a locked door's Toggle keeps offering Open instead of skipping ahead to
Close because the blocked attempt still "used" a press. See
Groups & Cycles for RepeatPolicy in full.
Worked examples¶
Keycard door: one Gates entry, blocked until the card reader is in its Accepted state:
Group "Open":
Gates: [ @Reader:Accepted ]
Walking up and pressing without a valid card refuses the group; OnActionRejected
fires with "gate @Reader:Accepted not met", which a HUD or debug overlay can
show as a denied cue.
Multi-lock vault: three independent bolts, all required:
Group "OpenVault":
Gates:
- %BoltA:Unlocked
- %BoltB:Unlocked
- %BoltC:Unlocked
Each bolt is its own actor with its own IC, unlocked independently (a separate key, a separate puzzle). The vault door itself holds no lock logic: it only reads three external states.
See also¶
Tag Grammar Reference: the
:state syntax and?gate reference in full.Groups & Cycles: where
Gatessits among the rest of a Group's settings, and RepeatPolicy/cycle rollback on a blocked gate.Debug overlay & troubleshooting: the live overlay's
Gatesflag shows the per-token PASS/FAIL state in real time.UMovaIxComponent::IsStateConditionMet()in the API reference.