diff --git a/AutoTrackR2/AutoTrackR2.csproj b/AutoTrackR2/AutoTrackR2.csproj
index 3110af0..0089026 100644
--- a/AutoTrackR2/AutoTrackR2.csproj
+++ b/AutoTrackR2/AutoTrackR2.csproj
@@ -10,10 +10,14 @@
     <Configurations>Debug;Release;Test</Configurations>
     <Platforms>AnyCPU;x64</Platforms>
     <ApplicationIcon>AutoTrackR2.ico</ApplicationIcon>
-    <Version>2.12</Version>
+    <Version>2.13</Version>
     <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
     <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
     <Deterministic>true</Deterministic>
+    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
+    <SelfContained>false</SelfContained>
+    <PublishSingleFile>true</PublishSingleFile>
+    <IncludeNativeLibrariesForSelfExtract>false</IncludeNativeLibrariesForSelfExtract>
   </PropertyGroup>
 
   <ItemGroup>
@@ -48,4 +52,8 @@
     </None>
   </ItemGroup>
 
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.6" />
+  </ItemGroup>
+
 </Project>
diff --git a/AutoTrackR2/AutoTrackR2.sln b/AutoTrackR2/AutoTrackR2.sln
new file mode 100644
index 0000000..eb3096a
--- /dev/null
+++ b/AutoTrackR2/AutoTrackR2.sln
@@ -0,0 +1,24 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.2.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTrackR2", "AutoTrackR2.csproj", "{E22C9485-B9D3-1444-D963-459CE2284B32}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E22C9485-B9D3-1444-D963-459CE2284B32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{E22C9485-B9D3-1444-D963-459CE2284B32}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{E22C9485-B9D3-1444-D963-459CE2284B32}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{E22C9485-B9D3-1444-D963-459CE2284B32}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {BBD4E112-AC22-4175-9EAB-009EB91E395B}
+	EndGlobalSection
+EndGlobal
diff --git a/AutoTrackR2/Constants/Weapons.cs b/AutoTrackR2/Constants/Weapons.cs
index c3e97d8..3aab4d5 100644
--- a/AutoTrackR2/Constants/Weapons.cs
+++ b/AutoTrackR2/Constants/Weapons.cs
@@ -14,7 +14,15 @@ public static class Weapons
         "*repair*",
         "*cutter*",
         "*tractor*",
-        "*carryable*"
+        "*carryable*",
+        "*shotgun*",
+        "*sniper*",
+        "*rifle*",
+        "*smg*",
+        "*pistol*",
+        "*sniper*",
+        "*lmg*",
+        "*volt*",
     };
 
   public static bool IsKnownWeapon(string weaponName)
diff --git a/AutoTrackR2/HomePage.xaml.cs b/AutoTrackR2/HomePage.xaml.cs
index b4a8dcf..81a401b 100644
--- a/AutoTrackR2/HomePage.xaml.cs
+++ b/AutoTrackR2/HomePage.xaml.cs
@@ -34,6 +34,9 @@ public partial class HomePage : UserControl
     {
         InitializeComponent();
 
+        // Initialize default values
+        LocalPlayerData.PlayerShip = "Player";
+
         if (string.IsNullOrEmpty(ConfigManager.KillHistoryFile))
         {
             throw new InvalidOperationException("KillHistoryFile path is not configured.");
@@ -119,11 +122,11 @@ public partial class HomePage : UserControl
             {
                 // Game is not running, set everything to Unknown
                 GameModeTextBox.Text = "Unknown";
-                PlayerShipTextBox.Text = "Unknown";
+                PlayerShipTextBox.Text = "Player";
                 PilotNameTextBox.Text = "Unknown";
                 LocationTextBox.Text = "Unknown";
                 LocalPlayerData.CurrentGameMode = GameMode.Unknown;
-                LocalPlayerData.PlayerShip = string.Empty;
+                LocalPlayerData.PlayerShip = "Player";
                 LocalPlayerData.Username = string.Empty;
                 LocalPlayerData.LastSeenVehicleLocation = "Unknown";
 
@@ -197,6 +200,28 @@ public partial class HomePage : UserControl
             });
         };
 
+        // Vehicle Control
+        TrackREventDispatcher.VehicleControlEvent += (data) =>
+        {
+            Dispatcher.Invoke(() =>
+            {
+                PlayerShipTextBox.Text = data.Ship ?? "Player";
+                AdjustFontSize(PlayerShipTextBox);
+                LocalPlayerData.PlayerShip = data.Ship ?? "Player";
+            });
+        };
+
+        // Jump Drive State Changed (Location Only)
+        TrackREventDispatcher.JumpDriveStateChangedEvent += (data) =>
+        {
+            Dispatcher.Invoke(() =>
+            {
+                LocalPlayerData.LastSeenVehicleLocation = data.Location;
+                LocationTextBox.Text = data.Location;
+                AdjustFontSize(LocationTextBox);
+            });
+        };
+
         // Game Mode
         TrackREventDispatcher.PlayerChangedGameModeEvent += (mode) =>
         {
diff --git a/AutoTrackR2/KillHistoryManager.cs b/AutoTrackR2/KillHistoryManager.cs
index 14c1cfb..cb6f63c 100644
--- a/AutoTrackR2/KillHistoryManager.cs
+++ b/AutoTrackR2/KillHistoryManager.cs
@@ -1,4 +1,5 @@
-using System.Globalization;
+using Microsoft.Data.Sqlite;
+using System.Globalization;
 using System.IO;
 using System.Text;
 using System.Linq;
@@ -11,8 +12,7 @@ namespace AutoTrackR2;
 
 public class KillHistoryManager
 {
-    private readonly string _killHistoryPath;
-    private readonly string _headers = "KillTime,EnemyPilot,EnemyShip,Enlisted,RecordNumber,OrgAffiliation,Player,Weapon,Ship,Method,Mode,GameVersion,TrackRver,Logged,PFP,Hash\n";
+    private readonly string _dbPath;
     private readonly KillStreakManager _killStreakManager;
     private readonly ConcurrentQueue<KillData> _killQueue;
     private readonly CancellationTokenSource _cancellationTokenSource;
@@ -23,13 +23,9 @@ public class KillHistoryManager
     {
         var appDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AutoTrackR2");
         Directory.CreateDirectory(appDataPath); // Ensure the directory exists
-        _killHistoryPath = Path.Combine(appDataPath, "Kill-log.csv");
+        _dbPath = Path.Combine(appDataPath, "kills.db");
 
-        // Create the CSV file with headers if it doesn't exist
-        if (!File.Exists(_killHistoryPath))
-        {
-            File.WriteAllText(_killHistoryPath, _headers);
-        }
+        InitializeDatabase();
 
         _killStreakManager = new KillStreakManager(soundsPath);
         _killQueue = new ConcurrentQueue<KillData>();
@@ -39,6 +35,34 @@ public class KillHistoryManager
         _processingTask = Task.Run(ProcessKillQueue);
     }
 
+    private void InitializeDatabase()
+    {
+        using var connection = new SqliteConnection($"Data Source={_dbPath}");
+        connection.Open();
+        var command = connection.CreateCommand();
+        command.CommandText = @"
+            CREATE TABLE IF NOT EXISTS kills (
+                Hash TEXT PRIMARY KEY,
+                KillTime TEXT,
+                EnemyPilot TEXT,
+                EnemyShip TEXT,
+                Enlisted TEXT,
+                RecordNumber TEXT,
+                OrgAffiliation TEXT,
+                Weapon TEXT,
+                Ship TEXT,
+                Method TEXT,
+                Location TEXT,
+                Mode TEXT,
+                GameVersion TEXT,
+                TrackRver TEXT,
+                Logged TEXT,
+                PFP TEXT
+            );
+        ";
+        command.ExecuteNonQuery();
+    }
+
     private async Task ProcessKillQueue()
     {
         while (!_cancellationTokenSource.Token.IsCancellationRequested)
@@ -70,56 +94,41 @@ public class KillHistoryManager
     {
         try
         {
-            // Ensure all fields are properly escaped for CSV
-            var fields = new[]
-            {
-                kill.KillTime.ToString(),
-                EscapeCsvField(kill.EnemyPilot),
-                EscapeCsvField(kill.EnemyShip),
-                EscapeCsvField(kill.Enlisted),
-                EscapeCsvField(kill.RecordNumber),
-                EscapeCsvField(kill.OrgAffiliation),
-                EscapeCsvField(kill.Player),
-                EscapeCsvField(kill.Weapon),
-                EscapeCsvField(kill.Ship),
-                EscapeCsvField(kill.Method),
-                EscapeCsvField(kill.Mode),
-                EscapeCsvField(kill.GameVersion),
-                EscapeCsvField(kill.TrackRver),
-                EscapeCsvField(kill.Logged),
-                EscapeCsvField(kill.PFP),
-                EscapeCsvField(kill.Hash)
-            };
-
-            var csvLine = string.Join(",", fields);
-
-            // Use FileShare.Read to allow other processes to read while we write
-            using var stream = new FileStream(_killHistoryPath, FileMode.Append, FileAccess.Write, FileShare.Read);
-            using var writer = new StreamWriter(stream);
-            await writer.WriteLineAsync(csvLine);
+            using var connection = new SqliteConnection($"Data Source={_dbPath}");
+            await connection.OpenAsync();
+            var command = connection.CreateCommand();
+            command.CommandText = @"
+                INSERT OR IGNORE INTO kills (
+                    Hash, KillTime, EnemyPilot, EnemyShip, Enlisted, RecordNumber, OrgAffiliation, Weapon, Ship, Method, Location, Mode, GameVersion, TrackRver, Logged, PFP
+                ) VALUES (
+                    $Hash, $KillTime, $EnemyPilot, $EnemyShip, $Enlisted, $RecordNumber, $OrgAffiliation, $Weapon, $Ship, $Method, $Location, $Mode, $GameVersion, $TrackRver, $Logged, $PFP
+                );
+            ";
+            command.Parameters.AddWithValue("$Hash", kill.Hash ?? "");
+            command.Parameters.AddWithValue("$KillTime", kill.KillTime ?? "");
+            command.Parameters.AddWithValue("$EnemyPilot", kill.EnemyPilot ?? "");
+            command.Parameters.AddWithValue("$EnemyShip", kill.EnemyShip ?? "");
+            command.Parameters.AddWithValue("$Enlisted", kill.Enlisted ?? "");
+            command.Parameters.AddWithValue("$RecordNumber", kill.RecordNumber ?? "");
+            command.Parameters.AddWithValue("$OrgAffiliation", kill.OrgAffiliation ?? "");
+            command.Parameters.AddWithValue("$Weapon", kill.Weapon ?? "");
+            command.Parameters.AddWithValue("$Ship", kill.Ship ?? "");
+            command.Parameters.AddWithValue("$Method", kill.Method ?? "");
+            command.Parameters.AddWithValue("$Location", kill.Location ?? "");
+            command.Parameters.AddWithValue("$Mode", kill.Mode ?? "");
+            command.Parameters.AddWithValue("$GameVersion", kill.GameVersion ?? "");
+            command.Parameters.AddWithValue("$TrackRver", kill.TrackRver ?? "");
+            command.Parameters.AddWithValue("$Logged", kill.Logged ?? "");
+            command.Parameters.AddWithValue("$PFP", kill.PFP ?? "");
+            await command.ExecuteNonQueryAsync();
         }
         catch (Exception ex)
         {
-            Debug.WriteLine($"Error writing kill to CSV: {ex.Message}");
+            Debug.WriteLine($"Error writing kill to SQLite: {ex.Message}");
             throw;
         }
     }
 
-    private string EscapeCsvField(string field)
-    {
-        if (string.IsNullOrEmpty(field)) return "";
-
-        // If the field contains any special characters, wrap it in quotes
-        if (field.Contains(",") || field.Contains("\"") || field.Contains("\n") || field.Contains("\r"))
-        {
-            // Double up any quotes
-            field = field.Replace("\"", "\"\"");
-            return $"\"{field}\"";
-        }
-
-        return field;
-    }
-
     public void AddKill(KillData kill)
     {
         _killQueue.Enqueue(kill);
@@ -145,47 +154,38 @@ public class KillHistoryManager
     public List<KillData> GetKills()
     {
         var kills = new List<KillData>();
-
-        using var reader = new StreamReader(new FileStream(_killHistoryPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
-        reader.ReadLine(); // Skip headers
-
-        while (reader.Peek() >= 0)
+        using var connection = new SqliteConnection($"Data Source={_dbPath}");
+        connection.Open();
+        var command = connection.CreateCommand();
+        command.CommandText = "SELECT Hash, KillTime, EnemyPilot, EnemyShip, Enlisted, RecordNumber, OrgAffiliation, Weapon, Ship, Method, Location, Mode, GameVersion, TrackRver, Logged, PFP FROM kills";
+        using var reader = command.ExecuteReader();
+        while (reader.Read())
         {
-            var line = reader.ReadLine();
-
-            // Remove extra quotes from CSV data
-            // Todo: These quotes are for handling commas in the data, but not sure if they're necessary
-            line = line?.Replace("\"", string.Empty);
-
-            var data = line?.Split(',');
-
             kills.Add(new KillData
             {
-                KillTime = data?[0],
-                EnemyPilot = data?[1],
-                EnemyShip = data?[2],
-                Enlisted = data?[3],
-                RecordNumber = data?[4],
-                OrgAffiliation = data?[5],
-                Player = data?[6],
-                Weapon = data?[7],
-                Ship = data?[8],
-                Method = data?[9],
-                Mode = data?[10],
-                GameVersion = data?[11],
-                TrackRver = data?[12],
-                Logged = data?[13],
-                PFP = data?[14],
-                Hash = data?[15]
+                Hash = reader.GetString(0),
+                KillTime = reader.GetString(1),
+                EnemyPilot = reader.GetString(2),
+                EnemyShip = reader.GetString(3),
+                Enlisted = reader.GetString(4),
+                RecordNumber = reader.GetString(5),
+                OrgAffiliation = reader.GetString(6),
+                Weapon = reader.GetString(7),
+                Ship = reader.GetString(8),
+                Method = reader.GetString(9),
+                Location = reader.GetString(10),
+                Mode = reader.GetString(11),
+                GameVersion = reader.GetString(12),
+                TrackRver = reader.GetString(13),
+                Logged = reader.GetString(14),
+                PFP = reader.GetString(15)
             });
         }
-
         // Apply KillFeedLimit if specified
         if (ConfigManager.KillFeedLimit.HasValue && ConfigManager.KillFeedLimit.Value > 0)
         {
             kills = kills.TakeLast(ConfigManager.KillFeedLimit.Value).ToList();
         }
-
         return kills;
     }
 
@@ -193,57 +193,45 @@ public class KillHistoryManager
     {
         string currentMonth = DateTime.Now.ToString("MMM", CultureInfo.InvariantCulture);
         var kills = new List<KillData>();
-
-        // Read all kills directly from file, ignoring KillFeedLimit
-        using var reader = new StreamReader(new FileStream(_killHistoryPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
-        reader.ReadLine(); // Skip headers
-
-        while (reader.Peek() >= 0)
+        using var connection = new SqliteConnection($"Data Source={_dbPath}");
+        connection.Open();
+        var command = connection.CreateCommand();
+        command.CommandText = "SELECT Hash, KillTime, EnemyPilot, EnemyShip, Enlisted, RecordNumber, OrgAffiliation, Weapon, Ship, Method, Location, Mode, GameVersion, TrackRver, Logged, PFP FROM kills";
+        using var reader = command.ExecuteReader();
+        while (reader.Read())
         {
-            var line = reader.ReadLine();
-
-            // Remove extra quotes from CSV data
-            line = line?.Replace("\"", string.Empty);
-
-            var data = line?.Split(',');
-
+            var kill = new KillData
+            {
+                Hash = reader.GetString(0),
+                KillTime = reader.GetString(1),
+                EnemyPilot = reader.GetString(2),
+                EnemyShip = reader.GetString(3),
+                Enlisted = reader.GetString(4),
+                RecordNumber = reader.GetString(5),
+                OrgAffiliation = reader.GetString(6),
+                Weapon = reader.GetString(7),
+                Ship = reader.GetString(8),
+                Method = reader.GetString(9),
+                Location = reader.GetString(10),
+                Mode = reader.GetString(11),
+                GameVersion = reader.GetString(12),
+                TrackRver = reader.GetString(13),
+                Logged = reader.GetString(14),
+                PFP = reader.GetString(15)
+            };
             // Check if the kill is from the current month before adding it
-            var killTime = data?[0];
-            if (string.IsNullOrEmpty(killTime)) continue;
-
-            // Try to parse as Unix timestamp first
-            if (long.TryParse(killTime, out long unixTime))
+            if (!string.IsNullOrEmpty(kill.KillTime))
             {
-                var date = DateTimeOffset.FromUnixTimeSeconds(unixTime);
-                if (date.ToString("MMM", CultureInfo.InvariantCulture) != currentMonth) continue;
+                if (long.TryParse(kill.KillTime, out long unixTime))
+                {
+                    var date = DateTimeOffset.FromUnixTimeSeconds(unixTime).DateTime;
+                    if (date.ToString("MMM", CultureInfo.InvariantCulture) == currentMonth)
+                    {
+                        kills.Add(kill);
+                    }
+                }
             }
-            else if (!killTime.Contains(currentMonth))
-            {
-                // Fall back to checking if it contains the month name (old format)
-                continue;
-            }
-
-            kills.Add(new KillData
-            {
-                KillTime = killTime,
-                EnemyPilot = data?[1],
-                EnemyShip = data?[2],
-                Enlisted = data?[3],
-                RecordNumber = data?[4],
-                OrgAffiliation = data?[5],
-                Player = data?[6],
-                Weapon = data?[7],
-                Ship = data?[8],
-                Method = data?[9],
-                Mode = data?[10],
-                GameVersion = data?[11],
-                TrackRver = data?[12],
-                Logged = data?[13],
-                PFP = data?[14],
-                Hash = data?[15]
-            });
         }
-
         return kills;
     }
 }
\ No newline at end of file
diff --git a/AutoTrackR2/LogEventHandlers/JumpDriveStateChangedEvent.cs b/AutoTrackR2/LogEventHandlers/JumpDriveStateChangedEvent.cs
index 2adf26f..01135d7 100644
--- a/AutoTrackR2/LogEventHandlers/JumpDriveStateChangedEvent.cs
+++ b/AutoTrackR2/LogEventHandlers/JumpDriveStateChangedEvent.cs
@@ -12,12 +12,12 @@ public class JumpDriveStateChangedEvent : ILogEventHandler
 {
     public Regex Pattern { get; }
     private Regex _cleanUpPattern = new Regex(@"(.+?)_\d+$");
-    
+
     public JumpDriveStateChangedEvent()
     {
         Pattern = new Regex(@"<Jump Drive State Changed>.*.adam: (?<ShipName>.*.) in zone (?<Location>.*.)\)");
     }
-    
+
     public void Handle(LogEntry entry)
     {
         if (entry.Message is null) return;
@@ -34,6 +34,13 @@ public class JumpDriveStateChangedEvent : ILogEventHandler
         {
             data.ShipName = match.Groups[1].Value;
         }
+
+        // Skip applying loadout if ship name matches "Default"
+        if (data.ShipName?.Equals("Default", StringComparison.OrdinalIgnoreCase) == true)
+        {
+            return;
+        }
+
         if (!string.IsNullOrEmpty(data.ShipName) && !string.IsNullOrEmpty(data.Location))
         {
             TrackREventDispatcher.OnJumpDriveStateChangedEvent(data);
diff --git a/AutoTrackR2/LogEventHandlers/RequestJumpFailedEvent.cs b/AutoTrackR2/LogEventHandlers/RequestJumpFailedEvent.cs
index aaef3e3..b096992 100644
--- a/AutoTrackR2/LogEventHandlers/RequestJumpFailedEvent.cs
+++ b/AutoTrackR2/LogEventHandlers/RequestJumpFailedEvent.cs
@@ -6,29 +6,35 @@ public class RequestJumpFailedEvent : ILogEventHandler
 {
     public Regex Pattern { get; }
     private Regex _cleanUpPattern = new Regex(@"(.+?)_\d+$");
-    
+
     public RequestJumpFailedEvent()
     {
         Pattern = new Regex(@"<Request Jump Failed>.*.adam: (?<ShipName>.*.) in zone (?<Location>.*.)\)");
     }
-    
+
     public void Handle(LogEntry entry)
     {
         if (entry.Message is null) return;
         var match = Pattern.Match(entry.Message);
         if (!match.Success) return;
-        
+
         var data = new JumpDriveStateChangedData
         {
             Location = match.Groups["Location"].Value
         };
-        
+
         match = _cleanUpPattern.Match(match.Groups["ShipName"].Value);
         if (match.Success)
         {
             data.ShipName = match.Groups[1].Value;
         }
-        
+
+        // Skip applying loadout if ship name matches "Default"
+        if (data.ShipName?.Equals("Default", StringComparison.OrdinalIgnoreCase) == true)
+        {
+            return;
+        }
+
         if (!string.IsNullOrEmpty(data.ShipName) && !string.IsNullOrEmpty(data.Location))
         {
             TrackREventDispatcher.OnJumpDriveStateChangedEvent(data);
diff --git a/AutoTrackR2/LogEventHandlers/VehicleControlEvent.cs b/AutoTrackR2/LogEventHandlers/VehicleControlEvent.cs
new file mode 100644
index 0000000..60ed34f
--- /dev/null
+++ b/AutoTrackR2/LogEventHandlers/VehicleControlEvent.cs
@@ -0,0 +1,80 @@
+using System.Text.RegularExpressions;
+using AutoTrackR2.Constants;
+
+namespace AutoTrackR2.LogEventHandlers;
+
+public struct VehicleControlData
+{
+  public string Action { get; set; } // "SetDriver" or "ClearDriver"
+  public string VehicleName { get; set; }
+  public string? Ship { get; set; }
+}
+
+public class VehicleControlEvent : ILogEventHandler
+{
+  public Regex Pattern { get; }
+  private Regex _cleanUpPattern = new Regex(@"(.+?)_\d+$");
+
+  public VehicleControlEvent()
+  {
+    // Pattern for entering vehicle (granted control)
+    Pattern = new Regex(@"granted control token for '(?<vehicle_name>[^']+)'", RegexOptions.Compiled);
+  }
+
+  public void Handle(LogEntry entry)
+  {
+    if (entry.Message is null) return;
+
+    // Check for vehicle entry (granted control)
+    var enterMatch = Pattern.Match(entry.Message);
+    if (enterMatch.Success)
+    {
+      var vehicleName = enterMatch.Groups["vehicle_name"].Value;
+      var cleanedShipName = CleanShipName(vehicleName);
+      LocalPlayerData.PlayerShip = cleanedShipName;
+      var data = new VehicleControlData
+      {
+        Action = "SetDriver",
+        VehicleName = vehicleName,
+        Ship = cleanedShipName
+      };
+      TrackREventDispatcher.OnVehicleControlEvent(data);
+      return;
+    }
+  }
+
+  private string CleanShipName(string vehicleName)
+  {
+    var cleanMatch = _cleanUpPattern.Match(vehicleName);
+    return cleanMatch.Success ? cleanMatch.Groups[1].Value : vehicleName;
+  }
+}
+
+public class VehicleControlClearEvent : ILogEventHandler
+{
+  public Regex Pattern { get; }
+
+  public VehicleControlClearEvent()
+  {
+    // Pattern for exiting vehicle (releasing control)
+    Pattern = new Regex(@"releasing control token", RegexOptions.Compiled);
+  }
+
+  public void Handle(LogEntry entry)
+  {
+    if (entry.Message is null) return;
+
+    var match = Pattern.Match(entry.Message);
+    if (match.Success)
+    {
+      LocalPlayerData.PlayerShip = "Player";
+      var data = new VehicleControlData
+      {
+        Action = "ClearDriver",
+        VehicleName = "Player",
+        Ship = "Player"
+      };
+      TrackREventDispatcher.OnVehicleControlEvent(data);
+    }
+  }
+}
\ No newline at end of file
diff --git a/AutoTrackR2/LogEventHandlers/VehicleDestructionEvent.cs b/AutoTrackR2/LogEventHandlers/VehicleDestructionEvent.cs
index 47b808a..1af55b6 100644
--- a/AutoTrackR2/LogEventHandlers/VehicleDestructionEvent.cs
+++ b/AutoTrackR2/LogEventHandlers/VehicleDestructionEvent.cs
@@ -1,64 +1,55 @@
 using System.Text.RegularExpressions;
+using AutoTrackR2.Constants;
 
 namespace AutoTrackR2.LogEventHandlers;
 
 public struct VehicleDestructionData
 {
-    public string Vehicle { get; set; }
+    public string VehicleName { get; set; }
+    public string VehicleId { get; set; }
+    public string Team { get; set; }
     public string VehicleZone { get; set; }
-    public float PosX { get; set; }
-    public float PosY { get; set; }
-    public float PosZ { get; set; }
-    public string Driver { get; set; }
-    public int DestroyLevelFrom { get; set; }
-    public int DestroyLevelTo { get; set; }
-    public string CausedBy { get; set; }
-    public string DamageType { get; set; }
+    public string? Ship { get; set; }
 }
 
 public class VehicleDestructionEvent : ILogEventHandler
 {
     public Regex Pattern { get; }
+    private Regex _shipManufacturerPattern;
+    private Regex _cleanUpPattern = new Regex(@"(.+?)_\d+$");
+
     public VehicleDestructionEvent()
     {
-        const string patternStr = """
-                                  <(?<timestamp>[^>]+)> \[Notice\] <Vehicle Destruction> CVehicle::OnAdvanceDestroyLevel: 
-                                  Vehicle '(?<vehicle>[^']+)' \[\d+\] in zone '(?<vehicle_zone>[^']+)' 
-                                  \[pos x: (?<pos_x>[-\d\.]+), y: (?<pos_y>[-\d\.]+), z: (?<pos_z>[-\d\.]+) 
-                                  vel x: [^,]+, y: [^,]+, z: [^\]]+\] driven by '(?<driver>[^']+)' \[\d+\] 
-                                  advanced from destroy level (?<destroy_level_from>\d+) to (?<destroy_level_to>\d+) 
-                                  caused by '(?<caused_by>[^']+)' \[\d+\] with '(?<damage_type>[^']+)'
-                                  """;
-        
-        Pattern = new Regex(Regex.Replace(patternStr, @"\t|\n|\r", ""));
+        Pattern = new Regex(@"<Vehicle Destruction> Vehicle '(?<vehicle_name>[^']+)' \[(?<vehicle_id>\d+)\] \[(?<team>[^\]]+)\] in zone '(?<vehicle_zone>[^']+)' has been destroyed");
+        _shipManufacturerPattern = new Regex($"^({string.Join("|", ShipManufacturers.List)})");
     }
 
     public void Handle(LogEntry entry)
     {
-        if (entry.Message == null)
-        {
-            return;
-        }
+        if (entry.Message is null) return;
+
         var match = Pattern.Match(entry.Message);
-        if (!match.Success)
-        {
-            return;
-        }
+        if (!match.Success) return;
 
         var data = new VehicleDestructionData
         {
-            Vehicle = match.Groups["vehicle"].Value,
+            VehicleName = match.Groups["vehicle_name"].Value,
+            VehicleId = match.Groups["vehicle_id"].Value,
+            Team = match.Groups["team"].Value,
             VehicleZone = match.Groups["vehicle_zone"].Value,
-            PosX = float.Parse(match.Groups["pos_x"].Value),
-            PosY = float.Parse(match.Groups["pos_y"].Value),
-            PosZ = float.Parse(match.Groups["pos_z"].Value),
-            Driver = match.Groups["driver"].Value,
-            DestroyLevelFrom = int.Parse(match.Groups["destroy_level_from"].Value),
-            DestroyLevelTo = int.Parse(match.Groups["destroy_level_to"].Value),
-            CausedBy = match.Groups["caused_by"].Value,
-            DamageType = match.Groups["damage_type"].Value,
         };
 
+        // Extract ship name from vehicle name if it's a ship
+        var shipMatch = _shipManufacturerPattern.Match(data.VehicleName);
+        if (shipMatch.Success)
+        {
+            var cleanMatch = _cleanUpPattern.Match(data.VehicleName);
+            if (cleanMatch.Success)
+            {
+                data.Ship = cleanMatch.Groups[1].Value;
+            }
+        }
+
         TrackREventDispatcher.OnVehicleDestructionEvent(data);
     }
 }
\ No newline at end of file
diff --git a/AutoTrackR2/LogHandler.cs b/AutoTrackR2/LogHandler.cs
index c8da3c7..79f5b20 100644
--- a/AutoTrackR2/LogHandler.cs
+++ b/AutoTrackR2/LogHandler.cs
@@ -47,7 +47,9 @@ public class LogHandler
         new JumpDriveStateChangedEvent(),
         new RequestJumpFailedEvent(),
         new VehicleDestructionEvent(),
-        new ActorDeathEvent()
+        new ActorDeathEvent(),
+        new VehicleControlEvent(),
+        new VehicleControlClearEvent()
     ];
 
     public LogHandler(string? logPath)
diff --git a/AutoTrackR2/TrackREventDispatcher.cs b/AutoTrackR2/TrackREventDispatcher.cs
index 36823ac..cf51a88 100644
--- a/AutoTrackR2/TrackREventDispatcher.cs
+++ b/AutoTrackR2/TrackREventDispatcher.cs
@@ -18,37 +18,36 @@ public static class TrackREventDispatcher
     {
         InstancedInteriorEvent?.Invoke(data);
     }
-    
+
     // Player changed GameMode (AC or PU)
     public static event Action<GameMode>? PlayerChangedGameModeEvent;
     public static void OnPlayerChangedGameModeEvent(GameMode mode)
     {
         PlayerChangedGameModeEvent?.Invoke(mode);
     }
-    
+
     // Game version has been detected
     public static event Action<string>? GameVersionEvent;
     public static void OnGameVersionEvent(string value)
     {
         GameVersionEvent?.Invoke(value);
     }
-    
+
     // Actor has died
     public static event Action<ActorDeathData>? ActorDeathEvent;
     public static void OnActorDeathEvent(ActorDeathData data)
     {
         ActorDeathEvent?.Invoke(data);
     }
-    
+
     // Vehicle has been destroyed
     public static event Action<VehicleDestructionData>? VehicleDestructionEvent;
     public static void OnVehicleDestructionEvent(VehicleDestructionData data)
     {
         VehicleDestructionEvent?.Invoke(data);
     }
-    
+
     // Jump Drive state has changed
-    // Todo: Add proper data for this event. Right now only ship name is used.
     public static event Action<JumpDriveStateChangedData>? JumpDriveStateChangedEvent;
     public static void OnJumpDriveStateChangedEvent(JumpDriveStateChangedData data)
     {
@@ -61,4 +60,11 @@ public static class TrackREventDispatcher
     {
         StreamlinkRecordEvent?.Invoke(streamerHandle);
     }
+
+    // Vehicle control has changed
+    public static event Action<VehicleControlData>? VehicleControlEvent;
+    public static void OnVehicleControlEvent(VehicleControlData data)
+    {
+        VehicleControlEvent?.Invoke(data);
+    }
 }
\ No newline at end of file