From fe565b1abdce82c7feee91d900b03e1f3e4aca53 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 00:54:23 -0700 Subject: [PATCH 1/7] Update loadouat regex for 4.1 event changes --- AutoTrackR2/KillTrackR_MainScript.ps1 | 33 ++++++++++----------------- AutoTrackR2/UpdatePage.xaml.cs | 2 +- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/AutoTrackR2/KillTrackR_MainScript.ps1 b/AutoTrackR2/KillTrackR_MainScript.ps1 index 57aec6b..42a7806 100644 --- a/AutoTrackR2/KillTrackR_MainScript.ps1 +++ b/AutoTrackR2/KillTrackR_MainScript.ps1 @@ -91,7 +91,7 @@ $prefixes = @( $killPattern = "<Actor Death> CActor::Kill: '(?<EnemyPilot>[^']+)' \[\d+\] in zone '(?<EnemyShip>[^']+)' killed by '(?<Player>[^']+)' \[[^']+\] using '(?<Weapon>[^']+)' \[Class (?<Class>[^\]]+)\] with damage type '(?<DamageType>[^']+)'" $puPattern = '<\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z> \[Notice\] <ContextEstablisherTaskFinished> establisher="CReplicationModel" message="CET completed" taskname="StopLoadingScreen" state=[^\s()]+\(\d+\) status="Finished" runningTime=\d+\.\d+ numRuns=\d+ map="megamap" gamerules="SC_Default" sessionId="[a-f0-9\-]+" \[Team_Network\]\[Network\]\[Replication\]\[Loading\]\[Persistence\]' $acPattern = "ArenaCommanderFeature" -$loadoutPattern = '\[InstancedInterior\] OnEntityLeaveZone - InstancedInterior \[(?<InstancedInterior>[^\]]+)\] \[\d+\] -> Entity \[(?<Entity>[^\]]+)\] \[\d+\] -- m_openDoors\[\d+\], m_managerGEID\[(?<ManagerGEID>\d+)\], m_ownerGEID\[(?<OwnerGEID>[^\[]+)\]' +$loadoutPattern = 'adam: (?<ShipName>.*.) in' $shipManPattern = "^(" + ($prefixes -join "|") + ")" # $loginPattern = "\[Notice\] <AccountLoginCharacterStatus_Character> Character: createdAt [A-Za-z0-9]+ - updatedAt [A-Za-z0-9]+ - geid [A-Za-z0-9]+ - accountId [A-Za-z0-9]+ - name (?<Player>[A-Za-z0-9_-]+) - state STATE_CURRENT" # KEEP THIS INCASE LEGACY LOGIN IS REMOVED $loginPattern = "\[Notice\] <Legacy login response> \[CIG-net\] User Login Success - Handle\[(?<Player>[A-Za-z0-9_-]+)\]" @@ -148,19 +148,13 @@ Do { } # Get Loadout if ($line -match $loadoutPattern) { - $entity = $matches['Entity'] - $ownerGEID = $matches['OwnerGEID'] - - If ($ownerGEID -eq $global:userName -and $entity -match $shipManPattern) { - $tryloadOut = $entity - If ($tryloadOut -match $cleanupPattern){ + If ($matches['ShipName'] -match $cleanupPattern){ if ($null -ne $matches[1]){ $global:loadOut = $matches[1] } - } - } + } + Write-Output "PlayerShip=$global:loadOut" } - Write-Output "PlayerShip=$global:loadOut" If ($line -match $versionPattern){ $global:GameVersion = $matches['gameversion'] @@ -465,18 +459,15 @@ function Read-LogEntry { } #Set loadout - if ($line -match $loadoutPattern) { - $entity = $matches['Entity'] - $ownerGEID = $matches['OwnerGEID'] + if ($line -match $loadoutPattern) { + If ($matches['ShipName'] -match $cleanupPattern){ + if ($null -ne $matches[1]){ + $global:loadOut = $matches[1] + } + } + Write-Output "PlayerShip=$global:loadOut" + } - If ($ownerGEID -eq $global:userName -and $entity -match $shipManPattern) { - $tryloadOut = $entity - If ($tryloadOut -match $cleanupPattern){ - $global:loadOut = $matches[1] - } - Write-Output "PlayerShip=$global:loadOut" - } - } } diff --git a/AutoTrackR2/UpdatePage.xaml.cs b/AutoTrackR2/UpdatePage.xaml.cs index 11f4d24..0d834fd 100644 --- a/AutoTrackR2/UpdatePage.xaml.cs +++ b/AutoTrackR2/UpdatePage.xaml.cs @@ -9,7 +9,7 @@ namespace AutoTrackR2 { public partial class UpdatePage : UserControl { - private string currentVersion = "v2.07"; + private string currentVersion = "v2.08"; private string latestVersion; public UpdatePage() From 69ef954d58a161c94ee4fcde783eacdf3aad8147 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 00:56:53 -0700 Subject: [PATCH 2/7] Minor refactor on the regex to make the event more obvious --- AutoTrackR2/KillTrackR_MainScript.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutoTrackR2/KillTrackR_MainScript.ps1 b/AutoTrackR2/KillTrackR_MainScript.ps1 index 42a7806..0f12abd 100644 --- a/AutoTrackR2/KillTrackR_MainScript.ps1 +++ b/AutoTrackR2/KillTrackR_MainScript.ps1 @@ -91,7 +91,7 @@ $prefixes = @( $killPattern = "<Actor Death> CActor::Kill: '(?<EnemyPilot>[^']+)' \[\d+\] in zone '(?<EnemyShip>[^']+)' killed by '(?<Player>[^']+)' \[[^']+\] using '(?<Weapon>[^']+)' \[Class (?<Class>[^\]]+)\] with damage type '(?<DamageType>[^']+)'" $puPattern = '<\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z> \[Notice\] <ContextEstablisherTaskFinished> establisher="CReplicationModel" message="CET completed" taskname="StopLoadingScreen" state=[^\s()]+\(\d+\) status="Finished" runningTime=\d+\.\d+ numRuns=\d+ map="megamap" gamerules="SC_Default" sessionId="[a-f0-9\-]+" \[Team_Network\]\[Network\]\[Replication\]\[Loading\]\[Persistence\]' $acPattern = "ArenaCommanderFeature" -$loadoutPattern = 'adam: (?<ShipName>.*.) in' +$loadoutPattern = '<Jump Drive State Changed>.*.adam: (?<ShipName>.*.) in' $shipManPattern = "^(" + ($prefixes -join "|") + ")" # $loginPattern = "\[Notice\] <AccountLoginCharacterStatus_Character> Character: createdAt [A-Za-z0-9]+ - updatedAt [A-Za-z0-9]+ - geid [A-Za-z0-9]+ - accountId [A-Za-z0-9]+ - name (?<Player>[A-Za-z0-9_-]+) - state STATE_CURRENT" # KEEP THIS INCASE LEGACY LOGIN IS REMOVED $loginPattern = "\[Notice\] <Legacy login response> \[CIG-net\] User Login Success - Handle\[(?<Player>[A-Za-z0-9_-]+)\]" From d6ce48b47538ff53db79f6ba61426f10fc0bc1c4 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 17:01:03 -0700 Subject: [PATCH 3/7] Implement KillHistory CSV functionality --- AutoTrackR2/HomePage.xaml.cs | 98 ++++++++++++++++++------------- AutoTrackR2/KillHistoryManager.cs | 83 ++++++++++++++++++++++++++ AutoTrackR2/MainWindow.xaml.cs | 12 ++++ AutoTrackR2/Util.cs | 31 ++++++++++ 4 files changed, 182 insertions(+), 42 deletions(-) create mode 100644 AutoTrackR2/KillHistoryManager.cs create mode 100644 AutoTrackR2/Util.cs diff --git a/AutoTrackR2/HomePage.xaml.cs b/AutoTrackR2/HomePage.xaml.cs index ccd42ab..fe47e59 100644 --- a/AutoTrackR2/HomePage.xaml.cs +++ b/AutoTrackR2/HomePage.xaml.cs @@ -5,38 +5,31 @@ using System.Windows.Media; using System.Windows.Media.Effects; using System.Windows.Documents; using System.Globalization; +using System.IO; +using System.Text; using System.Windows.Media.Imaging; using AutoTrackR2.LogEventHandlers; namespace AutoTrackR2; -public struct PlayerData -{ - public string? PFPURL; - public string? UEERecord; - public string? OrgURL; - public string? OrgName; - public string? JoinDate; -} - public partial class HomePage : UserControl { + private Process runningProcess; // Field to store the running process + private LogHandler? _logHandler; + private KillHistoryManager _killHistoryManager; + private bool _UIEventsRegistered = false; + public HomePage() { InitializeComponent(); - - // Get the current month - string currentMonth = DateTime.Now.ToString("MMMM", CultureInfo.InvariantCulture); + + _killHistoryManager = new KillHistoryManager(ConfigManager.KillHistoryFile); // Set the TextBlock text - KillTallyTitle.Text = $"Kill Tally - {currentMonth}"; + KillTallyTitle.Text = $"Kill Tally - {_killHistoryManager.GetKillsInCurrentMonth().Count}"; + AddKillHistoryKillsToUI(); } - - private Process runningProcess; // Field to store the running process - private LogHandler _logHandler; - private bool _UIEventsRegistered = false; - - + // Update Start/Stop button states based on the isRunning flag public void UpdateButtonState(bool isRunning) { @@ -89,6 +82,15 @@ public partial class HomePage : UserControl _logHandler = new LogHandler(ConfigManager.LogFile); _logHandler.Initialize(); } + + private void AddKillHistoryKillsToUI() + { + var kills = _killHistoryManager.GetKills(); + foreach (var kill in kills) + { + Dispatcher.Invoke(() => { AddKillToScreen(kill); }); + } + } private void RegisterUIEventHandlers() { @@ -134,15 +136,31 @@ public partial class HomePage : UserControl }; // Actor Death - TrackREventDispatcher.ActorDeathEvent += async (data) => { - if (data.VictimPilot != LocalPlayerData.Username) + TrackREventDispatcher.ActorDeathEvent += async (actorDeathData) => { + if (actorDeathData.VictimPilot != LocalPlayerData.Username) { - var playerData = await WebHandler.GetPlayerData(data.VictimPilot); + var playerData = await WebHandler.GetPlayerData(actorDeathData.VictimPilot); if (playerData != null) { - Dispatcher.Invoke(() => { AddKillToScreen(data, playerData); }); - await WebHandler.SubmitKill(data, playerData); + var killData = new KillData + { + EnemyPilot = actorDeathData.VictimPilot, + EnemyShip = actorDeathData.VictimShip, + OrgAffiliation = playerData?.OrgName, + Enlisted = playerData?.JoinDate, + KillTime = DateTime.UtcNow.ToString("dd MMM yyyy HH:mm"), + PFP = playerData?.PFPURL + }; + + // Add kill to UI + Dispatcher.Invoke(() => + { + AddKillToScreen(killData); + }); + + await WebHandler.SubmitKill(actorDeathData, playerData); + _killHistoryManager.AddKill(killData); } } }; @@ -155,7 +173,7 @@ public partial class HomePage : UserControl _UIEventsRegistered = true; } - private void AddKillToScreen(ActorDeathData deathData, PlayerData? playerData) + private void AddKillToScreen(KillData killData) { // Fetch the dynamic resource for AltTextColor var altTextColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AltTextColor"]); @@ -181,7 +199,7 @@ public partial class HomePage : UserControl Foreground = altTextColorBrush, FontFamily = orbitronFontFamily, }); - killTextBlock.Inlines.Add(new Run($"{deathData.VictimPilot}\n")); + killTextBlock.Inlines.Add(new Run($"{killData.EnemyPilot}\n")); // Repeat for other lines killTextBlock.Inlines.Add(new Run("Victim Ship: ") @@ -189,21 +207,21 @@ public partial class HomePage : UserControl Foreground = altTextColorBrush, FontFamily = orbitronFontFamily, }); - killTextBlock.Inlines.Add(new Run($"{deathData.VictimShip}\n")); + killTextBlock.Inlines.Add(new Run($"{killData.EnemyShip}\n")); killTextBlock.Inlines.Add(new Run("Victim Org: ") { Foreground = altTextColorBrush, FontFamily = orbitronFontFamily, }); - killTextBlock.Inlines.Add(new Run($"{playerData?.OrgName}\n")); + killTextBlock.Inlines.Add(new Run($"{killData.OrgAffiliation}\n")); killTextBlock.Inlines.Add(new Run("Join Date: ") { Foreground = altTextColorBrush, FontFamily = orbitronFontFamily, }); - killTextBlock.Inlines.Add(new Run($"{playerData?.JoinDate}\n")); + killTextBlock.Inlines.Add(new Run($"{killData.Enlisted}\n")); killTextBlock.Inlines.Add(new Run("UEE Record: ") { @@ -211,16 +229,12 @@ public partial class HomePage : UserControl FontFamily = orbitronFontFamily, }); - - const string dateFormatString = "dd MMM yyyy HH:mm"; - var currentTime = DateTime.UtcNow.ToString(dateFormatString); - killTextBlock.Inlines.Add(new Run("Kill Time: ") { Foreground = altTextColorBrush, FontFamily = orbitronFontFamily, }); - killTextBlock.Inlines.Add(new Run($"{currentTime}")); + killTextBlock.Inlines.Add(new Run($"{killData.KillTime}")); // Create a Border and apply the RoundedTextBlockWithBorder style var killBorder = new Border @@ -246,7 +260,7 @@ public partial class HomePage : UserControl // Create the Image for the profile var profileImage = new Image { - Source = new BitmapImage(new Uri(playerData?.PFPURL)), // Assuming the 8th part contains the profile image URL + Source = new BitmapImage(new Uri(killData.PFP)), // Assuming the 8th part contains the profile image URL Width = 90, Height = 90, Stretch = Stretch.Fill, // Adjust how the image fits @@ -279,15 +293,15 @@ public partial class HomePage : UserControl public void StopButton_Click(object sender, RoutedEventArgs e) { - _logHandler.Stop(); + _logHandler?.Stop(); // Clear the text boxes - System.Threading.Thread.Sleep(200); - PilotNameTextBox.Text = string.Empty; - PlayerShipTextBox.Text = string.Empty; - GameModeTextBox.Text = string.Empty; - KillTallyTextBox.Text = string.Empty; - KillFeedStackPanel.Children.Clear(); + // System.Threading.Thread.Sleep(200); + // PilotNameTextBox.Text = string.Empty; + // PlayerShipTextBox.Text = string.Empty; + // GameModeTextBox.Text = string.Empty; + // KillTallyTextBox.Text = string.Empty; + // KillFeedStackPanel.Children.Clear(); } private void AdjustFontSize(TextBlock textBlock) diff --git a/AutoTrackR2/KillHistoryManager.cs b/AutoTrackR2/KillHistoryManager.cs new file mode 100644 index 0000000..fd07f2e --- /dev/null +++ b/AutoTrackR2/KillHistoryManager.cs @@ -0,0 +1,83 @@ +using System.Globalization; +using System.IO; +using System.Text; + +namespace AutoTrackR2; + +public class KillHistoryManager +{ + private string _killHistoryPath; + private readonly string _headers = "KillTime,EnemyPilot,EnemyShip,Enlisted,RecordNumber,OrgAffiliation,Player,Weapon,Ship,Method,Mode,GameVersion,TrackRver,Logged,PFP\n"; + + public KillHistoryManager(string logPath) + { + _killHistoryPath = logPath; + + if (!File.Exists(_killHistoryPath)) + { + File.WriteAllText(_killHistoryPath, _headers); + } + } + + public void AddKill(KillData killData) + { + // Ensure the CSV file exists + // This should only happen if the file was deleted or corrupted + if (!File.Exists(_killHistoryPath)) + { + File.WriteAllText(_killHistoryPath, _headers); + } + + // Append the new kill data to the CSV file + var csv = new StringBuilder(); + csv.AppendLine($"\"{killData.KillTime}\",\"{killData.EnemyPilot}\",\"{killData.EnemyShip}\",\"{killData.Enlisted}\",\"{killData.RecordNumber}\",\"{killData.OrgAffiliation}\",\"{killData.Player}\",\"{killData.Weapon}\",\"{killData.Ship}\",\"{killData.Method}\",\"{killData.Mode}\",\"{killData.GameVersion}\",\"{killData.TrackRver}\",\"{killData.Logged}\",\"{killData.PFP}\""); + File.AppendAllText(_killHistoryPath, csv.ToString()); + } + + public List<KillData> GetKills() + { + var kills = new List<KillData>(); + + using var reader = new StreamReader(_killHistoryPath); + reader.ReadLine(); // Skip headers + + while (reader.Peek() >= 0) + { + 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] + }); + } + + return kills; + } + + public List<KillData> GetKillsInCurrentMonth() + { + string currentMonth = DateTime.Now.ToString("MMM", CultureInfo.InvariantCulture); + var kills = GetKills(); + return kills.Where(kill => kill.KillTime?.Contains(currentMonth) == true).ToList(); + } +} \ No newline at end of file diff --git a/AutoTrackR2/MainWindow.xaml.cs b/AutoTrackR2/MainWindow.xaml.cs index e432e97..3d143d0 100644 --- a/AutoTrackR2/MainWindow.xaml.cs +++ b/AutoTrackR2/MainWindow.xaml.cs @@ -195,6 +195,7 @@ namespace AutoTrackR2 public static class ConfigManager { public static string LogFile { get; set; } + public static string KillHistoryFile { get; set; } public static string ApiUrl { get; set; } public static string ApiKey { get; set; } public static string VideoPath { get; set; } @@ -202,6 +203,17 @@ namespace AutoTrackR2 public static int VideoRecord { get; set; } public static int OfflineMode { get; set; } public static int Theme { get; set; } + + static ConfigManager() + { + // Set default values + // AppData\Local\AutoTrackR2\Kill-log.csv + KillHistoryFile = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "AutoTrackR2", + "Kill-log.csv" + ); + } public static void LoadConfig() { diff --git a/AutoTrackR2/Util.cs b/AutoTrackR2/Util.cs new file mode 100644 index 0000000..b5931de --- /dev/null +++ b/AutoTrackR2/Util.cs @@ -0,0 +1,31 @@ +namespace AutoTrackR2; + +// Data returned from the CIG API +public struct PlayerData +{ + public string? PFPURL; + public string? UEERecord; + public string? OrgURL; + public string? OrgName; + public string? JoinDate; +} + +// Amalgamation of all data from a single kill +public struct KillData +{ + public string? KillTime; + public string? EnemyPilot; + public string? EnemyShip; + public string? Enlisted; + public string? RecordNumber; + public string? OrgAffiliation; + public string? Player; + public string? Weapon; + public string? Ship; + public string? Method; + public string? Mode; + public string? GameVersion; + public string? TrackRver; + public string? Logged; + public string? PFP; +} \ No newline at end of file From aa787d305ce661d35b408bd9b30913ff2f4668e0 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 17:15:40 -0700 Subject: [PATCH 4/7] Refactor config save/load --- AutoTrackR2/ConfigPage.xaml.cs | 39 ++++++++++------------------------ AutoTrackR2/HomePage.xaml.cs | 8 +++++++ AutoTrackR2/MainWindow.xaml.cs | 9 ++++---- 3 files changed, 23 insertions(+), 33 deletions(-) diff --git a/AutoTrackR2/ConfigPage.xaml.cs b/AutoTrackR2/ConfigPage.xaml.cs index 5e7f366..7dcfc7a 100644 --- a/AutoTrackR2/ConfigPage.xaml.cs +++ b/AutoTrackR2/ConfigPage.xaml.cs @@ -508,36 +508,19 @@ namespace AutoTrackR2 private void SaveButton_Click(object sender, RoutedEventArgs e) { - // Get the directory for the user's local application data - string appDataDirectory = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "AutoTrackR2" - ); - - // Ensure the directory exists - if (!Directory.Exists(appDataDirectory)) - { - Directory.CreateDirectory(appDataDirectory); - } - - // Combine the app data directory with the config file name - string configFilePath = Path.Combine(appDataDirectory, "config.ini"); - - using (StreamWriter writer = new StreamWriter(configFilePath)) - { - writer.WriteLine($"LogFile={LogFilePath.Text}"); - writer.WriteLine($"ApiUrl={ApiUrl.Text}"); - writer.WriteLine($"ApiKey={ApiKey.Text}"); - writer.WriteLine($"VideoPath={VideoPath.Text}"); - writer.WriteLine($"VisorWipe={(int)VisorWipeSlider.Value}"); - writer.WriteLine($"VideoRecord={(int)VideoRecordSlider.Value}"); - writer.WriteLine($"OfflineMode={(int)OfflineModeSlider.Value}"); - writer.WriteLine($"Theme={(int)ThemeSlider.Value}"); // Assumes you are saving the theme slider value (0, 1, or 2) - } - + ConfigManager.ApiKey = ApiKey.Text; + ConfigManager.ApiUrl = ApiUrl.Text; + ConfigManager.LogFile = LogFilePath.Text; + ConfigManager.VideoPath = VideoPath.Text; + ConfigManager.VisorWipe = (int)VisorWipeSlider.Value; + ConfigManager.VideoRecord = (int)VideoRecordSlider.Value; + ConfigManager.OfflineMode = (int)OfflineModeSlider.Value; + ConfigManager.Theme = (int)ThemeSlider.Value; + + // Save the current config values + ConfigManager.SaveConfig(); // Start the flashing effect FlashSaveButton(); - ConfigManager.LoadConfig(); } private void FlashSaveButton() diff --git a/AutoTrackR2/HomePage.xaml.cs b/AutoTrackR2/HomePage.xaml.cs index fe47e59..c4b3371 100644 --- a/AutoTrackR2/HomePage.xaml.cs +++ b/AutoTrackR2/HomePage.xaml.cs @@ -342,4 +342,12 @@ public partial class HomePage : UserControl // Apply the adjusted font size textBlock.FontSize = fontSize; } + + private void VisorWipe() + { + if (ConfigManager.VisorWipe == 1) + { + + } + } } diff --git a/AutoTrackR2/MainWindow.xaml.cs b/AutoTrackR2/MainWindow.xaml.cs index 3d143d0..94b6149 100644 --- a/AutoTrackR2/MainWindow.xaml.cs +++ b/AutoTrackR2/MainWindow.xaml.cs @@ -33,9 +33,6 @@ namespace AutoTrackR2 { InitializeComponent(); - // Load configuration settings before setting them in any page - ConfigManager.LoadConfig(); - homePage = new HomePage(); // Create a single instance of HomePage ContentControl.Content = homePage; // Default to HomePage @@ -205,7 +202,9 @@ namespace AutoTrackR2 public static int Theme { get; set; } static ConfigManager() - { + { + LoadConfig(); + // Set default values // AppData\Local\AutoTrackR2\Kill-log.csv KillHistoryFile = Path.Combine( @@ -253,7 +252,7 @@ namespace AutoTrackR2 // Define the config file path in a writable location string configDirectory = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "YourAppName" + "AutoTrackR2" ); // Ensure the directory exists From ebef4eca5b7db9cd1d76eeab95b6d712d2d0daa2 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 19:43:22 -0700 Subject: [PATCH 5/7] Add support for AHK scripts and remove the main Powershell Script --- AutoTrackR2/AutoTrackR2.csproj | 3 - AutoTrackR2/ConfigPage.xaml.cs | 3 +- AutoTrackR2/HomePage.xaml.cs | 41 +- AutoTrackR2/KillTrackR_MainScript.ps1 | 516 -------------------------- AutoTrackR2/MainWindow.xaml.cs | 16 + AutoTrackR2/UpdatePage.xaml.cs | 2 +- 6 files changed, 56 insertions(+), 525 deletions(-) delete mode 100644 AutoTrackR2/KillTrackR_MainScript.ps1 diff --git a/AutoTrackR2/AutoTrackR2.csproj b/AutoTrackR2/AutoTrackR2.csproj index 0ba95b7..875c53d 100644 --- a/AutoTrackR2/AutoTrackR2.csproj +++ b/AutoTrackR2/AutoTrackR2.csproj @@ -109,9 +109,6 @@ </ItemGroup> <ItemGroup> - <None Update="KillTrackR_MainScript.ps1"> - <CopyToOutputDirectory>Always</CopyToOutputDirectory> - </None> <None Update="update.ps1"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> diff --git a/AutoTrackR2/ConfigPage.xaml.cs b/AutoTrackR2/ConfigPage.xaml.cs index 7dcfc7a..f718aed 100644 --- a/AutoTrackR2/ConfigPage.xaml.cs +++ b/AutoTrackR2/ConfigPage.xaml.cs @@ -413,8 +413,7 @@ namespace AutoTrackR2 // Build the dynamic file path for the current user string filePath = Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), - "AutoTrackR2", + ConfigManager.AHKScriptFolder, "visorwipe.ahk" ); diff --git a/AutoTrackR2/HomePage.xaml.cs b/AutoTrackR2/HomePage.xaml.cs index c4b3371..cd264e6 100644 --- a/AutoTrackR2/HomePage.xaml.cs +++ b/AutoTrackR2/HomePage.xaml.cs @@ -81,6 +81,7 @@ public partial class HomePage : UserControl // _logHandler = new LogHandler(@"U:\\StarCitizen\\StarCitizen\\LIVE\\Game.log"); _logHandler = new LogHandler(ConfigManager.LogFile); _logHandler.Initialize(); + } private void AddKillHistoryKillsToUI() @@ -158,9 +159,16 @@ public partial class HomePage : UserControl { AddKillToScreen(killData); }); - - await WebHandler.SubmitKill(actorDeathData, playerData); + + // Only submit kill data if not in offline mode + if (ConfigManager.OfflineMode == 0) + { + await WebHandler.SubmitKill(actorDeathData, playerData); + } + _killHistoryManager.AddKill(killData); + VisorWipe(); + VideoRecord(); } } }; @@ -342,12 +350,39 @@ public partial class HomePage : UserControl // Apply the adjusted font size textBlock.FontSize = fontSize; } + + public static void RunAHKScript(string path) + { + string scriptPath = Path.Combine(ConfigManager.AHKScriptFolder, path); + + if (!File.Exists(scriptPath)) + { + return; + } + + // Run the script using powershell + using var ahkProcess = new Process(); + + // Runs the script via Explorer, ensuring it uses whatever the + // default binary for AHK is. Skips having to find a specific path to AHK + ahkProcess.StartInfo.FileName = "explorer"; + ahkProcess.StartInfo.Arguments = "\"" + scriptPath + "\""; + ahkProcess.Start(); + } private void VisorWipe() { if (ConfigManager.VisorWipe == 1) { - + RunAHKScript(ConfigManager.VisorWipeScript); + } + } + + private void VideoRecord() + { + if (ConfigManager.VideoRecord == 1) + { + RunAHKScript(ConfigManager.VideoRecordScript); } } } diff --git a/AutoTrackR2/KillTrackR_MainScript.ps1 b/AutoTrackR2/KillTrackR_MainScript.ps1 deleted file mode 100644 index 26f0ed2..0000000 --- a/AutoTrackR2/KillTrackR_MainScript.ps1 +++ /dev/null @@ -1,516 +0,0 @@ -$TrackRver = "2.07" - -# Path to the config file -$appName = "AutoTrackR2" -$scriptFolder = Join-Path -Path $env:LOCALAPPDATA -ChildPath $appName -$configFile = Join-Path -Path $scriptFolder -ChildPath "config.ini" - -# Read the config file into a hashtable -if (Test-Path $configFile) { - Write-Output "PlayerName=Config.ini found." - $configContent = Get-Content $configFile | Where-Object { $_ -notmatch '^#|^\s*$' } - - # Escape backslashes by doubling them - $configContent = $configContent -replace '\\', '\\\\' - - # Convert to key-value pairs - $config = $configContent -replace '^([^=]+)=(.+)$', '$1=$2' | ConvertFrom-StringData -} else { - Write-Output "Config.ini not found." - exit -} - -$parentApp = (Get-Process -Name AutoTrackR2).ID - -# Access config values -$logFilePath = $config.Logfile -$apiUrl = $config.ApiUrl -$apiKey = $config.ApiKey -$videoPath = $config.VideoPath -$visorWipe = $config.VisorWipe -$videoRecord = $config.VideoRecord -$offlineMode = $config.OfflineMode - -if ($offlineMode -eq 1){ - $offlineMode = $true -} else { - $offlineMode = $false -} -Write-Output "PlayerName=OfflineMode: $offlineMode" - -if ($videoRecord -eq 1){ - $videoRecord = $true -} else { - $videoRecord = $false -} -Write-Output "PlayerName=VideoRecord: $videoRecord" - -if ($visorWipe -eq 1){ - $visorWipe = $true -} else { - $visorWipe = $false -} -Write-Output "PlayerName=VisorWipe: $visorWipe" - -If (Test-Path $logFilePath) { - Write-Output "PlayerName=Logfile found" -} else { - Write-Output "Logfile not found." -} - -If ($null -ne $apiUrl){ - if ($apiUrl -notlike "*/register-kill") { - $apiUrl = $apiUrl.TrimEnd("/") + "/register-kill" - } - Write-output "PlayerName=$apiURL" -} - -# Ship Manufacturers -$prefixes = @( - "ORIG", - "CRUS", - "RSI", - "AEGS", - "VNCL", - "DRAK", - "ANVL", - "BANU", - "MISC", - "CNOU", - "XIAN", - "GAMA", - "TMBL", - "ESPR", - "KRIG", - "GRIN", - "XNAA", - "MRAI" -) - -# Define the regex pattern to extract information -$killPattern = "<Actor Death> CActor::Kill: '(?<EnemyPilot>[^']+)' \[\d+\] in zone '(?<EnemyShip>[^']+)' killed by '(?<Player>[^']+)' \[[^']+\] using '(?<Weapon>[^']+)' \[Class (?<Class>[^\]]+)\] with damage type '(?<DamageType>[^']+)'" -$puPattern = '<\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z> \[Notice\] <ContextEstablisherTaskFinished> establisher="CReplicationModel" message="CET completed" taskname="StopLoadingScreen" state=[^\s()]+\(\d+\) status="Finished" runningTime=\d+\.\d+ numRuns=\d+ map="megamap" gamerules="SC_Default" sessionId="[a-f0-9\-]+" \[Team_Network\]\[Network\]\[Replication\]\[Loading\]\[Persistence\]' -$acPattern = "Requesting Mode Change" # "ArenaCommanderFeature" -$loadoutPattern = '\[InstancedInterior\] OnEntityLeaveZone - InstancedInterior \[(?<InstancedInterior>[^\]]+)\] \[\d+\] -> Entity \[(?<Entity>[^\]]+)\] \[\d+\] -- m_openDoors\[\d+\], m_managerGEID\[(?<ManagerGEID>\d+)\], m_ownerGEID\[(?<OwnerGEID>[^\[]+)\]' -$shipManPattern = "^(" + ($prefixes -join "|") + ")" -# $loginPattern = "\[Notice\] <AccountLoginCharacterStatus_Character> Character: createdAt [A-Za-z0-9]+ - updatedAt [A-Za-z0-9]+ - geid [A-Za-z0-9]+ - accountId [A-Za-z0-9]+ - name (?<Player>[A-Za-z0-9_-]+) - state STATE_CURRENT" # KEEP THIS INCASE LEGACY LOGIN IS REMOVED -$loginPattern = "\[Notice\] <Legacy login response> \[CIG-net\] User Login Success - Handle\[(?<Player>[A-Za-z0-9_-]+)\]" -$cleanupPattern = '^(.+?)_\d+$' -$versionPattern = "--system-trace-env-id='pub-sc-alpha-(?<gameversion>\d{3,4}-\d{7})'" -$vehiclePattern = "<(?<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>[^']+)'" - -# Lookup Patterns -$joinDatePattern = '<span class="label">Enlisted</span>\s*<strong class="value">([^<]+)</strong>' -$ueePattern = '<p class="entry citizen-record">\s*<span class="label">UEE Citizen Record<\/span>\s*<strong class="value">#?(n\/a|\d+)<\/strong>\s*<\/p>' - -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$process = Get-Process | Where-Object {$_.Name -like "AutoTrackR2"} -$global:killTally = 0 - -# Load historic kills from csv -if (Test-Path "$scriptFolder\Kill-Log.csv") { - $historicKills = Import-CSV "$scriptFolder\Kill-log.csv" - $currentDate = Get-Date - $dateFormat = "dd MMM yyyy HH:mm UTC" - foreach ($kill in $historicKills) { - $killDate = [datetime]::ParseExact($kill.KillTime.Trim(), $dateFormat, [System.Globalization.CultureInfo]::InvariantCulture) - If ($killdate.year -eq $currentDate.Year -and $killdate.month -eq $currentDate.Month) { - $global:killTally++ - } - Try { - Write-Output "NewKill=throwaway,$($kill.EnemyPilot),$($kill.EnemyShip),$($kill.OrgAffiliation),$($kill.Enlisted),$($kill.RecordNumber),$($kill.KillTime), $($kill.PFP)" - } Catch { - Write-Output "Error Loading Kill: $($kill.EnemyPilot)" - } - } -} -Write-Output "KillTally=$global:killTally" - -# Match and extract username from gamelog -Do { - # Load gamelog into memory - $authLog = Get-Content -Path $logFilePath - - # Initialize variable to store username - $global:userName = $null - $global:loadout = "Player" - - # Loop through each line in the log to find the matching line - foreach ($line in $authLog) { - if ($line -match $loginPattern) { - $global:userName = $matches['Player'] - Write-Output "PlayerName=$global:userName" - } - # Get Loadout - if ($line -match $loadoutPattern) { - $entity = $matches['Entity'] - $ownerGEID = $matches['OwnerGEID'] - - If ($ownerGEID -eq $global:userName -and $entity -match $shipManPattern) { - $tryloadOut = $entity - If ($tryloadOut -match $cleanupPattern){ - if ($null -ne $matches[1]){ - $global:loadOut = $matches[1] - } - } - } - } - Write-Output "PlayerShip=$global:loadOut" - - If ($line -match $versionPattern){ - $global:GameVersion = $matches['gameversion'] - } - if ($line -match $acPattern){ - $global:GameMode = "AC" - } - if ($line -match $puPattern){ - $global:GameMode = "PU" - } - Write-Output "GameMode=$global:GameMode" - - } - # If no match found, print "Logged In: False" - if (-not $global:userName) { - Write-Output "PlayerName=No Player Found..." - Start-Sleep -Seconds 30 - } - - # Clear the log from memory - $authLog = $null -} until ($null -ne $global:userName) - -# Function to process new log entries and write to the host -function Read-LogEntry { - param ( - [string]$line - ) - - # Look for vehicle events - if ($line -match $vehiclePattern) { - # Access the named capture groups from the regex match - $global:vehicle_id = $matches['vehicle'] - $global:location = $matches['vehicle_zone'] - - } - - # Apply the regex pattern to the line - if ($line -match $killPattern) { - # Access the named capture groups from the regex match - $enemyPilot = $matches['EnemyPilot'] - $enemyShip = $matches['EnemyShip'] - $player = $matches['Player'] - $weapon = $matches['Weapon'] - $damageType = $matches['DamageType'] - $ship = $global:loadOut - - If ($enemyShip -ne "vehicle_id"){ - - $global:got_location = $location - } - else - { - $global:got_location = "NONE" - } - - Try { - $page1 = Invoke-WebRequest -uri "https://robertsspaceindustries.com/citizens/$enemyPilot" - } Catch { - $page1 = $null - } - - If ($null -ne $page1){ - # Check if the Autotrackr2 process is running - if ($null -eq (Get-Process -ID $parentApp -ErrorAction SilentlyContinue)) { - Stop-Process -Id $PID -Force - } - If ($enemyShip -ne "Player"){ - If ($enemyShip -eq $global:lastKill){ - $enemyShip = "Passenger" - } Else { - $global:lastKill = $enemyShip - } - } - - If ($player -eq $global:userName -and $enemyPilot -ne $global:userName){ - If ($enemyShip -match $cleanupPattern){ - $enemyShip = $matches[1] - } - If ($weapon -match $cleanupPattern){ - $weapon = $matches[1] - } - If ($weapon -eq "KLWE_MassDriver_S10"){ - $global:loadOut = "AEGS_Idris" - $ship = "AEGS_Idris" - } - if ($damageType -eq "Bullet" -or $weapon -like "apar_special_ballistic*") { - $ship = "Player" - $enemyShip = "Player" - } - If ($ship -match $cleanupPattern){ - $ship = $matches[1] - } - if ($ship -notmatch $shipManPattern){ - $ship = "Player" - } - If ($enemyShip -notmatch $shipManPattern -and $enemyShip -notlike "Passenger" ) { - $enemyShip = "Player" - } - - # Repeatedly remove all suffixes - while ($enemyShip -match '_(PU|AI|CIV|MIL|PIR)$') { - $enemyShip = $enemyShip -replace '_(PU|AI|CIV|MIL|PIR)$', '' - } - # Repeatedly remove all suffixes - while ($ship -match '_(PU|AI|CIV|MIL|PIR)$') { - $ship = $ship -replace '_(PU|AI|CIV|MIL|PIR)$', '' - } - while ($enemyShip -match '-00(1|2|3|4|5|6|7|8|9|0)$') { - $enemyShip = $enemyShip -replace '-00(1|2|3|4|5|6|7|8|9|0)$', '' - }while ($ship -match '-00(1|2|3|4|5|6|7|8|9|0)$') { - $ship = $ship -replace '-00(1|2|3|4|5|6|7|8|9|0)$', '' - } - - $KillTime = (Get-Date).ToUniversalTime().ToString("dd MMM yyyy HH:mm 'UTC'", [System.Globalization.CultureInfo]::InvariantCulture) - - # Get Enlisted Date - if ($($page1.content) -match $joinDatePattern) { - $joinDate = $matches[1] - $joinDate2 = $joinDate -replace ',', '' - } else { - $joinDate2 = "-" - } - - # Check if there are any matches - If ($null -eq $page1.links[0].innerHTML) { - $enemyOrgs = $page1.links[4].innerHTML - } Else { - $enemyOrgs = $page1.links[3].innerHTML - } - - if ($null -eq $enemyOrgs) { - $enemyOrgs = "-" - } - - # Get UEE Number - if ($($page1.content) -match $ueePattern) { - # The matched UEE Citizen Record number is in $matches[1] - $citizenRecord = $matches[1] - } else { - $citizenRecord = "n/a" - } - If ($citizenRecord -eq "n/a") { - $citizenRecordAPI = "-1" - $citizenRecord = "-" - } Else { - $citizenRecordAPI = $citizenRecord - } - - # Get PFP - if ($page1.images[0].src -like "/media/*") { - $victimPFP = "https://robertsspaceindustries.com$($page1.images[0].src)" - } Else { - $victimPFP = "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg" - } - - $global:killTally++ - Write-Output "KillTally=$global:killTally" - Write-Output "NewKill=throwaway,$enemyPilot,$enemyShip,$enemyOrgs,$joinDate2,$citizenRecord,$killTime,$victimPFP" - - $global:GameMode = $global:GameMode.ToLower() - # Send to API - # Define the data to send - If ($null -ne $apiUrl -and $offlineMode -eq $false){ - $data = @{ - victim_ship = $enemyShip - victim = $enemyPilot - enlisted = $joinDate - rsi = $citizenRecordAPI - weapon = $weapon - method = $damageType - loadout_ship = $ship - game_version = $global:GameVersion - gamemode = $global:GameMode - trackr_version = $TrackRver - location = $got_location - } - - # Headers which may or may not be necessary - $headers = @{ - "Authorization" = "Bearer $apiKey" - "Content-Type" = "application/json" - "User-Agent" = "AutoTrackR2" - } - - try { - # Send the POST request with JSON data - $null = Invoke-RestMethod -Uri $apiURL -Method Post -Body ($data | ConvertTo-Json -Depth 5) -Headers $headers - $logMode = "API" - $global:got_location = "NONE" - } catch { - # Catch and display errors - $apiError = $_ - # Add to output file - $logMode = "Err-Local" - } - } Else { - $logMode = "Local" - } - - # Define the output CSV path - $csvPath = "$scriptFolder\Kill-log.csv" - - # Create an object to hold the data - $killData = [PSCustomObject]@{ - KillTime = $killTime - EnemyPilot = $enemyPilot - EnemyShip = $enemyShip - Enlisted = $joinDate2 - RecordNumber = $citizenRecord - OrgAffiliation = $enemyOrgs - Player = $player - Weapon = $weapon - Ship = $ship - Method = $damageType - Mode = $global:GameMode - GameVersion = $global:GameVersion - TrackRver = $TrackRver - Logged = $logMode - PFP = $victimPFP - } - - # Remove commas from all properties - foreach ($property in $killData.PSObject.Properties) { - if ($property.Value -is [string]) { - $property.Value = $property.Value -replace ',', '' - } - } - - # Export to CSV - if (-Not (Test-Path $csvPath)) { - # If file doesn't exist, create it with headers - $killData | Export-Csv -Path $csvPath -NoTypeInformation - } else { - # Append data to the existing file without adding headers - $killData | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append -Encoding utf8 -FilePath $csvPath - } - - $sleeptimer = 10 - - # VisorWipe - If ($visorwipe -eq $true -and $enemyShip -ne "Passenger" -and $damageType -notlike "*Bullet*"){ - # send keybind for visorwipe - start-sleep 1 - $sleeptimer = $sleeptimer -1 - &"$scriptFolder\visorwipe.ahk" - } - - # Record video - if ($videoRecord -eq $true -and $enemyShip -ne "Passenger"){ - # send keybind for windows game bar recording - Start-Sleep 2 - $sleeptimer = $sleeptimer -9 - &"$scriptFolder\videorecord.ahk" - Start-Sleep 7 - - $latestFile = Get-ChildItem -Path $videoPath | Where-Object { -not $_.PSIsContainer } | Sort-Object CreationTime -Descending | Select-Object -First 1 - # Check if the latest file is no more than 30 seconds old - if ($latestFile) { - $fileAgeInSeconds = (New-TimeSpan -Start $latestFile.CreationTime -End (Get-Date)).TotalSeconds - if ($fileAgeInSeconds -le 30) { - # Generate a timestamp in ddMMMyyyy-HH:mm format - $timestamp = (Get-Date).ToString("ddMMMyyyy-HHmm") - - # Extract the file extension to preserve it - $fileExtension = $latestFile.Extension - - # Rename the file, preserving the original file extension - Rename-Item -Path $latestFile.FullName -NewName "$enemyPilot.$enemyShip.$timestamp$fileExtension" - } else {} - } else {} - } - Start-Sleep $sleeptimer - } - } - } - - # Get Logged-in User - If ($line -match $loginPattern) { - # Load gamelog into memory - $authLog = Get-Content -Path $logFilePath - $authLog = $authlog -match $loginPattern - $authLog = $authLog | Out-String - - # Extract User Name - $nameExtract = "name\s+(?<PlayerName>[^\s-]+)" - - If ($authLog -match $nameExtract -and $global:userName -ne $nameExtract){ - $global:userName = $matches['PlayerName'] - Write-Output "PlayerName=$global:userName" - } - } - - # Detect PU or AC - if ($line -match $puPattern) { - $global:GameMode = "PU" - Write-Output "GameMode=$global:GameMode" - } - if ($line -match $acPattern) { - $global:GameMode = "AC" - Write-Output "GameMode=$global:GameMode" - } - - #Set loadout - if ($line -match $loadoutPattern) { - $entity = $matches['Entity'] - $ownerGEID = $matches['OwnerGEID'] - - If ($ownerGEID -eq $global:userName -and $entity -match $shipManPattern) { - $tryloadOut = $entity - If ($tryloadOut -match $cleanupPattern){ - $global:loadOut = $matches[1] - } - Write-Output "PlayerShip=$global:loadOut" - } - } -} - - -# Monitor the log file and process new lines as they are added -Get-Content -Path $logFilePath -Wait -Tail 0 | ForEach-Object { - Read-LogEntry $_ -} - -<# -# Open the log file with shared access for reading and writing -$fileStream = [System.IO.FileStream]::new($logFilePath, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite) -$reader = [System.IO.StreamReader]::new($fileStream, [System.Text.Encoding]::UTF8) # Ensure we're reading as UTF-8 - -try { - # Move to the end of the file to start monitoring new entries - $reader.BaseStream.Seek(0, [System.IO.SeekOrigin]::End) - - while ($true) { - # Read the next line from the file - $line = $reader.ReadLine() - - # Ensure we have new content to process - if ($line) { - # Process the line (this is where your log entry handler would go) - Read-LogEntry $line - } - - # Sleep for a brief moment to avoid high CPU usage - Start-Sleep -Milliseconds 100 - } -} -finally { - # Ensure we close the reader and file stream properly when done - $reader.Close() - $fileStream.Close() -} -#> diff --git a/AutoTrackR2/MainWindow.xaml.cs b/AutoTrackR2/MainWindow.xaml.cs index 94b6149..637e90f 100644 --- a/AutoTrackR2/MainWindow.xaml.cs +++ b/AutoTrackR2/MainWindow.xaml.cs @@ -1,4 +1,6 @@ //using System.Collections.Generic; + +using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Input; @@ -193,6 +195,12 @@ namespace AutoTrackR2 { public static string LogFile { get; set; } public static string KillHistoryFile { get; set; } + + public static string AHKScriptFolder { get; set; } + + public static string VisorWipeScript { get; set; } + public static string VideoRecordScript { get; set; } + public static string ApiUrl { get; set; } public static string ApiKey { get; set; } public static string VideoPath { get; set; } @@ -212,6 +220,14 @@ namespace AutoTrackR2 "AutoTrackR2", "Kill-log.csv" ); + + AHKScriptFolder = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + "AutoTrackR2" + ); + + VisorWipeScript = "visorwipe.ahk"; + VideoRecordScript = "videorecord.ahk"; } public static void LoadConfig() diff --git a/AutoTrackR2/UpdatePage.xaml.cs b/AutoTrackR2/UpdatePage.xaml.cs index 75d9e70..87b260e 100644 --- a/AutoTrackR2/UpdatePage.xaml.cs +++ b/AutoTrackR2/UpdatePage.xaml.cs @@ -9,7 +9,7 @@ namespace AutoTrackR2 { public partial class UpdatePage : UserControl { - public static string currentVersion = "v2.08"; + public static string currentVersion = "v2.09"; private string latestVersion; public UpdatePage() From 90a905435c7802c2c0ee1cf0e98f8be5790065c6 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 19:54:01 -0700 Subject: [PATCH 6/7] UI enhancements on the config page --- AutoTrackR2/ConfigPage.xaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AutoTrackR2/ConfigPage.xaml b/AutoTrackR2/ConfigPage.xaml index 3b2016f..0f79db0 100644 --- a/AutoTrackR2/ConfigPage.xaml +++ b/AutoTrackR2/ConfigPage.xaml @@ -56,18 +56,21 @@ <!-- Visor Wipe Toggle Slider --> <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="Perform a Visor Wipe animation on player kill. Requires AHKv2." Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,4,3,5"/> <TextBlock Text="Visor Wipe:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/> <Slider Name="VisorWipeSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="27,-4,0,0" ValueChanged="VisorWipeSlider_ValueChanged"/> </StackPanel> <!-- Video Record Toggle Slider --> <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="Automatically clip your last kill. Check the README for more info." Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,4,3,5"/> <TextBlock Text="Video Record:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/> <Slider Name="VideoRecordSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="10,-4,0,0" ValueChanged="VideoRecordSlider_ValueChanged"/> </StackPanel> <!-- Offline Mode Toggle Slider --> <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="With Offline Mode enabled, kills will not be submitted to the configured API" Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,4,3,5"/> <TextBlock Text="Offline Mode:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/> <Slider Name="OfflineModeSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="12,-4,0,0" ValueChanged="OfflineModeSlider_ValueChanged"/> </StackPanel> From 0e4419e5cc8a6e03a93ad04d3d058a2aba3d6cf3 Mon Sep 17 00:00:00 2001 From: Dork Normalize <nope> Date: Fri, 28 Mar 2025 20:02:58 -0700 Subject: [PATCH 7/7] Add config info tooltips --- AutoTrackR2/ConfigPage.xaml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/AutoTrackR2/ConfigPage.xaml b/AutoTrackR2/ConfigPage.xaml index 0f79db0..937fe68 100644 --- a/AutoTrackR2/ConfigPage.xaml +++ b/AutoTrackR2/ConfigPage.xaml @@ -1,7 +1,7 @@ <UserControl x:Class="AutoTrackR2.ConfigPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - Height="396" Width="626"> + Height="410" Width="626"> <Grid Background="{DynamicResource BackgroundLightBrush}"> <!-- Main Layout Grid --> @@ -23,33 +23,37 @@ <StackPanel Grid.Column="0" VerticalAlignment="Center" Height="389"> <!-- Log File --> <StackPanel Margin="0,10,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="Set this to the Game.log file in your StarCitizen\LIVE directory." Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,0,3,5"/> <TextBlock Text="Log File:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,5,0,5" FontFamily="{StaticResource Roboto}"/> <StackPanel Orientation="Horizontal" Margin="30,0,0,0"> - <TextBox Name="LogFilePath" Width="340" Height="30" Style="{StaticResource RoundedTextBox}"/> + <TextBox Name="LogFilePath" Width="330" Height="30" Style="{StaticResource RoundedTextBox}"/> <Button Content="Browse" Width="75" Height="30" FontFamily="{StaticResource Orbitron}" Margin="5,0" Style="{StaticResource ButtonStyle}" Click="LogFileBrowseButton_Click"/> </StackPanel> </StackPanel> <!-- API URL --> <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="Need a URL? No idea what to do? Contact heavy_bob on Discord!" Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,3,3,5"/> <TextBlock Text="API URL:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,5,0,5"/> <StackPanel Orientation="Horizontal" Margin="30,0,0,0"> - <TextBox Name="ApiUrl" Width="340" Height="30" Style="{StaticResource RoundedTextBox}"/> + <TextBox Name="ApiUrl" Width="330" Height="30" Style="{StaticResource RoundedTextBox}"/> <Button Content="Test" Width="75" Height="30" FontFamily="{StaticResource Orbitron}" Margin="5,0" Style="{StaticResource ButtonStyle}" Click="TestApiButton_Click"/> </StackPanel> </StackPanel> <!-- API Key --> <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="Need a key? No idea what to do? Contact heavy_bob on Discord!" Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,3,3,5"/> <TextBlock Text="API Key:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,5,0,5"/> - <TextBox Name="ApiKey" Width="340" Height="30" Margin="33,0,0,0" Style="{StaticResource RoundedTextBox}"/> + <TextBox Name="ApiKey" Width="330" Height="30" Margin="33,0,0,0" Style="{StaticResource RoundedTextBox}"/> </StackPanel> <!-- Video Path --> <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="The directory where your clipping software saves kills. Check the README." Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,3,3,5"/> <TextBlock Text="Video Path:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,5,0,5"/> <StackPanel Orientation="Horizontal"> - <TextBox Name="VideoPath" Width="340" Height="30" Margin="10,0,0,0" Style="{StaticResource RoundedTextBox}"/> + <TextBox Name="VideoPath" Width="330" Height="30" Margin="10,0,0,0" Style="{StaticResource RoundedTextBox}"/> <Button Content="Browse" Width="75" Height="30" FontFamily="{StaticResource Orbitron}" Margin="5,0" Style="{StaticResource ButtonStyle}" Click="VideoPathBrowseButton_Click"/> </StackPanel> </StackPanel> @@ -69,8 +73,8 @@ </StackPanel> <!-- Offline Mode Toggle Slider --> - <StackPanel Margin="0,0,0,15" Orientation="Horizontal"> - <TextBlock Text="ⓘ" ToolTip="With Offline Mode enabled, kills will not be submitted to the configured API" Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,4,3,5"/> + <StackPanel Margin="0,0,0,10" Orientation="Horizontal"> + <TextBlock Text="ⓘ" ToolTip="With Offline Mode enabled, kills will not be submitted to the configured API." Foreground="{DynamicResource TextBrush}" FontSize="20" Margin="0,4,3,5"/> <TextBlock Text="Offline Mode:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/> <Slider Name="OfflineModeSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="12,-4,0,0" ValueChanged="OfflineModeSlider_ValueChanged"/> </StackPanel>