class_name EventDef extends RefCounted ## Phase 15 — Storyteller event definition (data class). ## ## EventDef is the static, authored shape of one event from the 25-prompt corpus ## (see docs/design.md "Prompt corpus"). Storyteller picks one EventDef per ## daily 6 AM roll, then runs its trigger predicate + cooldown gates, then ## applies its effect. ## ## EventDef instances are constructed in EventCatalog (`scenes/storyteller/event_catalog.gd`) ## by Agent A. They're treated as immutable at runtime; per-event cooldown state ## lives in Storyteller, NOT here. ## ## Categories (locked, mirror design.md headings): ## NUDGE — soft dismissible banner, no pause ## SEASONAL — ambient banner on season transition ## WANDERER — modal with choice (Welcome / Refuse) ## THREAT — modal with auto-pause; spawns hostiles ## DISEASE — modal or nudge; applies status to a pawn ## RESOURCE — banner; applies a transient buff ## LORE — flavor banner, no mechanical effect ## MILESTONE — celebratory banner; small mood thought ## ## Display kinds: ## BANNER — non-blocking, auto-dismiss ## MODAL — blocking, may auto-pause, may carry choices enum Category { NUDGE, SEASONAL, WANDERER, THREAT, DISEASE, RESOURCE, LORE, MILESTONE, } enum Display { BANNER, MODAL, } ## Stable id. Used for cooldown tracking and Strings.t() keys. var id: StringName = &"" ## Display title — short. Localized via Strings catalog by Agent A. var title: String = "" ## Body copy — 1-2 sentences, supports `%pawn%` substitution. var body: String = "" var category: Category = Category.NUDGE var display: Display = Display.BANNER ## Cooldown in in-game days from this event. Per-event gate. ## Per-category cooldowns live in Storyteller.CATEGORY_COOLDOWN_DAYS. var cooldown_days: int = 3 ## Base weight in the daily roll's weighted pool. Tension/state modifiers ## multiply this at roll time. var base_weight: float = 1.0 ## Optional choice labels for MODAL events (e.g. ["Welcome", "Send away"]). ## Empty array = dismiss-only. var choices: Array[String] = [] ## If true, this event causes a sim auto-pause when fired (Storyteller calls ## Sim.set_speed(PAUSE) before showing the UI). var auto_pause: bool = false ## Optional tile to focus the "Go there" camera-pan on. Vector2i(-1, -1) = no jump. var focus_tile: Vector2i = Vector2i(-1, -1) ## Predicate evaluated by Storyteller before this event is eligible to roll. ## Set in the EventCatalog factory; returns true when world state matches. ## Signature: Callable that takes no args, returns bool. var trigger_predicate: Callable = Callable() ## Effect applied when the event resolves (chosen path for modals, immediate for banners). ## Signature: Callable taking (choice_index: int) — choice 0 = first option / dismiss. var on_resolve: Callable = Callable()