Concept: Requirements & Conditions
An option can carry requirements. They are objects, not code in the actor: UCrimsonInteractionCondition is an instanced, stateless predicate - read the context, answer, mutate nothing - authored inline on the option, on a container, or once in a UCrimsonInteractionConditionSet asset, and composed with And / Or / Not. The plugin decides what a failure means; a leaf only says whether the player qualifies and why not.
One evaluation path
- Gather. The target returns its options as before. Each option's
ConditionsandConditionSetsride along. - Evaluate all.
UCrimsonInteractionCondition::EvaluateOptionruns every condition in order and records each on the option'sRequirementschecklist (text + met). The FIRST unmet one decides the outcome: itsFailureBehavior, failure title and reason. - Apply.
Hidedrops the option before the ability filter.ShowInformationalkeeps it as a message:bInformational = true, the title replaces the text, the reason becomesSubText, and the option skips the ability filter entirely (a message needs no ability behind it). - Present. The prompt shows the message without a key glyph and lists the checklist met / unmet; a press on an informational option fires nothing. The context menu's wrapper (
UCrimsonContextAction_FromInteractionOption) applies the same result and lists it grayed with every unmet line as the reason. - Re-check on the server. The client's option list is presentation. Before an interaction runs, CrimsonCore's handler and duration abilities re-gather the target's options on the server, keep those naming their own ability class, and refuse unless one of them passes. No option id travels: the ability class the wire already carries is the identity.
The result
FCrimsonInteractionConditionResult | Meaning |
|---|---|
bPassed | Every condition met. |
Failure | The first unmet condition's behavior: ShowInformational or Hide. |
Title / Reason | The first unmet condition's failure title (empty keeps the option's text) and reason (becomes SubText). |
Requirements | Every condition, met or not, in order - the checklist. Each line's text comes from GetRequirementText(Context, bMet): the condition's RequirementText, else the leaf's own wording, else the reason while unmet and the class name while met. |
A condition may only read what the instigator's client can see
The gather runs on the instigator's client for the prompt and on the server for the grant and the re-check, and both must agree. Replicated inventory, attributes, tags and replicated actor state are fine. A value that lives only on the server makes the prompt and the server disagree - the client shows Open and the server refuses. Mirror such state first.
Where leaves live
The base, the composites and the tag query ship in this plugin; a leaf that needs another system's knowledge lives in the code that joins the two (CrimsonCore ships an item check, an attribute compare and a team-attitude check), and CrimsonCore's owned stash turns its access policy into a condition so a refused player reads
No Access (Owner: <Name>) instead of nothing.See also
- How-To: Gate an Interaction with Conditions
- Concept: Scan, Gather, Filter, Broadcast
- Concept: Multiplayer & Authority