"Z": -464.7746
           },
           "TerritoryId": 956,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         },
         {
           "DataId": 1038716,
             "Z": -458.2132
           },
           "TerritoryId": 956,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         }
       ]
     },
             "Z": -519.18823
           },
           "TerritoryId": 956,
-          "InteractionType": "SinglePlayerDuty",
-          "Comment": "Duty - Shoot Large Green Bird"
+          "InteractionType": "WaitForManualProgress",
+          "Comment": "Shoot Large Green Bird"
         }
       ]
     },
 
             "Z": -108.537415
           },
           "TerritoryId": 956,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         },
         {
           "DataId": 1038707,
             "Z": -150.04199
           },
           "TerritoryId": 956,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 1038708,
             "Z": -130.11371
           },
           "TerritoryId": 956,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         }
       ]
     },
 
           "Comment": "A Frosty Reception",
           "DialogueChoices": [
             {
-              "Type": "ContentTalkList",
-              "Prompt": "264",
-              "Answer": "267"
+              "Type": "List",
+              "Prompt": 264,
+              "Answer": 267
             },
             {
-              "Type": "ContentTalkYesNo",
-              "Prompt": "268",
+              "Type": "YesNo",
+              "Prompt": 268,
               "Yes": true
             }
           ]
 
           },
           "TerritoryId": 960,
           "InteractionType": "WaitForManualProgress",
-          "Comment": "Duty - Find Errant Omicron"
+          "Comment": "Find Errant Omicron"
         }
       ]
     },
 
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         },
         {
           "DataId": 1032121,
 
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         }
       ]
     },
           "TerritoryId": 815,
           "InteractionType": "UseItem",
           "ItemId": 2002904,
-          "$.1": "QuestVariables if done first: 1 32 0 0 0 64"
+          "$.1": "QuestVariables if done first: 1 32 0 0 0 64",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 1027909,
           "TerritoryId": 815,
           "InteractionType": "UseItem",
           "ItemId": 2002904,
-          "$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96"
+          "$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 1027939,
           },
           "TerritoryId": 815,
           "InteractionType": "UseItem",
-          "ItemId": 2002904
+          "ItemId": 2002904,
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         }
       ]
     },
 
             "Z": 305.19568
           },
           "TerritoryId": 815,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMG104_03676_Q2_000_100",
+              "Answer": "TEXT_LUCKMG104_03676_A1_000_100"
+            }
+          ]
         }
       ]
     },
           "StopDistance": 1,
           "TerritoryId": 815,
           "InteractionType": "Interact",
-          "$.1": "QuestVariables if done first: 16 16 16 0 0 32"
+          "$.1": "QuestVariables if done first: 16 16 16 0 0 32",
+          "Fly": true,
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 2010810,
           },
           "TerritoryId": 815,
           "InteractionType": "Interact",
-          "$.1": "QuestVariables if done after [1]: 33 16 32 0 0 96"
+          "$.1": "QuestVariables if done after [1]: 33 16 32 0 0 96",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 2010809,
           },
           "TerritoryId": 815,
           "InteractionType": "Interact",
-          "Comment": "Combat not necessary to progress quest"
+          "Comment": "Combat not necessary to progress quest",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         }
       ]
     },
     {
       "Sequence": 4,
       "Steps": [
+        {
+          "Position": {
+            "X": 47.593674,
+            "Y": 42.681213,
+            "Z": -511.2799
+          },
+          "TerritoryId": 815,
+          "InteractionType": "WalkTo",
+          "Comment": "Should be far enough to reset combat"
+        },
         {
           "DataId": 1031732,
           "Position": {
           },
           "TerritoryId": 815,
           "InteractionType": "Interact",
-          "AetheryteShortcut": "Amh Araeng - Inn at Journey's Head"
+          "AetheryteShortcut": "Amh Araeng - Inn at Journey's Head",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMG104_03676_Q3_000_200",
+              "Answer": "TEXT_LUCKMG104_03676_A1_000_200"
+            }
+          ]
         }
       ]
     },
 
           },
           "TerritoryId": 820,
           "InteractionType": "Interact",
-          "$.1": "QuestValues if done first: 16 1 16 0 0 128"
+          "$.1": "QuestValues if done first: 16 1 16 0 0 128",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         },
         {
           "DataId": 1027602,
             "[Eulmore] Aetheryte Plaza",
             "[Eulmore] Southeast Derelicts"
           ],
-          "$.1": "QuestValues if done after [1]: 32 17 16 16 0 160"
+          "$.1": "QuestValues if done after [1]: 32 17 16 16 0 160",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 1029990,
           "AethernetShortcut": [
             "[Eulmore] Southeast Derelicts",
             "[Eulmore] The Glory Gate"
+          ],
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
           ]
         }
       ]
 
             "Z": -161.45575
           },
           "TerritoryId": 814,
-          "InteractionType": "SinglePlayerDuty",
+          "InteractionType": "WaitForManualProgress",
           "Comment": "Help Master Chai dodge enemies"
         }
       ]
 
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         },
         {
           "DataId": 1032121,
           },
           "TerritoryId": 351,
           "InteractionType": "SinglePlayerDuty",
-          "Comment": "Estinien vs. Arch Ultima"
+          "Comment": "Estinien vs. Arch Ultima",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_LUCKMG110_03682_Q1_100_125",
+              "Yes": true
+            }
+          ]
         }
       ]
     },
 
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         },
         {
           "DataId": 1032121,
 
             "Z": 14.22064
           },
           "TerritoryId": 844,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "TargetTerritoryId": 819
         },
         {
           "DataId": 1030370,
             "Z": 13.321045
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMH103_03763_Q1_000_500",
+              "Answer": "TEXT_LUCKMH103_03763_A1_000_500"
+            }
+          ]
         }
       ]
     },
 
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         },
         {
           "DataId": 1031722,
             "Z": 14.206055
           },
           "TerritoryId": 844,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "TargetTerritoryId": 819
         },
         {
           "DataId": 1027248,
           "InteractionType": "Interact",
           "Comment": "Chessamile",
           "$.0": "[1]",
-          "$.1": "QuestVariables if done first: 1 0 0 0 0 64"
+          "$.1": "QuestVariables if done first: 1 0 0 0 0 64",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 1027224,
           "InteractionType": "Interact",
           "Comment": "Bragi",
           "$.0": "[2]",
-          "$.1": "QuestVariables if done after [1]: 2 0 0 0 0 192"
+          "$.1": "QuestVariables if done after [1]: 2 0 0 0 0 192",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         },
         {
           "DataId": 1027322,
           "InteractionType": "Interact",
           "Comment": "Glynard",
           "$.0": "[3]",
-          "$.1": "QuestVariables if done after [1, 2]: 3 0 0 0 0 200"
+          "$.1": "QuestVariables if done after [1, 2]: 3 0 0 0 0 200",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            8
+          ]
         },
         {
           "DataId": 1027232,
             "[Crystarium] The Crystalline Mean"
           ],
           "$.0": "[4]",
-          "$.1": "QuestVariables if done after [1, 2, 3]: 4 0 0 0 0 216"
+          "$.1": "QuestVariables if done after [1, 2, 3]: 4 0 0 0 0 216",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            16
+          ]
         },
         {
           "DataId": 1027226,
           "AethernetShortcut": [
             "[Crystarium] The Crystalline Mean",
             "[Crystarium] The Cabinet of Curiosity"
+          ],
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
           ]
         }
       ]
 
           "TerritoryId": 817,
           "InteractionType": "SinglePlayerDuty",
           "Fly": true,
-          "Comment": "Duty - A Sleep Disturbed (Opo-Opo, Wolf, Serpent)"
+          "Comment": "A Sleep Disturbed (Opo-Opo, Wolf, Serpent)",
+          "$": "The dialogue choices and data ids here are recycled",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "DataId": 2011009,
+              "ExcelSheet": "GimmickYesNo",
+              "Prompt": 138,
+              "Yes": true
+            },
+            {
+              "Type": "YesNo",
+              "DataId": 2011006,
+              "ExcelSheet": "GimmickYesNo",
+              "Prompt": 139,
+              "Yes": true
+            },
+            {
+              "Type": "YesNo",
+              "DataId": 2011007,
+              "ExcelSheet": "GimmickYesNo",
+              "Prompt": 142,
+              "Yes": true
+            }
+          ]
         }
       ]
     },
 
     {
       "Sequence": 2,
       "Steps": [
+        {
+          "Position": {
+            "X": -475.38354,
+            "Y": 400.55338,
+            "Z": -779.4299
+          },
+          "TerritoryId": 818,
+          "InteractionType": "WalkTo",
+          "Fly": true,
+          "SkipIf": [
+            "FlyingLocked"
+          ]
+        },
         {
           "Position": {
             "X": -423.6145,
 
           },
           "TerritoryId": 813,
           "InteractionType": "WalkTo",
-          "AetheryteShortcut": "Lakeland - Ostall Imperative",
+          "AetheryteShortcut": "Lakeland - Fort Jobb",
           "Fly": true
         },
         {
           "TerritoryId": 813,
           "InteractionType": "Interact",
           "DisableNavmesh": true,
-          "$.1": "QuestVariables if done first: 1 0 0 0 0 64"
+          "$.1": "QuestVariables if done first: 1 0 0 0 0 64",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 2010278,
           },
           "TerritoryId": 813,
           "InteractionType": "Interact",
-          "DisableNavmesh": true
+          "DisableNavmesh": true,
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         },
         {
           "DataId": 2010282,
           },
           "TerritoryId": 813,
           "InteractionType": "Interact",
-          "DisableNavmesh": true
+          "DisableNavmesh": true,
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ],
+          "Comment": "TODO Check if pathfinding works automatically now"
         }
       ]
     },
 
 {
   "$schema": "https://carvel.li/questionable/quest-1.0",
   "Author": "liza",
-  "Comment": "TODO Missing quest end",
   "TerritoryBlacklist": [
     898
   ],
           },
           "TerritoryId": 814,
           "InteractionType": "Interact",
+          "AetheryteShortcut": "Kholusia - Wright",
           "Fly": true
         }
       ]
           "ContentFinderConditionId": 714
         }
       ]
+    },
+    {
+      "Sequence": 255,
+      "Steps": [
+        {
+          "DataId": 1032549,
+          "Position": {
+            "X": -1.9074707,
+            "Y": -200.00002,
+            "Z": -425.10114
+          },
+          "TerritoryId": 918,
+          "InteractionType": "Interact"
+        }
+      ]
     }
   ]
 }
 
       ]
     },
     {
-      "Sequence": 1,
-      "Comment": "TODO verify this is the correct sequence and/or where sequence 2 went",
+      "Sequence": 2,
       "Steps": [
         {
           "DataId": 1032529,
           "AethernetShortcut": [
             "[Crystarium] The Amaro Launch",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         },
         {
           "DataId": 1032121,
             "Z": 14.206055
           },
           "TerritoryId": 844,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "TargetTerritoryId": 819
         },
         {
           "DataId": 1030610,
           "AethernetShortcut": [
             "[Crystarium] The Dossal Gate",
             "[Crystarium] The Pendants"
+          ],
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_LUCKMH110_03770_Q1_000_600",
+              "Yes": true
+            }
           ]
         }
       ]
 
             "Z": -277.7906
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMI101_03771_Q3_000_148",
+              "Answer": "TEXT_LUCKMI101_03771_A3_000_149"
+            }
+          ]
         }
       ]
     },
           },
           "TerritoryId": 819,
           "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ],
           "$.1": "QuestVariables if done first: 1 16 0 0 0 64"
         },
         {
           "StopDistance": 5,
           "TerritoryId": 819,
           "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ],
           "$.1": "QuestVariables if done after [1]: 2 32 0 0 0 192"
         },
         {
             "Z": 173.38818
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         }
       ]
     },
     {
       "Sequence": 255,
       "Steps": [
-        {
-          "Position": {
-            "X": -140.22343,
-            "Y": 0.05337119,
-            "Z": 34.20123
-          },
-          "TerritoryId": 819,
-          "InteractionType": "WalkTo"
-        },
         {
           "DataId": 1027248,
           "Position": {
             "Z": -51.438232
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "AetheryteShortcut": "Crystarium"
         }
       ]
     }
 
     },
     {
       "Sequence": 2,
+      "Comment": "This isn't solving for the 'best' results, but for the closest waypoints",
       "Steps": [
         {
           "DataId": 2011078,
           ],
           "Fly": true,
           "$.0": "[1]",
-          "$.1": "QuestVariables if done first: 0 0 0 3 0 0 during fight; 16 1 0 2 16 8 after"
+          "$.1": "QuestVariables if done first: 0 0 0 3 0 0 during fight; 16 1 0 2 16 8 after",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            8
+          ]
         },
         {
           "DataId": 2011076,
           "InteractionType": "Combat",
           "EnemySpawnType": "AfterItemUse",
           "ItemId": 2003001,
-          "KillEnemyDataIds": [],
-          "Comment": "TODO Missing enemy ids",
+          "KillEnemyDataIds": [
+            12166
+          ],
           "Fly": true,
-          "$.1": "QuestVariables if done after [1]: 34 1 0 1 48 40"
+          "$.1": "QuestVariables if done after [1]: 34 1 0 1 48 40",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 2011079,
           "EnemySpawnType": "AfterItemUse",
           "ItemId": 2003001,
           "KillEnemyDataIds": [
+            12168
           ],
           "Comment": "TODO Missing enemy ids",
           "Fly": true,
-          "$.2": "QuestVariables if done after [1, 2]: 0 64 0 0 0 0"
+          "$.2": "QuestVariables if done after [1, 2]: irrelevant because it automatically progresses to the next step"
         }
       ]
     },
 
           "AethernetShortcut": [
             "[Crystarium] Aetheryte Plaza",
             "[Crystarium] The Dossal Gate"
-          ]
+          ],
+          "TargetTerritoryId": 844
         },
         {
           "DataId": 1033819,
 
             "Z": 604.27246
           },
           "TerritoryId": 814,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_LUCKMI105_03775_Q2_000_052",
+              "Yes": true
+            }
+          ]
         }
       ]
     },
 
             "Z": 1.6021729
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMI108_03778_Q1_000_001",
+              "Answer": "TEXT_LUCKMI108_03778_A1_000_002"
+            }
+          ]
         }
       ]
     },
     {
-      "Sequence": 1,
+      "Sequence": 2,
       "Steps": [
         {
           "TerritoryId": 931,
 
       "Sequence": 5,
       "Steps": [
         {
+          "Position": {
+            "X": 0,
+            "Y": 0,
+            "Z": 0
+          },
           "TerritoryId": 820,
-          "InteractionType": "Interact",
+          "InteractionType": "WalkTo",
           "AetheryteShortcut": "Eulmore"
         }
       ]
 
             "Z": 3.982544
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "AetheryteShortcut": "Crystarium",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMI111_03781_Q1_000_153",
+              "Answer": "TEXT_LUCKMI111_03781_A1_000_154"
+            }
+          ]
         }
       ]
     },
 
             "Z": 7.156433
           },
           "TerritoryId": 819,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_LUCKMI112_03782_Q1_000_007",
+              "Yes": true
+            }
+          ]
         },
         {
           "DataId": 1033888,
             "Z": -5.081299
           },
           "TerritoryId": 844,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_LUCKMI112_03782_Q2_000_044",
+              "Yes": true
+            }
+          ]
         }
       ]
     },
 
           "EnemySpawnType": "AfterInteraction",
           "KillEnemyDataIds": [
             12661
-          ]
+          ],
+          "Fly": true
         }
       ]
     },
 
             "Z": -6.9733887
           },
           "TerritoryId": 351,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "TargetTerritoryId": 351
         },
         {
           "DataId": 2011332,
 
           },
           "StopDistance": 5,
           "TerritoryId": 351,
-          "InteractionType": "Interact"
+          "InteractionType": "Interact",
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMJ104_04010_Q1_000_000",
+              "Answer": "TEXT_LUCKMJ104_04010_A1_000_002"
+            }
+          ]
         }
       ]
     },
 
           },
           "TerritoryId": 129,
           "InteractionType": "Interact",
-          "AetheryteShortcut": "Limsa Lominsa"
+          "AetheryteShortcut": "Limsa Lominsa",
+          "DialogueChoices": [
+            {
+              "Type": "YesNo",
+              "Prompt": "TEXT_LUCKMJ108_04014_SYSTEM_100_010",
+              "Yes": true
+            }
+          ]
         },
         {
           "DataId": 1002694,
 
     {
       "Sequence": 2,
       "Steps": [
+        {
+          "Position": {
+            "X": 46.600548,
+            "Y": 77.45801,
+            "Z": -366.82053
+          },
+          "TerritoryId": 180,
+          "InteractionType": "WalkTo",
+          "Fly": true
+        },
+        {
+          "Position": {
+            "X": 111.927666,
+            "Y": 26.050894,
+            "Z": -612.8873
+          },
+          "TerritoryId": 180,
+          "InteractionType": "WalkTo",
+          "Fly": true
+        },
         {
           "Position": {
             "X": 82.19566,
 
           "TerritoryId": 402,
           "InteractionType": "Interact",
           "Fly": true,
-          "$.1": "QuestVariables if done first: 1 16 0 0 0 64"
+          "$.1": "QuestVariables if done first: 1 16 0 0 0 64",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            64
+          ]
         },
         {
           "DataId": 1036359,
           "InteractionType": "Interact",
           "Mount": true,
           "Fly": true,
-          "$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96"
+          "$.1": "QuestVariables if done after [1]: 2 16 0 0 0 96",
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            32
+          ]
         },
         {
           "DataId": 1036357,
           },
           "TerritoryId": 402,
           "InteractionType": "Interact",
-          "DisableNavmesh": true
+          "DisableNavmesh": true,
+          "CompletionQuestVariablesFlags": [
+            null,
+            null,
+            null,
+            null,
+            null,
+            128
+          ]
         }
       ]
     },
           },
           "TerritoryId": 402,
           "InteractionType": "Interact",
-          "Fly": true
+          "Fly": true,
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMK103_04060_Q1_000_100",
+              "Answer": "TEXT_LUCKMK103_04060_A2_000_100"
+            }
+          ]
         }
       ]
     },
 
           "AethernetShortcut": [
             "[Ul'dah] Aetheryte Plaza",
             "[Ul'dah] Alchemists' Guild"
+          ],
+          "DialogueChoices": [
+            {
+              "Type": "List",
+              "Prompt": "TEXT_LUCKMK106_04063_Q1_000_100",
+              "Answer": "TEXT_LUCKMK106_04063_A2_000_100"
+            }
           ]
         }
       ]
 
                               "type": "string",
                               "enum": [
                                 "YesNo",
-                                "List",
-                                "ContentTalkYesNo",
-                                "ContentTalkList"
+                                "List"
                               ]
                             },
                             "ExcelSheet": {
                               "type": "string"
-                            },
-                            "Prompt": {
-                              "type": [
-                                "string",
-                                "null"
-                              ]
                             }
                           },
                           "required": [
-                            "Type",
-                            "Prompt"
+                            "Type"
                           ],
                           "allOf": [
                             {
                               "if": {
                                 "properties": {
                                   "Type": {
-                                    "anyOf": [
-                                      {
-                                        "const": "YesNo"
-                                      },
-                                      {
-                                        "const": "ContentTalkYesNo"
-                                      }
-                                    ]
+                                    "const": "YesNo"
                                   }
                                 }
                               },
                               "then": {
                                 "properties": {
+                                  "Prompt": {
+                                    "type": [
+                                      "string",
+                                      "integer"
+                                    ]
+                                  },
                                   "Yes": {
                                     "type": "boolean",
                                     "default": true
                                   }
                                 },
                                 "required": [
+                                  "Prompt",
                                   "Yes"
                                 ]
                               }
                               "if": {
                                 "properties": {
                                   "Type": {
-                                    "anyOf": [
-                                      {
-                                        "const": "List"
-                                      },
-                                      {
-                                        "const": "ContentTalkList"
-                                      }
-                                    ]
+                                    "const": "List"
                                   }
                                 }
                               },
                               "then": {
                                 "properties": {
+                                  "Prompt": {
+                                    "type": [
+                                      "string",
+                                      "integer",
+                                      "null"
+                                    ]
+                                  },
                                   "Answer": {
-                                    "type": "string"
+                                    "type": [
+                                      "string",
+                                      "integer"
+                                    ]
                                   }
                                 },
                                 "required": [
+                                  "Prompt",
                                   "Answer"
                                 ]
                               }
 
 internal sealed class Configuration : IPluginConfiguration
 {
     public int Version { get; set; } = 1;
-    public WindowConfig DebugWindowConfig { get; set; } = new();
+    public GeneralConfiguration General { get; } = new();
+    public AdvancedConfiguration Advanced { get; } = new();
+    public WindowConfig DebugWindowConfig { get; } = new();
+    public WindowConfig ConfigWindowConfig { get; } = new();
+
+    internal sealed class GeneralConfiguration
+    {
+        public bool AutoAcceptNextQuest { get; set; }
+        public uint MountId { get; set; } = 71;
+    }
+
+    internal sealed class AdvancedConfiguration
+    {
+        public bool NeverFly { get; set; }
+    }
 }
 
 using System.Linq;
 using Dalamud.Game.Addon.Lifecycle;
 using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
+using Dalamud.Game.ClientState.Objects;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Client.UI;
 using FFXIVClientStructs.FFXIV.Component.GUI;
     private readonly GameFunctions _gameFunctions;
     private readonly QuestController _questController;
     private readonly IGameGui _gameGui;
+    private readonly ITargetManager _targetManager;
     private readonly ILogger<GameUiController> _logger;
 
     public GameUiController(IAddonLifecycle addonLifecycle, IDataManager dataManager, GameFunctions gameFunctions,
-        QuestController questController, IGameGui gameGui, ILogger<GameUiController> logger)
+        QuestController questController, IGameGui gameGui, ITargetManager targetManager,
+        ILogger<GameUiController> logger)
     {
         _addonLifecycle = addonLifecycle;
         _dataManager = dataManager;
         _gameFunctions = gameFunctions;
         _questController = questController;
         _gameGui = gameGui;
+        _targetManager = targetManager;
         _logger = logger;
 
         _addonLifecycle.RegisterListener(AddonEvent.PostSetup, "SelectString", SelectStringPostSetup);
 
         foreach (var dialogueChoice in dialogueChoices)
         {
+            if (dialogueChoice.Type != EDialogChoiceType.List)
+                continue;
+
             if (dialogueChoice.Answer == null)
             {
-                _logger.LogInformation("Ignoring entry in DialogueChoices, no answer");
+                _logger.LogDebug("Ignoring entry in DialogueChoices, no answer");
                 continue;
             }
 
-            string? excelPrompt = null, excelAnswer;
-            switch (dialogueChoice.Type)
+            if (dialogueChoice.DataId != null && dialogueChoice.DataId != _targetManager.Target?.DataId)
             {
-                case EDialogChoiceType.ContentTalkList:
-                    if (dialogueChoice.Prompt != null)
-                    {
-                        excelPrompt =
-                            _gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
-                                CultureInfo.InvariantCulture));
-                    }
-
-                    excelAnswer =
-                        _gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Answer, CultureInfo.InvariantCulture));
-                    break;
-                case EDialogChoiceType.List:
-                    if (dialogueChoice.Prompt != null)
-                    {
-                        excelPrompt =
-                            _gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
-                    }
-
-                    excelAnswer =
-                        _gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
-                    break;
-                default:
-                    continue;
+                _logger.LogDebug(
+                    "Skipping entry in DialogueChoice expecting target dataId {ExpectedDataId}, actual target is {ActualTargetId}",
+                    dialogueChoice.DataId, _targetManager.Target?.DataId);
+                continue;
             }
 
+            string? excelPrompt = ResolveReference(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
+            string? excelAnswer = ResolveReference(quest, dialogueChoice.ExcelSheet, dialogueChoice.Answer);
+
             if (actualPrompt == null && !string.IsNullOrEmpty(excelPrompt))
             {
                 _logger.LogInformation("Unexpected excelPrompt: {ExcelPrompt}", excelPrompt);
         _logger.LogTrace("DefaultYesNo: Choice count: {Count}", dialogueChoices.Count);
         foreach (var dialogueChoice in dialogueChoices)
         {
-            string? excelPrompt;
-            if (dialogueChoice.Prompt != null)
+            if (dialogueChoice.Type != EDialogChoiceType.YesNo)
+                continue;
+
+            if (dialogueChoice.DataId != null && dialogueChoice.DataId != _targetManager.Target?.DataId)
             {
-                switch (dialogueChoice.Type)
-                {
-                    case EDialogChoiceType.ContentTalkYesNo:
-                        excelPrompt =
-                            _gameFunctions.GetContentTalk(uint.Parse(dialogueChoice.Prompt,
-                                CultureInfo.InvariantCulture));
-                        break;
-                    case EDialogChoiceType.YesNo:
-                        excelPrompt =
-                            _gameFunctions.GetDialogueText(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
-                        break;
-                    default:
-                        continue;
-                }
+                _logger.LogDebug(
+                    "Skipping entry in DialogueChoice expecting target dataId {ExpectedDataId}, actual target is {ActualTargetId}",
+                    dialogueChoice.DataId, _targetManager.Target?.DataId);
+                continue;
             }
-            else
-                excelPrompt = null;
 
+            string? excelPrompt = ResolveReference(quest, dialogueChoice.ExcelSheet, dialogueChoice.Prompt);
             if (excelPrompt == null || !GameStringEquals(actualPrompt, excelPrompt))
+            {
+                _logger.LogInformation("Unexpected excelPrompt: {ExcelPrompt}, actualPrompt: {ActualPrompt}",
+                    excelPrompt, actualPrompt);
                 continue;
+            }
 
             addonSelectYesno->AtkUnitBase.FireCallbackInt(dialogueChoice.Yes ? 0 : 1);
             if (!checkAllSteps)
             increaseStepCount = false;
 
             if (step != null)
-                _logger.LogTrace("Previous step: {CurrentTerritory}, {TargetTerritory}", step.TerritoryId, step.TargetTerritoryId);
+                _logger.LogTrace("Previous step: {CurrentTerritory}, {TargetTerritory}", step.TerritoryId,
+                    step.TargetTerritoryId);
         }
 
         if (step == null || step.TargetTerritoryId == null)
             _logger.LogInformation("Using warp {Id}, {Prompt}", entry.RowId, excelPrompt);
             addonSelectYesno->AtkUnitBase.FireCallbackInt(0);
             //if (increaseStepCount)
-                //_questController.IncreaseStepCount();
+            //_questController.IncreaseStepCount();
             return;
         }
     }
         return a.ReplaceLineEndings().Replace('\u2013', '-') == b.ReplaceLineEndings().Replace('\u2013', '-');
     }
 
+    private string? ResolveReference(Quest quest, string? excelSheet, ExcelRef? excelRef)
+    {
+        if (excelRef == null)
+            return null;
+
+        if (excelRef.Type == ExcelRef.EType.Key)
+            return _gameFunctions.GetDialogueText(quest, excelSheet, excelRef.AsKey());
+        else if (excelRef.Type == ExcelRef.EType.RowId)
+            return _gameFunctions.GetDialogueTextByRowId(excelSheet, excelRef.AsRowId());
+
+        return null;
+    }
+
     public void Dispose()
     {
         _addonLifecycle.UnregisterListener(AddonEvent.PostSetup, "AkatsukiNote", UnendingCodexPostSetup);
 
                     }
                 }
                 else if (!Destination.IsFlying && !_condition[ConditionFlag.Mounted] && navPoints.Count > 0 &&
-                         !_gameFunctions.HasStatusPreventingSprintOrMount() && Destination.CanSprint)
+                         !_gameFunctions.HasStatusPreventingSprintOrMount(true) && Destination.CanSprint)
                 {
                     float actualDistance = 0;
                     foreach (Vector3 end in navPoints)
         _logger.LogInformation("Pathfinding to {Destination}", Destination);
 
         _cancellationTokenSource = new();
-        _cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(10));
+        _cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(30));
         _pathfindTask =
             _navmeshIpc.Pathfind(_clientState.LocalPlayer!.Position, to, fly, _cancellationTokenSource.Token);
     }
 
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
 using FFXIVClientStructs.FFXIV.Client.Game;
+using FFXIVClientStructs.FFXIV.Client.Game.UI;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller.Steps;
 using Questionable.Data;
     private readonly ILogger<QuestController> _logger;
     private readonly QuestRegistry _questRegistry;
     private readonly IKeyState _keyState;
+    private readonly Configuration _configuration;
     private readonly IReadOnlyList<ITaskFactory> _taskFactories;
 
     private readonly Queue<ITask> _taskQueue = new();
         ILogger<QuestController> logger,
         QuestRegistry questRegistry,
         IKeyState keyState,
+        Configuration configuration,
         IEnumerable<ITaskFactory> taskFactories)
     {
         _clientState = clientState;
         _logger = logger;
         _questRegistry = questRegistry;
         _keyState = keyState;
+        _configuration = configuration;
         _taskFactories = taskFactories.ToList().AsReadOnly();
     }
 
         if (CurrentQuest != null && CurrentQuest.Quest.Data.TerritoryBlacklist.Contains(_clientState.TerritoryType))
             return;
 
+        // not verified to work
+        if (_automatic && _currentTask == null && _taskQueue.Count == 0 && CurrentQuest is { Sequence: 0, Step: 255 }
+            && DateTime.Now >= CurrentQuest.StepProgress.StartedAt.AddSeconds(15))
+        {
+            _logger.LogWarning("Quest accept apparently didn't work out, resetting progress");
+            CurrentQuest = CurrentQuest with
+            {
+                Step = 0
+            };
+
+            ExecuteNextStep(true);
+            return;
+        }
+
         UpdateCurrentTask();
     }
 
             {
                 _logger.LogInformation("New quest: {QuestName}", quest.Name);
                 CurrentQuest = new QuestProgress(quest, currentSequence, 0);
-                Stop("Different Quest");
+
+                bool continueAutomatically = _configuration.General.AutoAcceptNextQuest;
+
+                if (_clientState.LocalPlayer?.Level < quest.Level)
+                    continueAutomatically = false;
+
+                Stop("Different Quest", continueAutomatically);
             }
             else if (CurrentQuest != null)
             {
             CurrentQuest = CurrentQuest with
             {
                 Step = CurrentQuest.Step + 1,
-                StepProgress = new()
+                StepProgress = new(DateTime.Now),
             };
         }
         else
             CurrentQuest = CurrentQuest with
             {
                 Step = 255,
-                StepProgress = new()
+                StepProgress = new(DateTime.Now),
             };
         }
 
     public bool HasCurrentTaskMatching<T>() =>
         _currentTask is T;
 
+    public bool IsRunning => _currentTask != null || _taskQueue.Count > 0;
+
     public sealed record QuestProgress(
         Quest Quest,
         byte Sequence,
         StepProgress StepProgress)
     {
         public QuestProgress(Quest quest, byte sequence, int step)
-            : this(quest, sequence, step, new StepProgress())
+            : this(quest, sequence, step, new StepProgress(DateTime.Now))
         {
         }
     }
 
     // TODO is this still required?
     public sealed record StepProgress(
+        DateTime StartedAt,
         int DialogueChoicesSelected = 0);
 }
 
                 continue;
 
             quest.Name = questData.Name.ToString();
+            quest.Level = questData.ClassJobLevel0;
         }
     }
 
 
                 return ETaskResult.StillRunning;
             }
 
-            if (aetheryteData.IsCityAetheryte(To))
+            if (aetheryteData.IsAirshipLanding(To))
+            {
+                if (aetheryteData.CalculateAirshipLandingDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
+                        clientState.TerritoryType, To) > 5)
+                    return ETaskResult.StillRunning;
+            }
+            else if (aetheryteData.IsCityAetheryte(To))
             {
                 if (aetheryteData.CalculateDistance(clientState.LocalPlayer?.Position ?? Vector3.Zero,
                         clientState.TerritoryType, To) > 11)
 
 using System.Numerics;
 using Dalamud.Plugin.Services;
 using FFXIVClientStructs.FFXIV.Application.Network.WorkDefinitions;
+using FFXIVClientStructs.FFXIV.Client.Game;
 using Microsoft.Extensions.DependencyInjection;
 using Questionable.Controller.Steps.BaseTasks;
 using Questionable.Model;
                 var task = serviceProvider.GetRequiredService<WaitForCompletionFlags>()
                     .With(quest, step);
                 var delay = serviceProvider.GetRequiredService<WaitDelay>();
-                return [task, delay, new NextStep()];
+                return [task, delay, Next(quest, sequence, step)];
             }
 
             switch (step.InteractionType)
                 case EInteractionType.WalkTo:
                 case EInteractionType.Jump:
                     // no need to wait if we're just moving around
-                    return [new NextStep()];
+                    return [Next(quest, sequence, step)];
 
                 case EInteractionType.WaitForObjectAtPosition:
                     ArgumentNullException.ThrowIfNull(step.DataId);
                         serviceProvider.GetRequiredService<WaitObjectAtPosition>()
                             .With(step.DataId.Value, step.Position.Value),
                         serviceProvider.GetRequiredService<WaitDelay>(),
-                        new NextStep()
+                        Next(quest, sequence, step)
                     ];
 
                 case EInteractionType.Interact when step.TargetTerritoryId != null:
                     [
                         waitInteraction,
                         serviceProvider.GetRequiredService<WaitDelay>(),
-                        new NextStep()
+                        Next(quest, sequence, step)
                     ];
 
                 case EInteractionType.Interact:
                 default:
-                    return [serviceProvider.GetRequiredService<WaitDelay>(), new NextStep()];
+                    return [serviceProvider.GetRequiredService<WaitDelay>(), Next(quest, sequence, step)];
             }
         }
 
         public ITask CreateTask(Quest quest, QuestSequence sequence, QuestStep step)
             => throw new InvalidOperationException();
+
+        public ITask Next(Quest quest, QuestSequence sequence, QuestStep step)
+        {
+            bool lastStep = step == sequence.Steps.LastOrDefault();
+            if (sequence.Sequence == 0 && lastStep)
+            {
+                return new WaitConditionTask(() =>
+                {
+                    unsafe
+                    {
+                        var questManager = QuestManager.Instance();
+                        return questManager != null && questManager->IsQuestAccepted(quest.QuestId);
+                    }
+                }, "Wait(questAccepted)");
+            }
+            else if (sequence.Sequence == 255 && lastStep)
+            {
+                return new WaitConditionTask(() => QuestManager.IsQuestComplete(quest.QuestId),
+                    "Wait(questComplete)");
+            }
+            else
+                return new NextStep();
+        }
     }
 
     internal sealed class WaitDelay() : AbstractDelayedTask(TimeSpan.FromSeconds(1))
 
-using Dalamud.Game.ClientState.Conditions;
+using System;
+using Dalamud.Game.ClientState.Conditions;
 using Dalamud.Plugin.Services;
 using Microsoft.Extensions.Logging;
 
     : ITask
 {
     private bool _unmountTriggered;
+    private DateTime _unmountedAt = DateTime.MinValue;
 
     public bool Start()
     {
 
         logger.LogInformation("Step explicitly wants no mount, trying to unmount...");
         _unmountTriggered = gameFunctions.Unmount();
+        if (_unmountTriggered)
+            _unmountedAt = DateTime.Now;
         return true;
     }
 
         if (!_unmountTriggered)
         {
             _unmountTriggered = gameFunctions.Unmount();
+            if (_unmountTriggered)
+                _unmountedAt = DateTime.Now;
+
             return ETaskResult.StillRunning;
         }
 
+        if (DateTime.Now < _unmountedAt.AddSeconds(1))
+            return ETaskResult.StillRunning;
+
         return condition[ConditionFlag.Mounted]
             ? ETaskResult.StillRunning
             : ETaskResult.TaskComplete;
 
             => throw new InvalidOperationException();
     }
 
+    internal abstract class UseItemBase : ITask
+    {
+        private bool _usedItem;
+        private DateTime _continueAt;
+
+        protected abstract bool UseItem();
+
+        public bool Start()
+        {
+            _usedItem = UseItem();
+            _continueAt = DateTime.Now.AddSeconds(2);
+            return true;
+        }
+
+        public ETaskResult Update()
+        {
+            if (DateTime.Now > _continueAt)
+                return ETaskResult.StillRunning;
+
+            if (!_usedItem)
+            {
+                _usedItem = UseItem();
+                _continueAt = DateTime.Now.AddSeconds(2);
+                return ETaskResult.StillRunning;
+            }
+
+            return ETaskResult.TaskComplete;
+        }
+    }
+
 
-    internal sealed class UseOnGround(GameFunctions gameFunctions) : AbstractDelayedTask
+    internal sealed class UseOnGround(GameFunctions gameFunctions) : UseItemBase
     {
         public uint DataId { get; set; }
         public uint ItemId { get; set; }
             return this;
         }
 
-        protected override bool StartInternal()
-        {
-            gameFunctions.UseItemOnGround(DataId, ItemId);
-            return true;
-        }
+        protected override bool UseItem() => gameFunctions.UseItemOnGround(DataId, ItemId);
 
         public override string ToString() => $"UseItem({ItemId} on ground at {DataId})";
     }
 
-    internal sealed class UseOnObject(GameFunctions gameFunctions) : AbstractDelayedTask
+    internal sealed class UseOnObject(GameFunctions gameFunctions) : UseItemBase
     {
         public uint DataId { get; set; }
         public uint ItemId { get; set; }
             return this;
         }
 
-        protected override bool StartInternal()
-        {
-            gameFunctions.UseItem(DataId, ItemId);
-            return true;
-        }
+        protected override bool UseItem() => gameFunctions.UseItem(DataId, ItemId);
 
         public override string ToString() => $"UseItem({ItemId} on {DataId})";
     }
 
-    internal sealed class Use(GameFunctions gameFunctions) : AbstractDelayedTask
+    internal sealed class Use(GameFunctions gameFunctions) : UseItemBase
     {
         public uint ItemId { get; set; }
 
             return this;
         }
 
-        protected override bool StartInternal()
-        {
-            gameFunctions.UseItem(ItemId);
-            return true;
-        }
+        protected override bool UseItem() => gameFunctions.UseItem(ItemId);
 
         public override string ToString() => $"UseItem({ItemId})";
     }
 
     private readonly NavigationShortcutController _navigationShortcutController;
     private readonly WindowSystem _windowSystem;
     private readonly DebugWindow _debugWindow;
+    private readonly ConfigWindow _configWindow;
 
     public DalamudInitializer(DalamudPluginInterface pluginInterface, IFramework framework,
         ICommandManager commandManager, QuestController questController, MovementController movementController,
-        GameUiController gameUiController, NavigationShortcutController navigationShortcutController, WindowSystem windowSystem, DebugWindow debugWindow)
+        GameUiController gameUiController, NavigationShortcutController navigationShortcutController,
+        WindowSystem windowSystem, DebugWindow debugWindow, ConfigWindow configWindow)
     {
         _pluginInterface = pluginInterface;
         _framework = framework;
         _navigationShortcutController = navigationShortcutController;
         _windowSystem = windowSystem;
         _debugWindow = debugWindow;
+        _configWindow = configWindow;
+
+        _windowSystem.AddWindow(debugWindow);
+        _windowSystem.AddWindow(configWindow);
 
         _pluginInterface.UiBuilder.Draw += _windowSystem.Draw;
         _pluginInterface.UiBuilder.OpenMainUi += _debugWindow.Toggle;
+        _pluginInterface.UiBuilder.OpenConfigUi += _configWindow.Toggle;
         _framework.Update += FrameworkUpdate;
         _commandManager.AddHandler("/qst", new CommandInfo(ProcessCommand)
         {
 
     private void ProcessCommand(string command, string arguments)
     {
-        _debugWindow.Toggle();
+        if (arguments is "c" or "config")
+            _configWindow.Toggle();
+        else
+            _debugWindow.Toggle();
     }
 
     public void Dispose()
         _framework.Update -= FrameworkUpdate;
         _pluginInterface.UiBuilder.OpenMainUi -= _debugWindow.Toggle;
         _pluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
+
+        _windowSystem.RemoveAllWindows();
     }
 }
 
             }
             .AsReadOnly();
 
+    /// <summary>
+    /// Airship landings are special as they're one-way only (except for Radz-at-Han, which is a normal aetheryte).
+    /// </summary>
+    public ReadOnlyDictionary<EAetheryteLocation, Vector3> AirshipLandingLocations { get; } =
+        new Dictionary<EAetheryteLocation, Vector3>
+        {
+            { EAetheryteLocation.LimsaAirship, new(-19.44352f, 91.99999f, -9.892939f) },
+            { EAetheryteLocation.GridaniaAirship, new(24.86354f, -19.000002f, 96f) },
+            { EAetheryteLocation.UldahAirship, new(-16.954851f, 82.999985f, -9.421141f) },
+            { EAetheryteLocation.KuganeAirship, new(-55.72525f, 79.10602f, 46.23109f) },
+        }.AsReadOnly();
+
     public ReadOnlyDictionary<EAetheryteLocation, string> AethernetNames { get; }
     public ReadOnlyDictionary<EAetheryteLocation, ushort> TerritoryIds { get; }
     public IReadOnlyList<ushort> TownTerritoryIds { get; set; }
         return (fromPosition - toPosition).Length();
     }
 
+    public float CalculateAirshipLandingDistance(Vector3 fromPosition, ushort fromTerritoryType, EAetheryteLocation to)
+    {
+        if (!TerritoryIds.TryGetValue(to, out ushort toTerritoryType) || fromTerritoryType != toTerritoryType)
+            return float.MaxValue;
+
+        if (!AirshipLandingLocations.TryGetValue(to, out Vector3 toPosition))
+            return float.MaxValue;
+
+        return (fromPosition - toPosition).Length();
+    }
+
     public bool IsCityAetheryte(EAetheryteLocation aetheryte)
     {
         var territoryId = TerritoryIds[aetheryte];
         return TownTerritoryIds.Contains(territoryId);
     }
+
+    public bool IsAirshipLanding(EAetheryteLocation aetheryte) => AirshipLandingLocations.ContainsKey(aetheryte);
 }
 
 using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib.GameUI;
 using Lumina.Excel.CustomSheets;
-using Lumina.Excel.GeneratedSheets;
+using Lumina.Excel.GeneratedSheets2;
 using Microsoft.Extensions.Logging;
 using Questionable.Controller;
 using Questionable.Model.V1;
 using BattleChara = FFXIVClientStructs.FFXIV.Client.Game.Character.BattleChara;
+using ContentFinderCondition = Lumina.Excel.GeneratedSheets.ContentFinderCondition;
+using ContentTalk = Lumina.Excel.GeneratedSheets.ContentTalk;
+using Emote = Lumina.Excel.GeneratedSheets.Emote;
 using GameObject = Dalamud.Game.ClientState.Objects.Types.GameObject;
 using Quest = Questionable.Model.Quest;
+using TerritoryType = Lumina.Excel.GeneratedSheets.TerritoryType;
 
 namespace Questionable;
 
     private readonly IClientState _clientState;
     private readonly QuestRegistry _questRegistry;
     private readonly IGameGui _gameGui;
+    private readonly Configuration _configuration;
     private readonly ILogger<GameFunctions> _logger;
 
     public GameFunctions(IDataManager dataManager, IObjectTable objectTable, ISigScanner sigScanner,
         ITargetManager targetManager, ICondition condition, IClientState clientState, QuestRegistry questRegistry,
-        IGameGui gameGui, ILogger<GameFunctions> logger)
+        IGameGui gameGui, Configuration configuration, ILogger<GameFunctions> logger)
     {
         _dataManager = dataManager;
         _objectTable = objectTable;
         _clientState = clientState;
         _questRegistry = questRegistry;
         _gameGui = gameGui;
+        _configuration = configuration;
         _logger = logger;
         _processChatBox =
             Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(sigScanner.ScanText(Signatures.SendChat));
         return false;
     }
 
-    public void UseItem(uint itemId)
+    public bool UseItem(uint itemId)
     {
-        AgentInventoryContext.Instance()->UseItem(itemId);
+        return AgentInventoryContext.Instance()->UseItem(itemId) == 0;
     }
 
-    public void UseItem(uint dataId, uint itemId)
+    public bool UseItem(uint dataId, uint itemId)
     {
         GameObject? gameObject = FindObjectByDataId(dataId);
         if (gameObject != null)
         {
             _targetManager.Target = gameObject;
-            AgentInventoryContext.Instance()->UseItem(itemId);
+            return AgentInventoryContext.Instance()->UseItem(itemId) == 0;
         }
+
+        return false;
     }
 
-    public void UseItemOnGround(uint dataId, uint itemId)
+    public bool UseItemOnGround(uint dataId, uint itemId)
     {
         GameObject? gameObject = FindObjectByDataId(dataId);
         if (gameObject != null)
         {
             var position = (FFXIVClientStructs.FFXIV.Common.Math.Vector3)gameObject.Position;
-            ActionManager.Instance()->UseActionLocation(ActionType.KeyItem, itemId, location: &position);
+            return ActionManager.Instance()->UseActionLocation(ActionType.KeyItem, itemId, location: &position);
         }
+
+        return false;
     }
 
     public void UseEmote(uint dataId, EEmote emote)
         return gameObject != null && (gameObject.Position - position).Length() < 0.05f;
     }
 
-    public bool HasStatusPreventingSprintOrMount()
+    public bool HasStatusPreventingSprintOrMount(bool skipConfigCheck = false)
     {
+        if (!skipConfigCheck && _configuration.Advanced.NeverFly)
+            return true;
+
         if (_condition[ConditionFlag.Swimming] && !IsFlyingUnlockedInCurrentZone())
             return true;
 
             return true;
 
         var playerState = PlayerState.Instance();
-        if (playerState != null && playerState->IsMountUnlocked(71))
+        if (playerState != null && _configuration.General.MountId != 0 &&
+            playerState->IsMountUnlocked(_configuration.General.MountId))
         {
-            if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, 71) == 0)
+            if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, _configuration.General.MountId) == 0)
             {
-                if (ActionManager.Instance()->UseAction(ActionType.Mount, 71))
+                if (ActionManager.Instance()->UseAction(ActionType.Mount, _configuration.General.MountId))
                 {
-                    _logger.LogInformation("Using SDS Fenrir as mount");
+                    _logger.LogInformation("Using preferred mount");
                     return true;
                 }
 
         return excelSheet.FirstOrDefault(x => x.Key == key)?.Value?.ToDalamudString().ToString();
     }
 
-    public string? GetContentTalk(uint rowId)
+    public string? GetDialogueTextByRowId(string? excelSheet, uint rowId)
     {
-        var questRow = _dataManager.GetExcelSheet<ContentTalk>()!.GetRow(rowId);
-        return questRow?.Text?.ToString();
+        if (excelSheet == "GimmickYesNo")
+        {
+            var questRow = _dataManager.GetExcelSheet<GimmickYesNo>()!.GetRow(rowId);
+            return questRow?.Unknown0?.ToString();
+        }
+        else if (excelSheet is "ContentTalk" or null)
+        {
+            var questRow = _dataManager.GetExcelSheet<ContentTalk>()!.GetRow(rowId);
+            return questRow?.Text?.ToString();
+        }
+        else
+            throw new ArgumentOutOfRangeException(nameof(excelSheet), $"Unsupported excel sheet {excelSheet}");
     }
 
     public bool IsOccupied()
 
 {
     public required ushort QuestId { get; init; }
     public required string Name { get; set; }
+    public ushort Level { get; set; }
     public required QuestData Data { get; init; }
 
     public QuestSequence? FindSequence(byte currentSequence)
 
     {
         { EDialogChoiceType.YesNo, "YesNo" },
         { EDialogChoiceType.List, "List" },
-        { EDialogChoiceType.ContentTalkYesNo, "ContentTalkYesNo" },
-        { EDialogChoiceType.ContentTalkList, "ContentTalkList" },
     };
 }
 
--- /dev/null
+using System;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace Questionable.Model.V1.Converter;
+
+internal sealed class ExcelRefConverter : JsonConverter<ExcelRef>
+{
+    public override ExcelRef? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+    {
+        if (reader.TokenType == JsonTokenType.String)
+            return new ExcelRef(reader.GetString()!);
+        else if (reader.TokenType == JsonTokenType.Number)
+            return new ExcelRef(reader.GetUInt32());
+        else
+            return null;
+    }
+
+    public override void Write(Utf8JsonWriter writer, ExcelRef? value, JsonSerializerOptions options)
+    {
+        if (value == null)
+            writer.WriteNullValue();
+        else if (value.Type == ExcelRef.EType.Key)
+            writer.WriteStringValue(value.AsKey());
+        else if (value.Type == ExcelRef.EType.RowId)
+            writer.WriteNumberValue(value.AsRowId());
+        else
+            throw new JsonException();
+    }
+}
 
     [JsonConverter(typeof(DialogueChoiceTypeConverter))]
     public EDialogChoiceType Type { get; set; }
     public string? ExcelSheet { get; set; }
-    public string? Prompt { get; set; }
+
+    [JsonConverter(typeof(ExcelRefConverter))]
+    public ExcelRef? Prompt { get; set; }
+
     public bool Yes { get; set; } = true;
-    public string? Answer { get; set; }
+
+    [JsonConverter(typeof(ExcelRefConverter))]
+    public ExcelRef? Answer { get; set; }
+
+    /// <summary>
+    /// If set, only applies when focusing the given target id.
+    /// </summary>
+    public uint? DataId { get; set; }
 }
 
     None,
     YesNo,
     List,
-    ContentTalkYesNo,
-    ContentTalkList,
 }
 
--- /dev/null
+using System;
+
+namespace Questionable.Model.V1;
+
+public class ExcelRef
+{
+    private readonly string? _stringValue;
+    private readonly uint? _rowIdValue;
+
+    public ExcelRef(string value)
+    {
+        _stringValue = value;
+        _rowIdValue = null;
+        Type = EType.Key;
+    }
+
+    public ExcelRef(uint value)
+    {
+        _stringValue = null;
+        _rowIdValue = value;
+        Type = EType.RowId;
+    }
+
+    public EType Type { get; }
+
+    public string AsKey()
+    {
+        if (Type != EType.Key)
+            throw new InvalidOperationException();
+
+        return _stringValue!;
+    }
+
+    public uint AsRowId()
+    {
+        if (Type != EType.RowId)
+            throw new InvalidOperationException();
+
+        return _rowIdValue!.Value;
+    }
+
+    public enum EType
+    {
+        None,
+        Key,
+        RowId,
+    }
+}
 
         serviceCollection.AddSingleton<NavigationShortcutController>();
 
         serviceCollection.AddSingleton<DebugWindow>();
+        serviceCollection.AddSingleton<ConfigWindow>();
         serviceCollection.AddSingleton<DalamudInitializer>();
 
         _serviceProvider = serviceCollection.BuildServiceProvider();
 
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Dalamud.Interface.Colors;
+using Dalamud.Plugin;
+using Dalamud.Plugin.Services;
+using ImGuiNET;
+using LLib.ImGui;
+using Lumina.Excel.GeneratedSheets;
+
+namespace Questionable.Windows;
+
+internal sealed class ConfigWindow : LWindow, IPersistableWindowConfig
+{
+    private readonly DalamudPluginInterface _pluginInterface;
+    private readonly Configuration _configuration;
+
+    private readonly uint[] _mountIds;
+    private readonly string[] _mountNames;
+
+    [SuppressMessage("Performance", "CA1861", Justification = "One time initialization")]
+    public ConfigWindow(DalamudPluginInterface pluginInterface, Configuration configuration, IDataManager dataManager)
+        : base("Config - Questionable###QuestionableConfig", ImGuiWindowFlags.AlwaysAutoResize)
+    {
+        _pluginInterface = pluginInterface;
+        _configuration = configuration;
+
+        var mounts = dataManager.GetExcelSheet<Mount>()!
+            .Where(x => x is { RowId: > 0, Icon: > 0 })
+            .Select(x => (MountId: x.RowId, Name: x.Singular.ToString()))
+            .Where(x => !string.IsNullOrEmpty(x.Name))
+            .OrderBy(x => x.Name)
+            .ToList();
+        _mountIds = new uint[] { 0 }.Concat(mounts.Select(x => x.MountId)).ToArray();
+        _mountNames = new[] { "Mount Roulette" }.Concat(mounts.Select(x => x.Name)).ToArray();
+    }
+
+    public WindowConfig WindowConfig => _configuration.ConfigWindowConfig;
+
+    public override void Draw()
+    {
+        if (ImGui.BeginTabBar("QuestionableConfigTabs"))
+        {
+            if (ImGui.BeginTabItem("General"))
+            {
+                int selectedMount = Array.FindIndex(_mountIds, x => x == _configuration.General.MountId);
+                if (selectedMount == -1)
+                {
+                    selectedMount = 0;
+                    _configuration.General.MountId = _mountIds[selectedMount];
+                    Save();
+                }
+
+                if (ImGui.Combo("Preferred Mount", ref selectedMount, _mountNames, _mountNames.Length))
+                {
+                    _configuration.General.MountId = _mountIds[selectedMount];
+                    Save();
+                }
+
+                ImGui.EndTabItem();
+            }
+
+            if (ImGui.BeginTabItem("Advanced"))
+            {
+                ImGui.TextColored(ImGuiColors.DalamudRed,
+                    "Enabling any option here may cause unexpected behavior. Use at your own risk.");
+
+                ImGui.Separator();
+
+                bool neverFly = _configuration.Advanced.NeverFly;
+                if (ImGui.Checkbox("Disable flying (even if unlocked for the zone)", ref neverFly))
+                {
+                    _configuration.Advanced.NeverFly = neverFly;
+                    Save();
+                }
+
+                ImGui.EndTabItem();
+            }
+
+            ImGui.EndTabBar();
+        }
+    }
+
+    private void Save() => _pluginInterface.SavePluginConfig(_configuration);
+
+    public void SaveWindowConfig() => Save();
+}
 
 
 namespace Questionable.Windows;
 
-internal sealed class DebugWindow : LWindow, IPersistableWindowConfig, IDisposable
+internal sealed class DebugWindow : LWindow, IPersistableWindowConfig
 {
     private readonly DalamudPluginInterface _pluginInterface;
-    private readonly WindowSystem _windowSystem;
     private readonly MovementController _movementController;
     private readonly QuestController _questController;
     private readonly GameFunctions _gameFunctions;
     private readonly Configuration _configuration;
     private readonly ILogger<DebugWindow> _logger;
 
-    public DebugWindow(DalamudPluginInterface pluginInterface, WindowSystem windowSystem,
-        MovementController movementController, QuestController questController, GameFunctions gameFunctions,
-        IClientState clientState, IFramework framework, ITargetManager targetManager, GameUiController gameUiController,
-        Configuration configuration, ILogger<DebugWindow> logger)
+    public DebugWindow(DalamudPluginInterface pluginInterface,
+        MovementController movementController,
+        QuestController questController,
+        GameFunctions gameFunctions,
+        IClientState clientState,
+        IFramework framework,
+        ITargetManager targetManager,
+        GameUiController gameUiController,
+        Configuration configuration,
+        ILogger<DebugWindow> logger)
         : base("Questionable", ImGuiWindowFlags.AlwaysAutoResize)
     {
         _pluginInterface = pluginInterface;
-        _windowSystem = windowSystem;
         _movementController = movementController;
         _questController = questController;
         _gameFunctions = gameFunctions;
             MinimumSize = new Vector2(200, 30),
             MaximumSize = default
         };
-
-        _windowSystem.AddWindow(this);
     }
 
     public WindowConfig WindowConfig => _configuration.DebugWindowConfig;
             ImGui.Text(_questController.ToStatString());
             //ImGui.EndDisabled();
 
+            ImGui.BeginDisabled(_questController.IsRunning);
             if (ImGuiComponents.IconButton(FontAwesomeIcon.Play))
             {
                 _questController.ExecuteNextStep(true);
                 _questController.ExecuteNextStep(false);
             }
 
+            ImGui.EndDisabled();
             ImGui.SameLine();
 
             if (ImGuiComponents.IconButton(FontAwesomeIcon.Stop))
                 .FindSequence(currentQuest.Sequence)
                 ?.FindStep(currentQuest.Step);
             bool colored = currentStep != null && currentStep.InteractionType == EInteractionType.Instruction
-                && _questController.HasCurrentTaskMatching<WaitAtEnd.WaitNextStepOrSequence>();
+                                               && _questController
+                                                   .HasCurrentTaskMatching<WaitAtEnd.WaitNextStepOrSequence>();
 
             if (colored)
                 ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.HealerGreen);
                 _questController.Stop("Manual");
                 _questController.IncreaseStepCount();
             }
+
             if (colored)
                 ImGui.PopStyleColor();
+
+            bool autoAcceptNextQuest = _configuration.General.AutoAcceptNextQuest;
+            if (ImGui.Checkbox("Automatically accept next quest", ref autoAcceptNextQuest))
+            {
+                _configuration.General.AutoAcceptNextQuest = autoAcceptNextQuest;
+                _pluginInterface.SavePluginConfig(_configuration);
+            }
         }
         else
             ImGui.Text("No active quest");
         }
         else
         {
-            if (ImGui.Button($"Copy"))
+            ImGui.Button($"Copy");
+            if (ImGui.IsItemClicked(ImGuiMouseButton.Left))
             {
                 ImGui.SetClipboardText($$"""
                                          "Position": {
                                          "InteractionType": ""
                                          """);
             }
+            else if (ImGui.IsItemClicked(ImGuiMouseButton.Right))
+            {
+                Vector3 position = _clientState.LocalPlayer!.Position;
+                ImGui.SetClipboardText(string.Create(CultureInfo.InvariantCulture,
+                    $"new({position.X}f, {position.Y}f, {position.Z}f)"));
+            }
         }
     }
 
             ImGui.EndDisabled();
         }
     }
-
-    public void Dispose()
-    {
-        _windowSystem.RemoveWindow(this);
-    }
 }