using System.Text.Json.Serialization; namespace Theriapolis.Core.Data; /// /// Phase 6 M4 — JSON-loaded quest definition. A quest is a directed graph /// of steps; the engine starts at , evaluates each /// active step's per tick, /// and runs + /// when the step fires. /// /// Author convention: one tree per file in /// Content/Data/quests/*.json. matches the /// filename. Step ids are strings local to the tree. /// public sealed record QuestDef { [JsonPropertyName("id")] public string Id { get; init; } = ""; [JsonPropertyName("title")] public string Title { get; init; } = ""; [JsonPropertyName("description")] public string Description { get; init; } = ""; /// True when the quest doesn't appear in the journal until first activation (Maw discovery, etc.). [JsonPropertyName("hidden")] public bool Hidden { get; init; } = false; /// Step id the engine activates on quest start. [JsonPropertyName("entry_step")] public string EntryStep { get; init; } = ""; [JsonPropertyName("steps")] public QuestStepDef[] Steps { get; init; } = System.Array.Empty(); /// /// Optional: triggers that auto-start this quest. The engine checks /// these against world state on every tick; when any fires, the quest /// activates at . Empty = manual-start (e.g. /// dialogue's start_quest effect). /// [JsonPropertyName("auto_start_when")] public QuestConditionDef[] AutoStartWhen { get; init; } = System.Array.Empty(); } public sealed record QuestStepDef { [JsonPropertyName("id")] public string Id { get; init; } = ""; [JsonPropertyName("title")] public string Title { get; init; } = ""; [JsonPropertyName("description")] public string Description { get; init; } = ""; /// Optional waypoint hint — anchor or role tag the player should head toward. [JsonPropertyName("waypoint")] public string Waypoint { get; init; } = ""; /// Conditions that fire this step's onEnter + outcomes when ALL true. [JsonPropertyName("trigger_conditions")] public QuestConditionDef[] TriggerConditions { get; init; } = System.Array.Empty(); /// Effects applied once when the step fires. [JsonPropertyName("on_enter")] public QuestEffectDef[] OnEnter { get; init; } = System.Array.Empty(); /// Step ids this step transitions into (any one is selected via outcome conditions). [JsonPropertyName("outcomes")] public QuestOutcomeDef[] Outcomes { get; init; } = System.Array.Empty(); /// True if reaching this step completes the quest (success). [JsonPropertyName("completes_quest")] public bool CompletesQuest { get; init; } = false; /// True if reaching this step fails the quest. [JsonPropertyName("fails_quest")] public bool FailsQuest { get; init; } = false; } public sealed record QuestOutcomeDef { /// Step id to transition to. "<end>" closes the quest. [JsonPropertyName("next")] public string Next { get; init; } = ""; /// Conditions for THIS outcome to be selected. Empty = always. [JsonPropertyName("when")] public QuestConditionDef[] When { get; init; } = System.Array.Empty(); [JsonPropertyName("effects")] public QuestEffectDef[] Effects { get; init; } = System.Array.Empty(); } /// Trigger / outcome predicate. public sealed record QuestConditionDef { /// /// One of: "flag_set", "flag_clear", "flag_at_least", "enter_anchor", /// "enter_role_proximity", "npc_dead", "npc_alive", "time_elapsed_seconds", /// "rep_at_least", "rep_below", "has_item", "not_has_item", /// "quest_complete", "quest_active", "dialogue_choice". /// [JsonPropertyName("kind")] public string Kind { get; init; } = ""; [JsonPropertyName("flag")] public string Flag { get; init; } = ""; [JsonPropertyName("anchor")] public string Anchor { get; init; } = ""; [JsonPropertyName("role")] public string Role { get; init; } = ""; [JsonPropertyName("npc")] public string Npc { get; init; } = ""; [JsonPropertyName("faction")] public string Faction { get; init; } = ""; [JsonPropertyName("id")] public string Id { get; init; } = ""; [JsonPropertyName("quest")] public string Quest { get; init; } = ""; [JsonPropertyName("value")] public int Value { get; init; } [JsonPropertyName("seconds")] public long Seconds { get; init; } } /// Quest-step side effect. public sealed record QuestEffectDef { /// /// One of: "set_flag", "clear_flag", "give_item", "take_item", /// "give_xp", "rep_event", "spawn_npc", "despawn_npc", /// "start_quest", "end_quest", "fail_quest". /// [JsonPropertyName("kind")] public string Kind { get; init; } = ""; [JsonPropertyName("flag")] public string Flag { get; init; } = ""; [JsonPropertyName("value")] public int Value { get; init; } = 1; [JsonPropertyName("id")] public string Id { get; init; } = ""; [JsonPropertyName("qty")] public int Qty { get; init; } = 1; [JsonPropertyName("xp")] public int Xp { get; init; } [JsonPropertyName("event")] public DialogueRepEventDef? Event { get; init; } [JsonPropertyName("quest")] public string Quest { get; init; } = ""; /// For spawn_npc: resident template id (named takes precedence). [JsonPropertyName("template")] public string Template { get; init; } = ""; /// For spawn_npc/despawn_npc: which named role tag is being mutated. [JsonPropertyName("role")] public string Role { get; init; } = ""; }