# 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 (`?`). ```{image} ../_static/screenshots/shot-debug-overlay-tags-gates-mockup.svg :alt: debug overlay tags gates (placeholder mockup) :width: 100% ``` Save the real screenshot as: `shot-debug-overlay-tags-gates.png` ```{image} ../_static/screenshots/shot-debug-overlay-tags-gates.png :alt: debug overlay tags gates (real screenshot) :width: 100% ``` ## Group-level: `Gates` Every Group's `More` block carries one list, `TArray Gates`, checked when the group is asked to **start**: - Every entry must pass, ex: `Open`, `@Lock:!Off`. - A trailing `:!State` negates 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 {doc}`tag-grammar`) 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 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: ```text !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 | |---|---|---| | `CanExecuteGroup` (Blueprint-overridable) | `"blocked"` | A game-side hook said no, ex: needs a key the player does not have. | | `Gates` | `"gate not met"` | One of the group's own Gates entries failed. | | `RepeatPolicy` | (logged, see {doc}`groups-and-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: ```text @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 {doc}`groups-and-cycles` for RepeatPolicy in full. ## Worked examples **Keycard door**: one Gates entry, blocked until the card reader is in its `Accepted` state: ```text 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: ```text 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 - {doc}`tag-grammar`: the `:` state syntax and `?` gate reference in full. - {doc}`groups-and-cycles`: where `Gates` sits among the rest of a Group's settings, and RepeatPolicy/cycle rollback on a blocked gate. - {doc}`../guides/debugging`: the live overlay's `Gates` flag shows the per-token PASS/FAIL state in real time. - {cpp:func}`UMovaIxComponent::IsStateConditionMet` in the API reference.