type = character_event/letter_event/court_event/activity_event # Optional, defaults to character_event
scope = scope_type # Overrides the events root scope. Optional, defaults to character scope. Use scope = none for no root scope, scope = artifact for events centered around artifacts, etc.
# Optional custom event window name.
# For character/letter events this is the popup window in gui/event_windows.
# For activity events this is used by activity event inserts.
window = window_name
# anonymous_letter_event - letter_event, but without sender portrait and sigil widget
# big_event_window - used for task_contracts, bookmark events, decision outcomes, story cycles, black plague, etc.
# character_event - default
# duel_event - used in single combat events
# fullscreen_event - use splash screen queue
# letter_event - used for responses to character_interactions, between characters that are not in the same location
# scheme_conclusion_window - big_event_window, however we always use one of the sub-types:
# scheme_failed_event - scheme_conclusion_window, but with failure header
# scheme_preparations_event - scheme_conclusion_window, but with scheme_preparation widget
# scheme_successful_event - scheme_conclusion_window, but with successful header
# scheme_conclusion_event_no_header
# scheme_conclusion_window, but without header
#visit_settlement_window - big_event_window, used by laamp visit settlement decision
# Basic event text/effects (commonly used)
title = my_event_title # Dynamic Description syntax, see bottom of document
desc = my_event_desc # Dynamic Description syntax, see bottom of document
trigger = { ... }
immediate = { ... }
after = { ... }
hidden = yes/no # If yes, no event window is shown
major = yes/no
major_trigger = { ... }
# Non-character scoped events generally need to be hidden or major.
# If you have a cooldown, the recipient root gets a saved variable with that duration.
trigger = ... # optional, controls visibility for this portrait in the scope of the portrait character
animation = animation name # optional default animation, used if no triggered animations pass their trigger. See animations.txt for all possible animations, in-game: toggle event tools in the event or open portrait editor through the console.
scripted_animation = key_of_scripted_animation # optional alternative to animation
outfit_tags = { tag1 tag2 } # Specifies outfit tags for this portrait in ascending priority (i.e. tag2 will "override" tag1 here if anything with tag2 is found in a specific portrait modifier category)
remove_default_outfit = yes/no # If set to yes, portrait modifier categories in which nothing matches any of the event tags will be disabled completely (no by default)
hide_info = yes/no # If set to yes, only the portrait will be shown, with no identifiable elements (no CoA, tooltips, clicks...) (no by default)
# This behavior is also influenced by the EVENT_OPTIONS_SHOWN_HIDE_UNAVAILABLE or SCHEME_PREPARATION_OPTIONS_SHOWN_HIDE_UNAVAILABLE defines depending on event type.
show_as_unavailable = {}
# Highlights the event portrait of this character while this option is hovered. This is in addition to the automatic highlighting when hovering an event option that has an effect that affects portrait characters.
highlight_portrait = scope:a_character
reason = <flag> # Special reason for why this option is unlocked, can be any arbitrary string, is be checked in the UI to show special by reason
skill = diplomacy/martial/stewardship/intrigue/learning/prowess # Marks this option as skill-relevant in unlock reason UI (if shown); you still have to specify the skill and level in the trigger to unlock it
trait = some_trait # Marks this option as trait-relevant in unlock reason UI (if shown); you still have to specify the trait in the trigger to unlock it
# Misc option behavior
show_unlock_reason = yes/no # Controls whether unlock reason UI is shown for this option
is_cancel_option = yes/no # Marks this option as a cancel/back-out style option (used by some widgets/controllers)
clicksound = "sound_event" # Sound to play when selecting this option
fallback = yes/no # If no regular options are valid, fallback options are considered
exclusive = yes/no # If any exclusive option is valid, non-exclusive options are ignored
theme = "" # Theme to use in the event. For a list, check: 00_event_themes.txt
override_background = { # A background that can be shown when the event pops up. This overrides the theme one. In case that there are multiples the first one that fits the trigger will be the one selected. In case none fits the ones in the theme will be checked after.
override_transition = { # A transition that can be shown when the event pops up, before the event options and backgrounds. This overrides the theme one. In case that there are multiples the first one that fits the trigger will be the one selected. In case none fits the ones in the theme will be checked after.
override_effect_2d = { # A 2d effect that can be put on top of the background. This overrides the theme one. In case that there are multiples the first one that fits the trigger will be the one selected. In case none fits the ones in the theme will be checked after.
override_icon = { # An icon that can be shown when the event pops up. This overrides the theme one. In case that there are multiples the first one that fits the trigger will be the one selected. In case none fits the ones in the theme will be checked after.
trigger = {} # Receives the event scope to check if it's valid.
reference = "" # Path to the texture
}
override_header_background = { # The header asset located behind the event icon. This overrides the header asset defined by the theme. If there are multiples defined here, the first one that passes its trigger will be selected. If none are valid, then the theme's header asset will be used
override_sound = { # A sound that can be played when the event pops up. This overrides the theme one. In case that there are multiples the first one that fits the trigger will be the one selected. In case none fits the ones in the theme will be checked after.
text | EventWindowWidgetEnterText | Saves some text onto the character. May use controller = { type = text data = { ... } } and setup_scope for text_target.
event_chain_progress | EventWindowWidgetChainProgress | Displays progress through an event chain, needs event_chain_length and event_chain_progress scope values set
struggle_info | EventWindowCustomWidgetStruggleInfo | Displays information for the struggle, needs "start" scope value set
situation_info | EventWindowCustomWidgetSituationInfo | Displays information for the situation
- Always include a safe fallback path (`desc` fallback in `first_valid`, or `fallback` in `switch`).
- Keep localization keys flat and explicit; nesting controls selection, loc does the prose.
- When building long descriptions, split into semantic chunks and compose with nested blocks.
- Prefer `first_valid` for deterministic branching and `random_valid` for variation.
- For option names, prefer multiple gated `name` entries over overly complex single-entry nesting.
COMMON GOTCHA WHEN BUILDING DYNAMIC DESCRIPTIONS, FOR INTERNAL DESIGNERS: If you're building a complex loc string that includes dialogue, it's common to end up with keys that contains an odd number of citation marks. In these cases you may need to escape the odd citation marks using double-backslash to pass the sanity checking git hook before you commit your work. E.g.:
my_cool_event_desc.intro: "The guy says, \\"Hey "
my_cool_event_desc.intro.friend: "friend"
my_cool_event_desc.intro.buddy: "buddy"
my_cool_event_desc.intro.idiot: "idiot"
my_cool_event_desc.intro.outro: ", watch where you're going!\\" I pay him no mind and continue on my way."