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; } = "";
}