Prompt the subject's controller to pick one of several author-defined
options, then run that option's own nested outcome list against the same
execution context. This is the "User Choice" meta outcome — a second
promptFor consumer alongside summonNpc/scryArrange/playAnimation,
but routed through _renderUserChoice (prompt-renderers.mjs) instead of
a bespoke Application.
Config:
promptTitle string | null — optional dialog heading; falls back to a
sensible default (referencing the subject's name) when unset.
options Array<{
id string — foundry.utils.randomID()
name string — short label shown on the choice button
description string — longer text shown under the name
outcomes object[] — plain-object outcome entries
{ id, order, type, target, config }, same
shape as TriggerOutcomeModel fields but never
backed by an EmbeddedDataField. Deliberately
NOT nestable — a userChoice inside an
option's outcomes is rejected by the config
UI, not by this executor.
}>
Only { id, name, description } per option crosses into the prompt spec
sent to promptFor — the nested outcomes arrays never leave the GM/
executor client, since they're plain data (not sanitized for socket
transport) and only ever need to run locally once a choice comes back.
On response, resolves the chosen option by response.chosenId, runs its
outcomes through _runOutcomeList against the same context (so
NegateSignal, context._actorUpdateBatch, and context.outcomeResults
all compose with the rest of the trigger's outcome list), and stamps
context.outcomeResults.userChoice[subject.id] = { chosenOptionId, chosenOptionName }
for downstream {result.chosenOptionName}-style formula chaining.
Prompt the subject's controller to pick one of several author-defined options, then run that option's own nested outcome list against the same execution context. This is the "User Choice" meta outcome — a second
promptForconsumer alongsidesummonNpc/scryArrange/playAnimation, but routed through_renderUserChoice(prompt-renderers.mjs) instead of a bespoke Application.Config: promptTitle string | null — optional dialog heading; falls back to a sensible default (referencing the subject's name) when unset. options Array<{ id string — foundry.utils.randomID() name string — short label shown on the choice button description string — longer text shown under the name outcomes object[] — plain-object outcome entries { id, order, type, target, config }, same shape as TriggerOutcomeModel fields but never backed by an EmbeddedDataField. Deliberately NOT nestable — a userChoice inside an option's outcomes is rejected by the config UI, not by this executor. }>
Only
{ id, name, description }per option crosses into the prompt spec sent topromptFor— the nestedoutcomesarrays never leave the GM/ executor client, since they're plain data (not sanitized for socket transport) and only ever need to run locally once a choice comes back.On response, resolves the chosen option by
response.chosenId, runs itsoutcomesthrough_runOutcomeListagainst the same context (soNegateSignal,context._actorUpdateBatch, andcontext.outcomeResultsall compose with the rest of the trigger's outcome list), and stampscontext.outcomeResults.userChoice[subject.id] = { chosenOptionId, chosenOptionName }for downstream{result.chosenOptionName}-style formula chaining.