{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://carvel.li/questionable/quest-1.0",
  "title": "Questionable V1",
  "description": "A series of quest sequences",
  "type": "object",
  "properties": {
    "Author": {
      "description": "Author of the quest sequence",
      "type": "string"
    },
    "Contributors": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "Comment": {
      "type": "string"
    },
    "TerritoryBlacklist": {
      "type": "array",
      "items": {
        "type": "integer"
      }
    },
    "QuestSequence": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "Sequence": {
            "type": "integer",
            "minimum": 0,
            "maximum": 255
          },
          "Steps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "DataId": {
                  "type": "integer",
                  "description": "The data id of the NPC/Object/Aetheryte/Aether Current",
                  "exclusiveMinimum": 0
                },
                "Position": {
                  "type": "object",
                  "description": "Position to (typically) walk to",
                  "properties": {
                    "X": {
                      "type": "number"
                    },
                    "Y": {
                      "type": "number"
                    },
                    "Z": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "X",
                    "Y",
                    "Z"
                  ]
                },
                "StopDistance": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Set if pathfinding should stop closer or further away from the default stop distance",
                  "exclusiveMinimum": 0
                },
                "TerritoryId": {
                  "type": "integer",
                  "description": "The territory id associated with the location",
                  "exclusiveMinimum": 0
                },
                "TargetTerritoryId": {
                  "type": "integer",
                  "description": "If set, this step is complete (movement-wise) if this territory id is reached",
                  "exclusiveMinimum": 0
                },
                "InteractionType": {
                  "type": "string",
                  "description": "What to do at the position",
                  "enum": [
                    "Interact",
                    "WalkTo",
                    "AttuneAethernetShard",
                    "AttuneAetheryte",
                    "AttuneAetherCurrent",
                    "Combat",
                    "UseItem",
                    "Say",
                    "Emote",
                    "WaitForNpcAtPosition",
                    "WaitForManualProgress",
                    "Duty",
                    "SinglePlayerDuty",
                    "Jump",
                    "ShouldBeAJump",
                    "Instruction"
                  ]
                },
                "Disabled": {
                  "description": "Whether this step is disabled (see SkipIf for more control)",
                  "type": "boolean"
                },
                "DisableNavmesh": {
                  "description": "If true, will go to the position in a straight line instead of using pathfinding",
                  "type": "boolean"
                },
                "Mount": {
                  "type": [
                    "boolean",
                    "null"
                  ],
                  "description": "If true, will mount regardless of distance to position. If false, will unmount."
                },
                "Fly": {
                  "type": "boolean",
                  "description": "If true and flying is unlocked in a zone, will use a flight path"
                },
                "Sprint": {
                  "type": [
                    "boolean",
                    "null"
                  ]
                },
                "AetheryteShortcut": {
                  "type": "string",
                  "description": "The Aetheryte to teleport to (before moving)",
                  "enum": [
                    "Gridania",
                    "Central Shroud - Bentbranch Meadows",
                    "East Shroud - Hawthorne Hut",
                    "South Shroud - Quarrymill",
                    "South Shroud - Camp Tranquil",
                    "North Shroud - Fallgourd Float",
                    "Ul'dah",
                    "Western Thanalan - Horizon",
                    "Central Thanalan - Black Brush Station",
                    "Eastern Thanalan - Camp Drybone",
                    "Southern Thanalan - Little Ala Mhigo",
                    "Southern Thanalan - Forgotten Springs",
                    "Northern Thanalan - Camp Bluefog",
                    "Northern Thanalan - Ceruleum Processing Plant",
                    "Limsa Lominsa",
                    "Middle La Noscea - Summerford Farms",
                    "Lower La Noscea - Moraby Drydocks",
                    "Eastern La Noscea - Costa Del Sol",
                    "Eastern La Noscea - Wineport",
                    "Western La Noscea - Swiftperch",
                    "Western La Noscea - Aleport",
                    "Upper La Noscea - Camp Bronze Lake",
                    "Outer La Noscea - Camp Overlook",
                    "Coerthas Central Highlands - Camp Dragonhead",
                    "Mor Dhona",
                    "Gold Saucer",
                    "Wolves' Den Pier",
                    "Ishgard",
                    "Idyllshire",
                    "Coerthas Western Highlands - Falcon's Nest",
                    "The Sea of Clouds - Camp Cloudtop",
                    "The Sea of Clouds - Ok' Zundu",
                    "Azys Lla - Helix",
                    "The Dravanian Forelands - Tailfeather",
                    "The Dravanian Forelands - Anyx Trine",
                    "The Churning Mists - Moghome",
                    "The Churning Mists - Zenith",
                    "Rhalgr's Reach",
                    "Fringes - Castrum Oriens",
                    "Fringes - Peering Stones",
                    "Peaks - Ala Gannha",
                    "Peaks - Ala Ghiri",
                    "Lochs - Porta Praetoria",
                    "Lochs - Ala Mhigan Quarter",
                    "Kugane",
                    "Ruby Sea - Tamamizu",
                    "Ruby Sea - Onokoro",
                    "Yanxia - Namai",
                    "Yanxia - House of the Fierce",
                    "Azim Steppe - Reunion",
                    "Azim Steppe - Dawn Throne",
                    "Azim Steppe - Dhoro Iloh",
                    "Doman Enclave",
                    "Crystarium",
                    "Eulmore",
                    "Lakeland - Fort Jobb",
                    "Lakeland - Ostall Imperative",
                    "Kholusia - Stilltide",
                    "Kholusia - Wright",
                    "Kholusia - Tomra",
                    "Amh Araeng - Mord Souq",
                    "Amh Araeng - Inn at Journey's Head",
                    "Amh Araeng - Twine",
                    "Rak'tika - Slitherbough",
                    "Rak'tika - Fanow",
                    "Il Mheg - Lydha Lran",
                    "Il Mheg - Pia Enni",
                    "Il Mheg - Wolekdorf",
                    "Tempest - Ondo Cups",
                    "Tempest - Macarenses Angle",
                    "Old Sharlayan",
                    "Radz-at-Han",
                    "Labyrinthos - Archeion",
                    "Labyrinthos - Sharlayan Hamlet",
                    "Labyrinthos - Aporia",
                    "Thavnair - Yedlihmad",
                    "Thavnair - Great Work",
                    "Thavnair - Palaka's Stand",
                    "Garlemald - Camp Broken Glass",
                    "Garlemald - Tertium",
                    "Mare Lamentorum - Sinus Lacrimarum",
                    "Mare Lamentorum - Bestways Burrow",
                    "Elpis - Anagnorisis",
                    "Elpis - Twelve Wonders",
                    "Elpis - Poieten Oikos",
                    "Ultima Thule - Reah Tahra",
                    "Ultima Thule - Abode of the Ea",
                    "Ultima Thule - Base Omicron"
                  ]
                },
                "AethernetShortcut": {
                  "type": "array",
                  "description": "A pair of aethernet locations (from + to) to use as a shortcut",
                  "minItems": 1,
                  "maxItems": 2,
                  "items": {
                    "type": "string",
                    "enum": [
                      "[Gridania] Aetheryte Plaza",
                      "[Gridania] Archer's Guild",
                      "[Gridania] Leatherworker's Guild & Shaded Bower",
                      "[Gridania] Lancer's Guild",
                      "[Gridania] Conjurer's Guild",
                      "[Gridania] Botanist's Guild",
                      "[Gridania] Mih Khetto's Amphitheatre",
                      "[Gridania] Blue Badger Gate (Central Shroud)",
                      "[Gridania] Yellow Serpent Gate (North Shroud)",
                      "[Gridania] White Wolf Gate (Central Shroud)",
                      "[Gridania] Airship Landing",
                      "[Ul'dah] Aetheryte Plaza",
                      "[Ul'dah] Adventurer's Guild",
                      "[Ul'dah] Thaumaturge's Guild",
                      "[Ul'dah] Gladiator's Guild",
                      "[Ul'dah] Miner's Guild",
                      "[Ul'dah] Weavers' Guild",
                      "[Ul'dah] Goldsmiths' Guild",
                      "[Ul'dah] Sapphire Avenue Exchange",
                      "[Ul'dah] Alchemists' Guild",
                      "[Ul'dah] Gate of the Sultana (Western Thanalan)",
                      "[Ul'dah] Gate of Nald (Central Thanalan)",
                      "[Ul'dah] Gate of Thal (Central Thanalan)",
                      "[Ul'dah] The Chamber of Rule",
                      "[Ul'dah] Airship Landing",
                      "[Limsa Lominsa] Aetheryte Plaza",
                      "[Limsa Lominsa] Arcanist's Guild",
                      "[Limsa Lominsa] Fishermen's Guild",
                      "[Limsa Lominsa] Hawker's Alley",
                      "[Limsa Lominsa] The Aftcastle",
                      "[Limsa Lominsa] Culinarian's Guild",
                      "[Limsa Lominsa] Marauder's Guild",
                      "[Limsa Lominsa] Zephyr Gate (Middle La Noscea)",
                      "[Limsa Lominsa] Tempest Gate (Lower La Noscea)",
                      "[Limsa Lominsa] Airship Landing",
                      "[Ishgard] Aetheryte Plaza",
                      "[Ishgard] The Forgotten Knight",
                      "[Ishgard] Skysteel Manufactory",
                      "[Ishgard] The Brume",
                      "[Ishgard] Athenaeum Astrologicum",
                      "[Ishgard] The Jeweled Crozier",
                      "[Ishgard] Saint Reymanaud's Cathedral",
                      "[Ishgard] The Tribunal",
                      "[Ishgard] The Last Vigil",
                      "[Ishgard] The Gates of Judgement (Coerthas Central Highlands)",
                      "[Idyllshire] Aetheryte Plaza",
                      "[Idyllshire] West Idyllshire",
                      "[Idyllshire] Prologue Gate",
                      "[Idyllshire] Epilogue Gate",
                      "[Rhalgr's Reach] Aetheryte Plaza",
                      "[Rhalgr's Reach] Western Rhalgr's Reach",
                      "[Rhalgr's Reach] Northeastern Rhalgr's Reach",
                      "[Rhalgr's Reach] Fringes Gate",
                      "[Rhalgr's Reach] Peaks Gate",
                      "[Kugane] Aetheryte Plaza",
                      "[Kugane] Shiokaze Hostelry",
                      "[Kugane] Pier #1",
                      "[Kugane] Thavnairian Consulate",
                      "[Kugane] Kogane Dori Markets",
                      "[Kugane] Bokairo Inn",
                      "[Kugane] The Ruby Bazaar",
                      "[Kugane] Sekiseigumi Barracks",
                      "[Kugane] Rakuza District",
                      "[Kugane] The Ruby Price",
                      "[Kugane] Airship Landing",
                      "[Crystarium] Aetheryte Plaza",
                      "[Crystarium] Musica Universalis Markets",
                      "[Crystarium] Themenos Rookery",
                      "[Crystarium] The Dossal Gate",
                      "[Crystarium] The Pendants",
                      "[Crystarium] The Amaro Launch",
                      "[Crystarium] The Crystalline Mean",
                      "[Crystarium] The Cabinet of Curiosity",
                      "[Crystarium] Tessellation (Lakeland)",
                      "[Eulmore] Aetheryte Plaza",
                      "[Eulmore] Southeast Derelicts",
                      "[Eulmore] Nightsoil Pots",
                      "[Eulmore] The Glory Gate",
                      "[Eulmore] The Mainstay",
                      "[Eulmore] The Path to Glory (Kholusia)",
                      "[Old Sharlayan] Aetheryte Plaza",
                      "[Old Sharlayan] The Studium",
                      "[Old Sharlayan] The Baldesion Annex",
                      "[Old Sharlayan] The Rostra",
                      "[Old Sharlayan] The Leveilleur Estate",
                      "[Old Sharlayan] Journey's End",
                      "[Old Sharlayan] Scholar's Harbor",
                      "[Old Sharlayan] The Hall of Artifice (Labyrinthos)",
                      "[Radz-at-Han] Aetheryte Plaza",
                      "[Radz-at-Han] Meghaduta",
                      "[Radz-at-Han] Ruveydah Fibers",
                      "[Radz-at-Han] Airship Landing",
                      "[Radz-at-Han] Alzadaal's Peace",
                      "[Radz-at-Han] Hall of the Radiant Host",
                      "[Radz-at-Han] Mehryde's Meyhane",
                      "[Radz-at-Han] Kama",
                      "[Radz-at-Han] The High Crucible of Al-Kimiya",
                      "[Radz-at-Han] The Gate of First Sight (Thavnair)"
                    ]
                  }
                },
                "ItemId": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "The Item to use",
                  "exclusiveMinimum": 0
                },
                "SkipIf": {
                  "type": "array",
                  "description": "TODO Not implemented",
                  "items": {
                    "type": "string",
                    "enum": [
                      "Never",
                      "FlyingLocked",
                      "FlyingUnlocked",
                      "DifferentTerritory"
                    ]
                  }
                },
                "CompletionQuestVariablesFlags": {
                  "type": "array",
                  "description": "Quest Variables that dictate whether or not this step is skipped: null is don't check, positive values need to be set, negative values need to be unset",
                  "items": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "enum": [
                      null,
                      1,
                      2,
                      4,
                      8,
                      16,
                      32,
                      64,
                      128,
                      -1,
                      -2,
                      -4,
                      -8,
                      -16,
                      -32,
                      -64,
                      -128
                    ]
                  },
                  "minItems": 6,
                  "maxItems": 6
                },
                "Comment": {
                  "type": "string"
                }
              },
              "required": [
                "TerritoryId",
                "InteractionType"
              ],
              "allOf": [
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "Interact"
                      }
                    }
                  },
                  "then": {
                    "required": [
                      "DataId"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "WalkTo"
                      }
                    }
                  },
                  "then": {
                    "required": [
                      "Position"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "anyOf": [
                          {
                            "const": "AttuneAethernetShard"
                          },
                          {
                            "const": "AttuneAetheryte"
                          }
                        ]
                      }
                    }
                  },
                  "then": {
                    "required": [
                      "DataId",
                      "Position"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "AttuneAetherCurrent"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "AetherCurrentId": {
                        "type": "integer",
                        "description": "The aether current id, used to check if a given aetheryte is unlocked",
                        "exclusiveMinimum": 0
                      }
                    },
                    "required": [
                      "DataId",
                      "Position",
                      "AetherCurrentId"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "Combat"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "EnemySpawnType": {
                        "type": "string",
                        "description": "Determines how enemy spawning is handled in combat locations",
                        "enum": [
                          "AutoOnEnterArea",
                          "AfterInteraction",
                          "AfterItemUse",
                          "OverworldEnemies"
                        ]
                      },
                      "KillEnemyDataIds": {
                        "description": "The enemy data ids which are supposed to be killed",
                        "type": "array",
                        "items": {
                          "type": "integer"
                        }
                      }
                    },
                    "required": [
                      "Position",
                      "EnemySpawnType",
                      "KillEnemyDataIds"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "UseItem"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "GroundTarget": {
                        "type": [
                          "boolean",
                          "null"
                        ],
                        "default": false
                      }
                    },
                    "required": [
                      "Position",
                      "ItemId"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "Emote"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "Emote": {
                        "type": "string",
                        "description": "The emote to use",
                        "enum": [
                          "stretch",
                          "wave",
                          "rally",
                          "deny",
                          "pray"
                        ]
                      }
                    },
                    "required": [
                      "Position",
                      "Emote"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "Say"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "ChatMessage": {
                        "type": "object",
                        "description": "The text to use with /say",
                        "properties": {
                          "ExcelSheet": {
                            "type": "string"
                          },
                          "Key": {
                            "type": "string"
                          }
                        },
                        "required": [
                          "Key"
                        ]
                      }
                    },
                    "required": [
                      "ChatMessage"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "Jump"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "JumpDestination": {
                        "type": "object",
                        "properties": {
                          "Position": {
                            "type": "object",
                            "description": "Position to try reaching after the jump",
                            "properties": {
                              "X": {
                                "type": "number"
                              },
                              "Y": {
                                "type": "number"
                              },
                              "Z": {
                                "type": "number"
                              }
                            },
                            "required": [
                              "X",
                              "Y",
                              "Z"
                            ]
                          },
                          "StopDistance": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "Set if pathfinding should stop closer or further away from the default stop distance",
                            "exclusiveMinimum": 0
                          },
                          "DelaySeconds": {
                            "type": [
                              "number",
                              "null"
                            ]
                          }
                        },
                        "required": [
                          "Position"
                        ]
                      }
                    },
                    "required": [
                      "Position",
                      "JumpDestination"
                    ]
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "anyOf": [
                          {
                            "const": "Interact"
                          },
                          {
                            "const": "SinglePlayerDuty"
                          },
                          {
                            "const": "WaitForManualProgress"
                          }
                        ]
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "DialogueChoices": {
                        "type": "array",
                        "items": {
                          "type": "object",
                          "properties": {
                            "Type": {
                              "type": "string",
                              "enum": [
                                "YesNo",
                                "List"
                              ]
                            },
                            "ExcelSheet": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "Type"
                          ],
                          "allOf": [
                            {
                              "if": {
                                "properties": {
                                  "Type": {
                                    "const": "YesNo"
                                  }
                                }
                              },
                              "then": {
                                "properties": {
                                  "Prompt": {
                                    "type": [
                                      "string",
                                      "integer"
                                    ]
                                  },
                                  "Yes": {
                                    "type": "boolean",
                                    "default": true
                                  }
                                },
                                "required": [
                                  "Prompt",
                                  "Yes"
                                ]
                              }
                            },
                            {
                              "if": {
                                "properties": {
                                  "Type": {
                                    "const": "List"
                                  }
                                }
                              },
                              "then": {
                                "properties": {
                                  "Prompt": {
                                    "type": [
                                      "string",
                                      "integer",
                                      "null"
                                    ]
                                  },
                                  "Answer": {
                                    "type": [
                                      "string",
                                      "integer"
                                    ]
                                  }
                                },
                                "required": [
                                  "Prompt",
                                  "Answer"
                                ]
                              }
                            }
                          ]
                        }
                      }
                    }
                  }
                },
                {
                  "if": {
                    "properties": {
                      "InteractionType": {
                        "const": "Duty"
                      }
                    }
                  },
                  "then": {
                    "properties": {
                      "ContentFinderConditionId": {
                        "type": "integer",
                        "exclusiveMinimum": 0
                      }
                    },
                    "required": [
                      "ContentFinderConditionId"
                    ]
                  }
                }
              ]
            }
          },
          "Comment": {
            "type": "string"
          }
        },
        "required": [
          "Sequence"
        ]
      }
    }
  },
  "required": [
    "QuestSequence",
    "Author"
  ]
}