diff --git a/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/A6_Vanu Vanu (all).json b/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/A6_Vanu Vanu (all).json
new file mode 100644
index 00000000..036c2982
--- /dev/null
+++ b/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/A6_Vanu Vanu (all).json	
@@ -0,0 +1,29 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "DataId": 1016089,
+          "Position": {
+            "X": -799.46594,
+            "Y": -133.2695,
+            "Z": -404.1352
+          },
+          "StopDistance": 3,
+          "TerritoryId": 401,
+          "InteractionType": "WalkTo",
+          "AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
+          "Fly": true,
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/Dailies/2172_Pussyfooting About.json b/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/Dailies/2172_Pussyfooting About.json
index fab39d1f..e12ff08c 100644
--- a/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/Dailies/2172_Pussyfooting About.json	
+++ b/QuestPaths/3.x - Heavensward/Allied Societies/Vanu Vanu/Dailies/2172_Pussyfooting About.json	
@@ -58,6 +58,17 @@
     {
       "Sequence": 2,
       "Steps": [
+        {
+          "Position": {
+            "X": -799.46594,
+            "Y": -133.2695,
+            "Z": -404.1352
+          },
+          "TerritoryId": 401,
+          "InteractionType": "WalkTo",
+          "AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
+          "Fly": true
+        },
         {
           "DataId": 1016089,
           "Position": {
@@ -67,8 +78,7 @@
           },
           "TerritoryId": 401,
           "InteractionType": "Interact",
-          "AetheryteShortcut": "The Sea of Clouds - Ok' Zundu",
-          "Fly": true
+          "Mount": false
         }
       ]
     },
diff --git a/QuestPaths/3.x - Heavensward/Allied Societies/Vath/A7_Vath.json b/QuestPaths/3.x - Heavensward/Allied Societies/Vath/A7_Vath.json
new file mode 100644
index 00000000..6ffe879d
--- /dev/null
+++ b/QuestPaths/3.x - Heavensward/Allied Societies/Vath/A7_Vath.json	
@@ -0,0 +1,27 @@
+{
+  "$schema": "https://git.carvel.li/liza/Questionable/raw/branch/master/QuestPaths/quest-v1.json",
+  "Author": "liza",
+  "QuestSequence": [
+    {
+      "Sequence": 0,
+      "Steps": [
+        {
+          "Position": {
+            "X": 58.39701,
+            "Y": -48.000008,
+            "Z": -172.36507
+          },
+          "TerritoryId": 398,
+          "InteractionType": "WalkTo",
+          "AetheryteShortcut": "The Dravanian Forelands - Anyx Trine",
+          "Fly": true,
+          "SkipConditions": {
+            "AetheryteShortcutIf": {
+              "InSameTerritory": true
+            }
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/Questionable.Model/Questing/ElementId.cs b/Questionable.Model/Questing/ElementId.cs
index 396c3524..a553ff0d 100644
--- a/Questionable.Model/Questing/ElementId.cs
+++ b/Questionable.Model/Questing/ElementId.cs
@@ -56,6 +56,19 @@ public abstract class ElementId : IComparable<ElementId>, IEquatable<ElementId>
             return new LeveId(ushort.Parse(value.Substring(1), CultureInfo.InvariantCulture));
         else if (value.StartsWith("S"))
             return new SatisfactionSupplyNpcId(ushort.Parse(value.Substring(1), CultureInfo.InvariantCulture));
+        else if (value.StartsWith("A"))
+        {
+            value = value.Substring(1);
+            string[] parts = value.Split('x');
+            if (parts.Length == 2)
+            {
+                return new AlliedSocietyDailyId(
+                    byte.Parse(parts[0], CultureInfo.InvariantCulture),
+                    byte.Parse(parts[1], CultureInfo.InvariantCulture));
+            }
+            else
+                return new AlliedSocietyDailyId(byte.Parse(value, CultureInfo.InvariantCulture));
+        }
         else
             return new QuestId(ushort.Parse(value, CultureInfo.InvariantCulture));
     }
@@ -70,7 +83,8 @@ public abstract class ElementId : IComparable<ElementId>, IEquatable<ElementId>
         catch (Exception)
         {
             elementId = null;
-            return false;
+            //return false;
+            throw;
         }
     }
 }
@@ -98,3 +112,14 @@ public sealed class SatisfactionSupplyNpcId(ushort value) : ElementId(value)
         return "S" + Value.ToString(CultureInfo.InvariantCulture);
     }
 }
+
+public sealed class AlliedSocietyDailyId(byte alliedSociety, byte rank = 0) : ElementId((ushort)(alliedSociety * 10 + rank))
+{
+    public byte AlliedSociety { get; } = alliedSociety;
+    public byte Rank { get; } = rank;
+
+    public override string ToString()
+    {
+        return "A" + AlliedSociety + "x" + Rank;
+    }
+}
diff --git a/Questionable/Controller/CommandHandler.cs b/Questionable/Controller/CommandHandler.cs
index c6085a18..1c2bed2b 100644
--- a/Questionable/Controller/CommandHandler.cs
+++ b/Questionable/Controller/CommandHandler.cs
@@ -4,6 +4,7 @@ using Dalamud.Game.ClientState.Objects;
 using Dalamud.Game.Command;
 using Dalamud.Plugin.Services;
 using Lumina.Excel.Sheets;
+using Microsoft.Extensions.Logging;
 using Questionable.Functions;
 using Questionable.Model.Questing;
 using Questionable.Windows;
diff --git a/Questionable/Data/QuestData.cs b/Questionable/Data/QuestData.cs
index 5d7b7022..3cb2f295 100644
--- a/Questionable/Data/QuestData.cs
+++ b/Questionable/Data/QuestData.cs
@@ -68,6 +68,29 @@ internal sealed class QuestData
                 .Where(x => x.LevelLevemete.RowId != 0)
                 .Select(x => new LeveInfo(x)),
         ];
+
+        quests.AddRange(
+            dataManager.GetExcelSheet<BeastTribe>()
+                .Where(x => x.RowId > 0 && !x.Name.IsEmpty)
+                .SelectMany(x =>
+                {
+                    if (x.RowId < 5)
+                    {
+                        return ((IEnumerable<byte>)
+                            [
+                                0,
+                                ..quests.Where(y => y.AlliedSociety == (EAlliedSociety)x.RowId && y.IsRepeatable)
+                                    .Cast<QuestInfo>()
+                                    .Select(y => (byte)y.AlliedSocietyRank).Distinct()
+                            ])
+                            .Select(rank => new AlliedSocietyDailyInfo(x, rank));
+                    }
+                    else
+                    {
+                        return [new AlliedSocietyDailyInfo(x, 0)];
+                    }
+                }));
+
         _quests = quests.ToDictionary(x => x.QuestId, x => x);
 
         // workaround because the game doesn't require completion of the CT questline through normal means
diff --git a/Questionable/Functions/QuestFunctions.cs b/Questionable/Functions/QuestFunctions.cs
index bb206a1b..fc5d7935 100644
--- a/Questionable/Functions/QuestFunctions.cs
+++ b/Questionable/Functions/QuestFunctions.cs
@@ -14,7 +14,6 @@ using LLib.GameData;
 using LLib.GameUI;
 using Lumina.Excel.Sheets;
 using Questionable.Controller;
-using Questionable.Controller.Steps.Interactions;
 using Questionable.Data;
 using Questionable.Model;
 using Questionable.Model.Questing;
@@ -487,6 +486,8 @@ internal sealed unsafe class QuestFunctions
             return IsQuestAccepted(leveId);
         else if (elementId is SatisfactionSupplyNpcId)
             return false;
+        else if (elementId is AlliedSocietyDailyId)
+            return false;
         else
             throw new ArgumentOutOfRangeException(nameof(elementId));
     }
@@ -517,6 +518,8 @@ internal sealed unsafe class QuestFunctions
             return IsQuestComplete(leveId);
         else if (elementId is SatisfactionSupplyNpcId)
             return false;
+        else if (elementId is AlliedSocietyDailyId)
+            return false;
         else
             throw new ArgumentOutOfRangeException(nameof(elementId));
     }
@@ -540,6 +543,8 @@ internal sealed unsafe class QuestFunctions
             return IsQuestLocked(leveId);
         else if (elementId is SatisfactionSupplyNpcId satisfactionSupplyNpcId)
             return IsQuestLocked(satisfactionSupplyNpcId);
+        else if (elementId is AlliedSocietyDailyId alliedSocietyDailyId)
+            return IsQuestLocked(alliedSocietyDailyId);
         else
             throw new ArgumentOutOfRangeException(nameof(elementId));
     }
@@ -579,6 +584,13 @@ internal sealed unsafe class QuestFunctions
         return !HasCompletedPreviousQuests(questInfo, null);
     }
 
+    private bool IsQuestLocked(AlliedSocietyDailyId alliedSocietyDailyId)
+    {
+        PlayerState* playerState = PlayerState.Instance();
+        byte currentRank = playerState->GetBeastTribeRank(alliedSocietyDailyId.AlliedSociety);
+        return currentRank == 0 || currentRank < alliedSocietyDailyId.Rank;
+    }
+
     public bool IsDailyAlliedSocietyQuest(QuestId questId)
     {
         var questInfo = (QuestInfo)_questData.GetQuestInfo(questId);
diff --git a/Questionable/Model/AlliedSocietyDailyInfo.cs b/Questionable/Model/AlliedSocietyDailyInfo.cs
new file mode 100644
index 00000000..0f203609
--- /dev/null
+++ b/Questionable/Model/AlliedSocietyDailyInfo.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using LLib.GameData;
+using Lumina.Excel.Sheets;
+using Questionable.Data;
+using Questionable.Model.Questing;
+
+namespace Questionable.Model;
+
+internal sealed class AlliedSocietyDailyInfo : IQuestInfo
+{
+    public AlliedSocietyDailyInfo(BeastTribe beastTribe, byte rank)
+    {
+        QuestId = new AlliedSocietyDailyId((byte)beastTribe.RowId, rank);
+        Name = beastTribe.Name.ToString();
+        ClassJobs = (EAlliedSociety)beastTribe.RowId switch
+        {
+            EAlliedSociety.Amaljaa or EAlliedSociety.Sylphs or EAlliedSociety.Kobolds or EAlliedSociety.Sahagin or
+                EAlliedSociety.VanuVanu or EAlliedSociety.Vath or
+                EAlliedSociety.Kojin or EAlliedSociety.Ananta or
+                EAlliedSociety.Pixies or
+                EAlliedSociety.Arkasodara or
+                EAlliedSociety.Pelupelu =>
+                [
+                    ..ClassJobUtils.AsIndividualJobs(EExtendedClassJob.DoW),
+                    ..ClassJobUtils.AsIndividualJobs(EExtendedClassJob.DoM)
+                ],
+            EAlliedSociety.Ixal or EAlliedSociety.Moogles or EAlliedSociety.Dwarves or EAlliedSociety.Loporrits =>
+                ClassJobUtils.AsIndividualJobs(EExtendedClassJob.DoH).ToList(),
+
+            EAlliedSociety.Qitari or EAlliedSociety.Omicrons =>
+                ClassJobUtils.AsIndividualJobs(EExtendedClassJob.DoL).ToList(),
+
+            EAlliedSociety.Namazu =>
+            [
+                ..ClassJobUtils.AsIndividualJobs(EExtendedClassJob.DoH),
+                ..ClassJobUtils.AsIndividualJobs(EExtendedClassJob.DoL)
+            ],
+
+            _ => throw new ArgumentOutOfRangeException(nameof(beastTribe))
+        };
+        Expansion = (EExpansionVersion)beastTribe.Expansion.RowId;
+    }
+
+    public ElementId QuestId { get; }
+    public string Name { get; }
+    public uint IssuerDataId => 0;
+    public ImmutableList<PreviousQuestInfo> PreviousQuests { get; } = [];
+    public EQuestJoin PreviousQuestJoin => EQuestJoin.All;
+    public bool IsRepeatable => true;
+    public ushort Level => 1;
+    public EAlliedSociety AlliedSociety => EAlliedSociety.None;
+    public uint? JournalGenre => null;
+    public ushort SortKey => 0;
+    public bool IsMainScenarioQuest => false;
+    public IReadOnlyList<EClassJob> ClassJobs { get; }
+    public EExpansionVersion Expansion { get; }
+}
diff --git a/Questionable/Windows/PriorityWindow.cs b/Questionable/Windows/PriorityWindow.cs
index 08bd35e5..8b4d5202 100644
--- a/Questionable/Windows/PriorityWindow.cs
+++ b/Questionable/Windows/PriorityWindow.cs
@@ -106,7 +106,7 @@ internal sealed class PriorityWindow : LWindow
             if (!string.IsNullOrEmpty(_searchString))
             {
                 foundQuests = _questRegistry.AllQuests
-                    .Where(x => x.Id is not SatisfactionSupplyNpcId)
+                    .Where(x => x.Id is not SatisfactionSupplyNpcId and not AlliedSocietyDailyId)
                     .Where(x => x.Info.Name.Contains(_searchString, StringComparison.CurrentCultureIgnoreCase))
                     .Where(x => !_questFunctions.IsQuestUnobtainable(x.Id));
             }