--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using Dalamud.Game;
+using Dalamud.Game.ClientState.Objects;
+using Dalamud.Game.ClientState.Objects.Types;
+using Dalamud.Plugin.Services;
+using FFXIVClientStructs.FFXIV.Client.System.Framework;
+using FFXIVClientStructs.FFXIV.Client.System.Memory;
+using FFXIVClientStructs.FFXIV.Client.System.String;
+using Lumina.Excel.GeneratedSheets;
+using Microsoft.Extensions.Logging;
+using Questionable.Model.V1;
+
+namespace Questionable;
+
+internal sealed unsafe class ChatFunctions
+{
+    private delegate void ProcessChatBoxDelegate(IntPtr uiModule, IntPtr message, IntPtr unused, byte a4);
+
+    private readonly ReadOnlyDictionary<EEmote, string> _emoteCommands;
+
+    private readonly GameFunctions _gameFunctions;
+    private readonly ITargetManager _targetManager;
+    private readonly ILogger<ChatFunctions> _logger;
+    private readonly ProcessChatBoxDelegate _processChatBox;
+    private readonly delegate* unmanaged<Utf8String*, int, IntPtr, void> _sanitiseString;
+
+    public ChatFunctions(ISigScanner sigScanner, IDataManager dataManager, GameFunctions gameFunctions,
+        ITargetManager targetManager, ILogger<ChatFunctions> logger)
+    {
+        _gameFunctions = gameFunctions;
+        _targetManager = targetManager;
+        _logger = logger;
+        _processChatBox =
+            Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(sigScanner.ScanText(Signatures.SendChat));
+        _sanitiseString =
+            (delegate* unmanaged<Utf8String*, int, IntPtr, void>)sigScanner.ScanText(Signatures.SanitiseString);
+
+        _emoteCommands = dataManager.GetExcelSheet<Emote>()!
+            .Where(x => x.RowId > 0)
+            .Where(x => x.TextCommand != null && x.TextCommand.Value != null)
+            .Select(x => (x.RowId, Command: x.TextCommand.Value!.Command?.ToString()))
+            .Where(x => x.Command != null && x.Command.StartsWith('/'))
+            .ToDictionary(x => (EEmote)x.RowId, x => x.Command!)
+            .AsReadOnly();
+    }
+
+    /// <summary>
+    /// <para>
+    /// Send a given message to the chat box. <b>This can send chat to the server.</b>
+    /// </para>
+    /// <para>
+    /// <b>This method is unsafe.</b> This method does no checking on your input and
+    /// may send content to the server that the normal client could not. You must
+    /// verify what you're sending and handle content and length to properly use
+    /// this.
+    /// </para>
+    /// </summary>
+    /// <param name="message">Message to send</param>
+    /// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
+    private void SendMessageUnsafe(byte[] message)
+    {
+        var uiModule = (IntPtr)Framework.Instance()->GetUiModule();
+
+        using var payload = new ChatPayload(message);
+        var mem1 = Marshal.AllocHGlobal(400);
+        Marshal.StructureToPtr(payload, mem1, false);
+
+        _processChatBox(uiModule, mem1, IntPtr.Zero, 0);
+
+        Marshal.FreeHGlobal(mem1);
+    }
+
+    /// <summary>
+    /// <para>
+    /// Send a given message to the chat box. <b>This can send chat to the server.</b>
+    /// </para>
+    /// <para>
+    /// This method is slightly less unsafe than <see cref="SendMessageUnsafe"/>. It
+    /// will throw exceptions for certain inputs that the client can't normally send,
+    /// but it is still possible to make mistakes. Use with caution.
+    /// </para>
+    /// </summary>
+    /// <param name="message">message to send</param>
+    /// <exception cref="ArgumentException">If <paramref name="message"/> is empty, longer than 500 bytes in UTF-8, or contains invalid characters.</exception>
+    /// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
+    private void SendMessage(string message)
+    {
+        _logger.LogDebug("Attempting to send chat message '{Message}'", message);
+        var bytes = Encoding.UTF8.GetBytes(message);
+        if (bytes.Length == 0)
+            throw new ArgumentException("message is empty", nameof(message));
+
+        if (bytes.Length > 500)
+            throw new ArgumentException("message is longer than 500 bytes", nameof(message));
+
+        if (message.Length != SanitiseText(message).Length)
+            throw new ArgumentException("message contained invalid characters", nameof(message));
+
+        SendMessageUnsafe(bytes);
+    }
+
+    /// <summary>
+    /// <para>
+    /// Sanitises a string by removing any invalid input.
+    /// </para>
+    /// <para>
+    /// The result of this method is safe to use with
+    /// <see cref="SendMessage"/>, provided that it is not empty or too
+    /// long.
+    /// </para>
+    /// </summary>
+    /// <param name="text">text to sanitise</param>
+    /// <returns>sanitised text</returns>
+    /// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
+    private string SanitiseText(string text)
+    {
+        var uText = Utf8String.FromString(text);
+
+        _sanitiseString(uText, 0x27F, IntPtr.Zero);
+        var sanitised = uText->ToString();
+
+        uText->Dtor();
+        IMemorySpace.Free(uText);
+
+        return sanitised;
+    }
+
+    public void ExecuteCommand(string command)
+    {
+        if (!command.StartsWith('/'))
+            return;
+
+        SendMessage(command);
+    }
+
+    public void UseEmote(uint dataId, EEmote emote)
+    {
+        GameObject? gameObject = _gameFunctions.FindObjectByDataId(dataId);
+        if (gameObject != null)
+        {
+            _targetManager.Target = gameObject;
+            ExecuteCommand($"{_emoteCommands[emote]} motion");
+        }
+    }
+
+    public void UseEmote(EEmote emote)
+    {
+        ExecuteCommand($"{_emoteCommands[emote]} motion");
+    }
+
+    private static class Signatures
+    {
+        internal const string SendChat = "48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9";
+        internal const string SanitiseString = "E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8D";
+    }
+
+    [StructLayout(LayoutKind.Explicit)]
+    [SuppressMessage("ReSharper", "PrivateFieldCanBeConvertedToLocalVariable")]
+    private readonly struct ChatPayload : IDisposable
+    {
+        [FieldOffset(0)] private readonly IntPtr textPtr;
+
+        [FieldOffset(16)] private readonly ulong textLen;
+
+        [FieldOffset(8)] private readonly ulong unk1;
+
+        [FieldOffset(24)] private readonly ulong unk2;
+
+        internal ChatPayload(byte[] stringBytes)
+        {
+            textPtr = Marshal.AllocHGlobal(stringBytes.Length + 30);
+            Marshal.Copy(stringBytes, 0, textPtr, stringBytes.Length);
+            Marshal.WriteByte(textPtr + stringBytes.Length, 0);
+
+            textLen = (ulong)(stringBytes.Length + 1);
+
+            unk1 = 64;
+            unk2 = 0;
+        }
+
+        public void Dispose()
+        {
+            Marshal.FreeHGlobal(textPtr);
+        }
+    }
+}
 
     private readonly NavmeshIpc _navmeshIpc;
     private readonly IClientState _clientState;
     private readonly GameFunctions _gameFunctions;
+    private readonly ChatFunctions _chatFunctions;
     private readonly ICondition _condition;
     private readonly ILogger<MovementController> _logger;
     private CancellationTokenSource? _cancellationTokenSource;
     private Task<List<Vector3>>? _pathfindTask;
 
     public MovementController(NavmeshIpc navmeshIpc, IClientState clientState, GameFunctions gameFunctions,
-        ICondition condition, ILogger<MovementController> logger)
+        ChatFunctions chatFunctions, ICondition condition, ILogger<MovementController> logger)
     {
         _navmeshIpc = navmeshIpc;
         _clientState = clientState;
         _gameFunctions = gameFunctions;
+        _chatFunctions = chatFunctions;
         _condition = condition;
         _logger = logger;
     }
         if (InputManager.IsAutoRunning())
         {
             _logger.LogInformation("Turning off auto-move");
-            _gameFunctions.ExecuteCommand("/automove off");
+            _chatFunctions.ExecuteCommand("/automove off");
         }
 
         Destination = new DestinationData(dataId, to, stopDistance ?? (DefaultStopDistance - 0.2f), fly, sprint,
         if (InputManager.IsAutoRunning())
         {
             _logger.LogInformation("Turning off auto-move [stop]");
-            _gameFunctions.ExecuteCommand("/automove off");
+            _chatFunctions.ExecuteCommand("/automove off");
         }
     }
 
 
 
     private readonly Dictionary<ushort, Quest> _quests = new();
 
-    public QuestRegistry(DalamudPluginInterface pluginInterface, IDataManager dataManager, ILogger<QuestRegistry> logger)
+    public QuestRegistry(DalamudPluginInterface pluginInterface, IDataManager dataManager,
+        ILogger<QuestRegistry> logger)
     {
         _pluginInterface = pluginInterface;
         _dataManager = dataManager;
 
 
 internal static class WaitAtEnd
 {
-    internal sealed class Factory(IServiceProvider serviceProvider, IClientState clientState, ICondition condition) : ITaskFactory
+    internal sealed class Factory(IServiceProvider serviceProvider, IClientState clientState, ICondition condition)
+        : ITaskFactory
     {
         public IEnumerable<ITask> CreateAllTasks(Quest quest, QuestSequence sequence, QuestStep step)
         {
             switch (step.InteractionType)
             {
                 case EInteractionType.Combat:
-                    var notInCombat = new WaitConditionTask(() => !condition[ConditionFlag.InCombat], "Wait(not in combat)");
-                    return [
+                    var notInCombat =
+                        new WaitConditionTask(() => !condition[ConditionFlag.InCombat], "Wait(not in combat)");
+                    return
+                    [
                         serviceProvider.GetRequiredService<WaitDelay>(),
                         notInCombat,
                         serviceProvider.GetRequiredService<WaitDelay>(),
                     if (step.TerritoryId != step.TargetTerritoryId)
                     {
                         // interaction moves to a different territory
-                        waitInteraction = new WaitConditionTask(() => clientState.TerritoryType == step.TargetTerritoryId,
+                        waitInteraction = new WaitConditionTask(
+                            () => clientState.TerritoryType == step.TargetTerritoryId,
                             $"Wait(tp to territory: {step.TargetTerritoryId})");
                     }
                     else
 
                 return false;
             }
 
-            logger.LogInformation("Want to use mount if away from destination ({Distance} yalms), trying (in territory {Id})...", distance, _territoryId);
+            logger.LogInformation(
+                "Want to use mount if away from destination ({Distance} yalms), trying (in territory {Id})...",
+                distance, _territoryId);
         }
         else
             logger.LogInformation("Want to use mount, trying (in territory {Id})...", _territoryId);
 
         if (condition[ConditionFlag.InFlight])
         {
             gameFunctions.Unmount();
+            _continueAt = DateTime.Now.AddSeconds(1);
             return true;
         }
 
             else
                 _unmountTriggered = gameFunctions.Unmount();
 
-            _continueAt = DateTime.Now.AddSeconds(0.5);
+            _continueAt = DateTime.Now.AddSeconds(1);
             return ETaskResult.StillRunning;
         }
 
 
                 return true;
             }
 
-            logger.LogInformation("Already attuned to aether current {AetherCurrentId} / {DataId}", AetherCurrentId, DataId);
+            logger.LogInformation("Already attuned to aether current {AetherCurrentId} / {DataId}", AetherCurrentId,
+                DataId);
             return false;
         }
 
 
             => throw new InvalidOperationException();
     }
 
-    internal sealed class UseOnObject(GameFunctions gameFunctions) : AbstractDelayedTask
+    internal sealed class UseOnObject(ChatFunctions chatFunctions) : AbstractDelayedTask
     {
         public EEmote Emote { get; set; }
         public uint DataId { get; set; }
 
         protected override bool StartInternal()
         {
-            gameFunctions.UseEmote(DataId, Emote);
+            chatFunctions.UseEmote(DataId, Emote);
             return true;
         }
 
         public override string ToString() => $"Emote({Emote} on {DataId})";
     }
 
-    internal sealed class Use(GameFunctions gameFunctions) : AbstractDelayedTask
+    internal sealed class Use(ChatFunctions chatFunctions) : AbstractDelayedTask
     {
         public EEmote Emote { get; set; }
 
 
         protected override bool StartInternal()
         {
-            gameFunctions.UseEmote(Emote);
+            chatFunctions.UseEmote(Emote);
             return true;
         }
 
 
             {
                 _needsUnmount = true;
                 gameFunctions.Unmount();
-                _continueAt = DateTime.Now.AddSeconds(0.5);
+                _continueAt = DateTime.Now.AddSeconds(1);
                 return true;
             }
 
                 if (condition[ConditionFlag.Mounted])
                 {
                     gameFunctions.Unmount();
-                    _continueAt = DateTime.Now.AddSeconds(0.5);
+                    _continueAt = DateTime.Now.AddSeconds(1);
                     return ETaskResult.StillRunning;
                 }
                 else
 
 
             ArgumentNullException.ThrowIfNull(step.ChatMessage);
 
-            string? excelString = gameFunctions.GetDialogueText(quest, step.ChatMessage.ExcelSheet, step.ChatMessage.Key);
+            string? excelString =
+                gameFunctions.GetDialogueText(quest, step.ChatMessage.ExcelSheet, step.ChatMessage.Key);
             ArgumentNullException.ThrowIfNull(excelString);
 
             var unmount = serviceProvider.GetRequiredService<UnmountTask>();
             => throw new InvalidOperationException();
     }
 
-    internal sealed class UseChat(GameFunctions gameFunctions) : AbstractDelayedTask
+    internal sealed class UseChat(ChatFunctions chatFunctions) : AbstractDelayedTask
     {
         public string ChatMessage { get; set; } = null!;
 
 
         protected override bool StartInternal()
         {
-            gameFunctions.ExecuteCommand($"/say {ChatMessage}");
+            chatFunctions.ExecuteCommand($"/say {ChatMessage}");
             return true;
         }
 
 
                 if (itemCount == _itemCount)
                 {
                     // TODO Better handling for game-provided errors, i.e. reacting to the 'Could not use' messages. UseItem() is successful in this case (and returns 0)
-                    logger.LogInformation("Attempted to use vesper bay aetheryte ticket, but it didn't consume an item - reattempting next frame");
+                    logger.LogInformation(
+                        "Attempted to use vesper bay aetheryte ticket, but it didn't consume an item - reattempting next frame");
                     _usedItem = false;
                     return ETaskResult.StillRunning;
                 }
 
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
-using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Numerics;
-using System.Runtime.InteropServices;
-using System.Text;
 using Dalamud.Game;
 using Dalamud.Game.ClientState.Conditions;
 using Dalamud.Game.ClientState.Objects;
 using FFXIVClientStructs.FFXIV.Client.Game.Control;
 using FFXIVClientStructs.FFXIV.Client.Game.Object;
 using FFXIVClientStructs.FFXIV.Client.Game.UI;
-using FFXIVClientStructs.FFXIV.Client.System.Framework;
-using FFXIVClientStructs.FFXIV.Client.System.Memory;
-using FFXIVClientStructs.FFXIV.Client.System.String;
 using FFXIVClientStructs.FFXIV.Client.UI.Agent;
 using FFXIVClientStructs.FFXIV.Component.GUI;
 using LLib.GameUI;
 
 internal sealed unsafe class GameFunctions
 {
-    private static class Signatures
-    {
-        internal const string SendChat = "48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9";
-        internal const string SanitiseString = "E8 ?? ?? ?? ?? EB 0A 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8D";
-    }
-
-    private delegate void ProcessChatBoxDelegate(IntPtr uiModule, IntPtr message, IntPtr unused, byte a4);
-
-    private readonly ProcessChatBoxDelegate _processChatBox;
-    private readonly delegate* unmanaged<Utf8String*, int, IntPtr, void> _sanitiseString;
     private readonly ReadOnlyDictionary<ushort, byte> _territoryToAetherCurrentCompFlgSet;
-    private readonly ReadOnlyDictionary<EEmote, string> _emoteCommands;
     private readonly ReadOnlyDictionary<uint, ushort> _contentFinderConditionToContentId;
 
     private readonly IDataManager _dataManager;
     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, Configuration configuration, ILogger<GameFunctions> logger)
+    public GameFunctions(IDataManager dataManager,
+        IObjectTable objectTable,
+        ITargetManager targetManager,
+        ICondition condition,
+        IClientState clientState,
+        QuestRegistry questRegistry,
+        IGameGui gameGui,
+        Configuration configuration,
+        ILogger<GameFunctions> logger)
     {
         _dataManager = dataManager;
         _objectTable = objectTable;
         _gameGui = gameGui;
         _configuration = configuration;
         _logger = logger;
-        _processChatBox =
-            Marshal.GetDelegateForFunctionPointer<ProcessChatBoxDelegate>(sigScanner.ScanText(Signatures.SendChat));
-        _sanitiseString =
-            (delegate* unmanaged<Utf8String*, int, IntPtr, void>)sigScanner.ScanText(Signatures.SanitiseString);
 
         _territoryToAetherCurrentCompFlgSet = dataManager.GetExcelSheet<TerritoryType>()!
             .Where(x => x.RowId > 0)
             .Where(x => x.Unknown32 > 0)
             .ToDictionary(x => (ushort)x.RowId, x => x.Unknown32)
             .AsReadOnly();
-        _emoteCommands = dataManager.GetExcelSheet<Emote>()!
-            .Where(x => x.RowId > 0)
-            .Where(x => x.TextCommand != null && x.TextCommand.Value != null)
-            .Select(x => (x.RowId, Command: x.TextCommand.Value!.Command?.ToString()))
-            .Where(x => x.Command != null && x.Command.StartsWith('/'))
-            .ToDictionary(x => (EEmote)x.RowId, x => x.Command!)
-            .AsReadOnly();
         _contentFinderConditionToContentId = dataManager.GetExcelSheet<ContentFinderCondition>()!
             .Where(x => x.RowId > 0 && x.Content > 0)
             .ToDictionary(x => x.RowId, x => x.Content)
 
     public bool TeleportAetheryte(uint aetheryteId)
     {
+        _logger.LogDebug("Attempting to teleport to aetheryte {AetheryteId}", aetheryteId);
         if (IsAetheryteUnlocked(aetheryteId, out var subIndex))
         {
             if (aetheryteId == PlayerState.Instance()->HomeAetheryteId &&
             {
                 ReturnRequestedAt = DateTime.Now;
                 if (ActionManager.Instance()->UseAction(ActionType.GeneralAction, 8))
+                {
+                    _logger.LogInformation("Using 'return' for home aetheryte");
                     return true;
+                }
             }
 
             if (ActionManager.Instance()->GetActionStatus(ActionType.Action, 5) == 0)
+            {
                 // fallback if return isn't available or (more likely) on a different aetheryte
+                _logger.LogInformation("Teleporting to aetheryte {AetheryteId}", aetheryteId);
                 return Telepo.Instance()->Teleport(aetheryteId, subIndex);
+            }
         }
 
         return false;
                playerState->IsAetherCurrentUnlocked(aetherCurrentId);
     }
 
-    public void ExecuteCommand(string command)
-    {
-        if (!command.StartsWith('/'))
-            return;
-
-        SendMessage(command);
-    }
-
-    #region SendMessage
-
-    /// <summary>
-    /// <para>
-    /// Send a given message to the chat box. <b>This can send chat to the server.</b>
-    /// </para>
-    /// <para>
-    /// <b>This method is unsafe.</b> This method does no checking on your input and
-    /// may send content to the server that the normal client could not. You must
-    /// verify what you're sending and handle content and length to properly use
-    /// this.
-    /// </para>
-    /// </summary>
-    /// <param name="message">Message to send</param>
-    /// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
-    private void SendMessageUnsafe(byte[] message)
-    {
-        var uiModule = (IntPtr)Framework.Instance()->GetUiModule();
-
-        using var payload = new ChatPayload(message);
-        var mem1 = Marshal.AllocHGlobal(400);
-        Marshal.StructureToPtr(payload, mem1, false);
-
-        _processChatBox(uiModule, mem1, IntPtr.Zero, 0);
-
-        Marshal.FreeHGlobal(mem1);
-    }
-
-    /// <summary>
-    /// <para>
-    /// Send a given message to the chat box. <b>This can send chat to the server.</b>
-    /// </para>
-    /// <para>
-    /// This method is slightly less unsafe than <see cref="SendMessageUnsafe"/>. It
-    /// will throw exceptions for certain inputs that the client can't normally send,
-    /// but it is still possible to make mistakes. Use with caution.
-    /// </para>
-    /// </summary>
-    /// <param name="message">message to send</param>
-    /// <exception cref="ArgumentException">If <paramref name="message"/> is empty, longer than 500 bytes in UTF-8, or contains invalid characters.</exception>
-    /// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
-    public void SendMessage(string message)
-    {
-        var bytes = Encoding.UTF8.GetBytes(message);
-        if (bytes.Length == 0)
-        {
-            throw new ArgumentException("message is empty", nameof(message));
-        }
-
-        if (bytes.Length > 500)
-        {
-            throw new ArgumentException("message is longer than 500 bytes", nameof(message));
-        }
-
-        if (message.Length != SanitiseText(message).Length)
-        {
-            throw new ArgumentException("message contained invalid characters", nameof(message));
-        }
-
-        SendMessageUnsafe(bytes);
-    }
-
-    /// <summary>
-    /// <para>
-    /// Sanitises a string by removing any invalid input.
-    /// </para>
-    /// <para>
-    /// The result of this method is safe to use with
-    /// <see cref="SendMessage"/>, provided that it is not empty or too
-    /// long.
-    /// </para>
-    /// </summary>
-    /// <param name="text">text to sanitise</param>
-    /// <returns>sanitised text</returns>
-    /// <exception cref="InvalidOperationException">If the signature for this function could not be found</exception>
-    public string SanitiseText(string text)
-    {
-        var uText = Utf8String.FromString(text);
-
-        _sanitiseString(uText, 0x27F, IntPtr.Zero);
-        var sanitised = uText->ToString();
-
-        uText->Dtor();
-        IMemorySpace.Free(uText);
-
-        return sanitised;
-    }
-
-    [StructLayout(LayoutKind.Explicit)]
-    [SuppressMessage("ReSharper", "PrivateFieldCanBeConvertedToLocalVariable")]
-    private readonly struct ChatPayload : IDisposable
-    {
-        [FieldOffset(0)] private readonly IntPtr textPtr;
-
-        [FieldOffset(16)] private readonly ulong textLen;
-
-        [FieldOffset(8)] private readonly ulong unk1;
-
-        [FieldOffset(24)] private readonly ulong unk2;
-
-        internal ChatPayload(byte[] stringBytes)
-        {
-            textPtr = Marshal.AllocHGlobal(stringBytes.Length + 30);
-            Marshal.Copy(stringBytes, 0, textPtr, stringBytes.Length);
-            Marshal.WriteByte(textPtr + stringBytes.Length, 0);
-
-            textLen = (ulong)(stringBytes.Length + 1);
-
-            unk1 = 64;
-            unk2 = 0;
-        }
-
-        public void Dispose()
-        {
-            Marshal.FreeHGlobal(textPtr);
-        }
-    }
-
-    #endregion
-
     public GameObject? FindObjectByDataId(uint dataId)
     {
         foreach (var gameObject in _objectTable)
         return false;
     }
 
-    public void UseEmote(uint dataId, EEmote emote)
-    {
-        GameObject? gameObject = FindObjectByDataId(dataId);
-        if (gameObject != null)
-        {
-            _targetManager.Target = gameObject;
-            ExecuteCommand($"{_emoteCommands[emote]} motion");
-        }
-    }
-
-    public void UseEmote(EEmote emote)
-    {
-        ExecuteCommand($"{_emoteCommands[emote]} motion");
-    }
-
     public bool IsObjectAtPosition(uint dataId, Vector3 position, float distance)
     {
         GameObject? gameObject = FindObjectByDataId(dataId);
         {
             if (ActionManager.Instance()->GetActionStatus(ActionType.Mount, _configuration.General.MountId) == 0)
             {
+                _logger.LogDebug("Attempting to use preferred mount...");
                 if (ActionManager.Instance()->UseAction(ActionType.Mount, _configuration.General.MountId))
                 {
                     _logger.LogInformation("Using preferred mount");
         {
             if (ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 9) == 0)
             {
+                _logger.LogDebug("Attempting to use mount roulette...");
                 if (ActionManager.Instance()->UseAction(ActionType.GeneralAction, 9))
                 {
                     _logger.LogInformation("Using mount roulette");
 
         if (ActionManager.Instance()->GetActionStatus(ActionType.GeneralAction, 23) == 0)
         {
-            _logger.LogInformation("Unmounting...");
-            return ActionManager.Instance()->UseAction(ActionType.GeneralAction, 23);
+            _logger.LogDebug("Attempting to unmount...");
+            if (ActionManager.Instance()->UseAction(ActionType.GeneralAction, 23))
+            {
+                _logger.LogInformation("Unmounted");
+                return true;
+            }
+
+            return false;
         }
         else
         {
 
 <Project Sdk="Microsoft.NET.Sdk">
     <PropertyGroup>
         <TargetFramework>net8.0-windows</TargetFramework>
-        <Version>0.18</Version>
+        <Version>0.19</Version>
         <LangVersion>12</LangVersion>
         <Nullable>enable</Nullable>
         <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
     </PropertyGroup>
 
     <ItemGroup>
-        <PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="4.0.1" />
+        <PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="4.0.1"/>
         <PackageReference Include="DalamudPackager" Version="2.1.12"/>
         <PackageReference Include="JetBrains.Annotations" Version="2023.3.0" ExcludeAssets="runtime"/>
-        <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
+        <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0"/>
         <PackageReference Include="System.Text.Json" Version="8.0.3"/>
     </ItemGroup>
 
     </ItemGroup>
 
     <ItemGroup>
-      <ProjectReference Include="..\LLib\LLib.csproj" />
-        <ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj" />
-        <ProjectReference Include="..\QuestPaths\QuestPaths.csproj" />
+        <ProjectReference Include="..\LLib\LLib.csproj"/>
+        <ProjectReference Include="..\Questionable.Model\Questionable.Model.csproj"/>
+        <ProjectReference Include="..\QuestPaths\QuestPaths.csproj"/>
     </ItemGroup>
 </Project>
 
         serviceCollection.AddSingleton((Configuration?)pluginInterface.GetPluginConfig() ?? new Configuration());
 
         serviceCollection.AddSingleton<GameFunctions>();
+        serviceCollection.AddSingleton<ChatFunctions>();
         serviceCollection.AddSingleton<AetheryteData>();
         serviceCollection.AddSingleton<TerritoryData>();
         serviceCollection.AddSingleton<NavmeshIpc>();
         serviceCollection.AddTaskWithFactory<Say.Factory, Say.UseChat>();
         serviceCollection.AddTaskWithFactory<UseItem.Factory, UseItem.UseOnGround, UseItem.UseOnObject, UseItem.Use>();
         serviceCollection.AddTaskWithFactory<EquipItem.Factory, EquipItem.DoEquip>();
-        serviceCollection.AddTaskWithFactory<SinglePlayerDuty.Factory, SinglePlayerDuty.DisableYesAlready, SinglePlayerDuty.RestoreYesAlready>();
+        serviceCollection
+            .AddTaskWithFactory<SinglePlayerDuty.Factory, SinglePlayerDuty.DisableYesAlready,
+                SinglePlayerDuty.RestoreYesAlready>();
 
         serviceCollection
             .AddTaskWithFactory<WaitAtEnd.Factory,
 
     private readonly string[] _mountNames;
 
     private readonly string[] _grandCompanyNames =
-        ["None (manually pick quest)", "Maelstrom", "Twin Adder"/*, "Immortal Flames"*/];
+        ["None (manually pick quest)", "Maelstrom", "Twin Adder" /*, "Immortal Flames"*/];
 
     [SuppressMessage("Performance", "CA1861", Justification = "One time initialization")]
     public ConfigWindow(DalamudPluginInterface pluginInterface, Configuration configuration, IDataManager dataManager)
 
     private readonly MovementController _movementController;
     private readonly QuestController _questController;
     private readonly GameFunctions _gameFunctions;
+    private readonly ChatFunctions _chatFunctions;
     private readonly IClientState _clientState;
     private readonly IFramework _framework;
     private readonly ITargetManager _targetManager;
         MovementController movementController,
         QuestController questController,
         GameFunctions gameFunctions,
+        ChatFunctions chatFunctions,
         IClientState clientState,
         IFramework framework,
         ITargetManager targetManager,
         _movementController = movementController;
         _questController = questController;
         _gameFunctions = gameFunctions;
+        _chatFunctions = chatFunctions;
         _clientState = clientState;
         _framework = framework;
         _targetManager = targetManager;
         if (ImGui.Button("Move to Flag"))
         {
             _movementController.Destination = null;
-            _gameFunctions.ExecuteCommand(
+            _chatFunctions.ExecuteCommand(
                 $"/vnav {(_gameFunctions.IsFlyingUnlockedInCurrentZone() ? "flyflag" : "moveflag")}");
         }