diff --git a/AutoTrackR2/App.xaml.cs b/AutoTrackR2/App.xaml.cs index 55a1e85..7441812 100644 --- a/AutoTrackR2/App.xaml.cs +++ b/AutoTrackR2/App.xaml.cs @@ -20,6 +20,13 @@ namespace AutoTrackR2 "crash.log" ); private StreamlinkHandler? _streamlinkHandler; + private KillStreakManager? _killStreakManager; + + private void HandleException(Exception ex) + { + MessageBox.Show($"Failed to start AutoTrackR2: {ex.Message}", "AutoTrackR2 Error", MessageBoxButton.OK, MessageBoxImage.Error); + Current.Shutdown(); + } protected override void OnStartup(StartupEventArgs e) { @@ -49,6 +56,10 @@ namespace AutoTrackR2 // Initialize StreamlinkHandler before creating the main window _streamlinkHandler = new StreamlinkHandler(); + // Initialize KillStreakManager + var soundsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sounds"); + _killStreakManager = new KillStreakManager(soundsPath); + // Create and show the main window var mainWindow = new MainWindow(); mainWindow.Show(); @@ -57,8 +68,7 @@ namespace AutoTrackR2 } catch (Exception ex) { - MessageBox.Show($"Failed to start AutoTrackR2: {ex.Message}", "AutoTrackR2 Error", MessageBoxButton.OK, MessageBoxImage.Error); - Current.Shutdown(); + HandleException(ex); } } @@ -110,24 +120,10 @@ namespace AutoTrackR2 protected override void OnExit(ExitEventArgs e) { - try - { - if (_mutex != null && _mutexOwned) - { - _mutex.ReleaseMutex(); - _mutex.Close(); - _mutex = null; - } - } - catch (Exception ex) - { - // Log the error but don't prevent shutdown - File.AppendAllText(CrashLogPath, $"[{DateTime.Now}] Error during shutdown: {ex.Message}\n"); - } - finally - { - base.OnExit(e); - } + // Clean up resources + _killStreakManager?.Cleanup(); + _mutex?.Dispose(); + base.OnExit(e); } } } diff --git a/AutoTrackR2/AutoTrackR2.csproj b/AutoTrackR2/AutoTrackR2.csproj index b9db3ce..6e88f61 100644 --- a/AutoTrackR2/AutoTrackR2.csproj +++ b/AutoTrackR2/AutoTrackR2.csproj @@ -38,4 +38,14 @@ </Resource> </ItemGroup> + <ItemGroup> + <None Include="sounds\*.mp3"> + <CopyToOutputDirectory>Always</CopyToOutputDirectory> + </None> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="NAudio" Version="2.2.1" /> + </ItemGroup> + </Project> diff --git a/AutoTrackR2/ConfigPage.xaml b/AutoTrackR2/ConfigPage.xaml index 5fb0510..55374eb 100644 --- a/AutoTrackR2/ConfigPage.xaml +++ b/AutoTrackR2/ConfigPage.xaml @@ -156,6 +156,19 @@ <RowDefinition Height="Auto"/> </Grid.RowDefinitions> + <!-- Kill Streak Test Button --> + <!-- + <Button Grid.Column="0" + Grid.Row="0" + Grid.ColumnSpan="2" + Content="Test Kill Streak Sounds" + Height="30" + FontFamily="{StaticResource Orbitron}" + Margin="0,0,0,10" + Style="{StaticResource ButtonStyle}" + Click="TestKillStreakButton_Click"/> + --> + <!-- Left Column Controls --> <!-- Visor Wipe Toggle --> diff --git a/AutoTrackR2/ConfigPage.xaml.cs b/AutoTrackR2/ConfigPage.xaml.cs index e4c1772..e7cd94b 100644 --- a/AutoTrackR2/ConfigPage.xaml.cs +++ b/AutoTrackR2/ConfigPage.xaml.cs @@ -12,6 +12,7 @@ using System.Windows.Media.Effects; using System.Windows.Threading; using Microsoft.Win32; using System.Threading.Tasks; +using AutoTrackR2.Constants; namespace AutoTrackR2; @@ -24,6 +25,10 @@ public partial class ConfigPage : UserControl Dictionary<string, Theme>? _themes = null; + private KillStreakManager? _testKillStreakManager; + private bool _isTestRunning = false; + private int _currentTestStep = 0; + public ConfigPage(MainWindow mainWindow) { InitializeComponent(); @@ -215,7 +220,7 @@ public partial class ConfigPage : UserControl dialog.CheckFileExists = false; dialog.CheckPathExists = true; dialog.FileName = "Folder Selection"; - + if (dialog.ShowDialog() == true) { string? selectedFolder = Path.GetDirectoryName(dialog.FileName); @@ -338,7 +343,7 @@ public partial class ConfigPage : UserControl 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 @@ -414,7 +419,7 @@ public partial class ConfigPage : UserControl client.DefaultRequestHeaders.UserAgent.ParseAdd("AutoTrackR2"); // Create JSON body with version - var jsonBody = new { version = "2.10" }; + var jsonBody = new { version = AppConstants.Version }; var content = new StringContent(JsonSerializer.Serialize(jsonBody), Encoding.UTF8, "application/json"); // Send POST @@ -502,7 +507,7 @@ public partial class ConfigPage : UserControl client.DefaultRequestHeaders.UserAgent.ParseAdd("AutoTrackR2"); // Create JSON body with version - var jsonBody = new { version = "2.10" }; + var jsonBody = new { version = AppConstants.Version }; var content = new StringContent(JsonSerializer.Serialize(jsonBody), Encoding.UTF8, "application/json"); // Send POST to test endpoint @@ -562,6 +567,26 @@ public partial class ConfigPage : UserControl MessageBox.Show("Directory does not exist.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } + + private async void TestKillStreakButton_Click(object sender, RoutedEventArgs e) + { + // Create a single KillStreakManager instance if it doesn't exist + if (_testKillStreakManager == null) + { + var soundsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sounds"); + _testKillStreakManager = new KillStreakManager(soundsPath); + } + + // Simulate 5 quick kills + for (int i = 0; i < 5; i++) + { + _testKillStreakManager.OnKill(); + } + + // Reset the streak after all sounds have played + await Task.Delay(1000); + _testKillStreakManager.OnDeath(); + } } public class Theme diff --git a/AutoTrackR2/Constants.cs b/AutoTrackR2/Constants.cs new file mode 100644 index 0000000..14a8c8a --- /dev/null +++ b/AutoTrackR2/Constants.cs @@ -0,0 +1,6 @@ +namespace AutoTrackR2.Constants; + +public static class AppConstants +{ + public const string Version = "2.11"; +} \ No newline at end of file diff --git a/AutoTrackR2/HomePage.xaml.cs b/AutoTrackR2/HomePage.xaml.cs index 80bbd06..b202b55 100644 --- a/AutoTrackR2/HomePage.xaml.cs +++ b/AutoTrackR2/HomePage.xaml.cs @@ -11,7 +11,7 @@ using System.Windows.Media.Imaging; using AutoTrackR2.LogEventHandlers; using System.Timers; using System.Linq; - +using AutoTrackR2.Constants; namespace AutoTrackR2; @@ -37,7 +37,7 @@ public partial class HomePage : UserControl { throw new InvalidOperationException("KillHistoryFile path is not configured."); } - _killHistoryManager = new KillHistoryManager(ConfigManager.KillHistoryFile); + _killHistoryManager = new KillHistoryManager(ConfigManager.KillHistoryFile, Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sounds")); // Set the TextBlock text KillTallyTitle.Text = $"Kill Tally - {DateTime.Now.ToString("MMMM")}"; @@ -231,7 +231,7 @@ public partial class HomePage : UserControl Method = actorDeathData.DamageType, RecordNumber = playerData?.UEERecord, GameVersion = LocalPlayerData.GameVersion ?? "Unknown", - TrackRver = "2.10", + TrackRver = AppConstants.Version, Enlisted = playerData?.JoinDate, KillTime = ((DateTimeOffset)DateTime.ParseExact(actorDeathData.Timestamp, "yyyy-MM-ddTHH:mm:ss.fffZ", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal)).ToUnixTimeSeconds().ToString(), PFP = playerData?.PFPURL ?? "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg", @@ -279,6 +279,11 @@ public partial class HomePage : UserControl }); } } + else + { + // Player died, reset kill streak + _killHistoryManager.ResetKillStreak(); + } }; // Vehicle Destruction diff --git a/AutoTrackR2/KillHistoryManager.cs b/AutoTrackR2/KillHistoryManager.cs index 65f33ad..fd8fa1a 100644 --- a/AutoTrackR2/KillHistoryManager.cs +++ b/AutoTrackR2/KillHistoryManager.cs @@ -8,11 +8,13 @@ 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,Hash\n"; + private readonly KillStreakManager _killStreakManager; - public KillHistoryManager(string logPath) + public KillHistoryManager(string logPath, string soundsPath) { _killHistoryPath = logPath; - + _killStreakManager = new KillStreakManager(soundsPath); + if (!File.Exists(_killHistoryPath)) { File.WriteAllText(_killHistoryPath, _headers); @@ -97,6 +99,9 @@ public class KillHistoryManager using var fileStream = new FileStream(_killHistoryPath, FileMode.Append, FileAccess.Write, FileShare.None); using var writer = new StreamWriter(fileStream); writer.Write(csv.ToString()); + + // Trigger kill streak sound + _killStreakManager.OnKill(); } catch (IOException ex) { @@ -104,7 +109,12 @@ public class KillHistoryManager Console.WriteLine($"Error writing to file: {ex.Message}"); } } - + + public void ResetKillStreak() + { + _killStreakManager.OnDeath(); + } + public List<KillData> GetKills() { var kills = new List<KillData>(); diff --git a/AutoTrackR2/KillStreakManager.cs b/AutoTrackR2/KillStreakManager.cs new file mode 100644 index 0000000..6d4fb28 --- /dev/null +++ b/AutoTrackR2/KillStreakManager.cs @@ -0,0 +1,176 @@ +using System.Media; +using System.Timers; +using System.IO; +using NAudio.Wave; + +namespace AutoTrackR2; + +public class KillStreakManager +{ + private readonly Queue<string> _soundQueue = new(); + private readonly System.Timers.Timer _killStreakTimer = new(5000); // 5 seconds between kills for streak + private int _currentKills = 0; + private int _totalKills = 0; + private readonly string _soundsPath; + private readonly object _lock = new(); + private WaveOutEvent? _waveOut; + private bool _isPlaying = false; + + public KillStreakManager(string soundsPath) + { + _soundsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sounds"); + _killStreakTimer.Elapsed += OnKillStreakTimerElapsed; + Console.WriteLine($"KillStreakManager initialized with sounds path: {_soundsPath}"); + } + + public void OnKill() + { + lock (_lock) + { + _currentKills++; + _totalKills++; + _killStreakTimer.Stop(); + _killStreakTimer.Start(); + + // Handle multi-kill announcements + string multiKillSound = _currentKills switch + { + 2 => "double_kill.mp3", + 3 => "triple_kill.mp3", + 4 => "overkill.mp3", + 5 => "killtacular.mp3", + 6 => "killtrocity.mp3", + 7 => "killimanjaro.mp3", + 8 => "killtastrophe.mp3", + 9 => "killpocalypse.mp3", + 10 => "killionaire.mp3", + _ => null + }; + + // Handle spree announcements + string spreeSound = _totalKills switch + { + 5 => "killing_spree.mp3", + 10 => "killing_frenzy.mp3", + 15 => "running_riot.mp3", + 20 => "rampage.mp3", + 25 => "untouchable.mp3", + 30 => "invincible.mp3", + 35 => "unstoppable.mp3", + 40 => "hells_janitor.mp3", + 45 => "perfection.mp3", + _ => null + }; + + // Queue up the sounds if they exist + if (multiKillSound != null) + { + string soundPath = Path.Combine(_soundsPath, multiKillSound); + Console.WriteLine($"Queueing multi-kill sound: {soundPath}"); + _soundQueue.Enqueue(soundPath); + } + if (spreeSound != null) + { + string soundPath = Path.Combine(_soundsPath, spreeSound); + Console.WriteLine($"Queueing spree sound: {soundPath}"); + _soundQueue.Enqueue(soundPath); + } + + // Only start playing if not already playing + if (!_isPlaying && _soundQueue.Count > 0) + { + PlayNextSound(); + } + } + } + + public void OnDeath() + { + lock (_lock) + { + _totalKills = 0; + _currentKills = 0; + _killStreakTimer.Stop(); + Console.WriteLine("Kill streak reset due to death"); + } + } + + private void OnKillStreakTimerElapsed(object? sender, ElapsedEventArgs e) + { + lock (_lock) + { + _currentKills = 0; + _killStreakTimer.Stop(); + Console.WriteLine("Kill streak reset due to timeout"); + } + } + + public void Cleanup() + { + lock (_lock) + { + _killStreakTimer.Stop(); + _killStreakTimer.Dispose(); + _waveOut?.Dispose(); + _waveOut = null; + } + } + + private void PlayNextSound() + { + if (_soundQueue.Count > 0) + { + string soundPath = _soundQueue.Dequeue(); + Console.WriteLine($"Attempting to play sound: {soundPath}"); + try + { + if (File.Exists(soundPath)) + { + // Stop any currently playing sound + _waveOut?.Stop(); + _waveOut?.Dispose(); + + // Create a new WaveOutEvent + _waveOut = new WaveOutEvent(); + + // Create a new AudioFileReader for the MP3 file + using var audioFile = new AudioFileReader(soundPath); + _waveOut.Init(audioFile); + + // Set up event handler for when playback finishes + _waveOut.PlaybackStopped += (sender, e) => + { + _isPlaying = false; + if (_soundQueue.Count > 0) + { + PlayNextSound(); + } + }; + + _isPlaying = true; + _waveOut.Play(); + + Console.WriteLine($"Successfully played sound: {soundPath}"); + } + else + { + Console.WriteLine($"Sound file not found: {soundPath}"); + _isPlaying = false; + if (_soundQueue.Count > 0) + { + PlayNextSound(); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Error playing sound {soundPath}: {ex.Message}"); + _isPlaying = false; + if (_soundQueue.Count > 0) + { + PlayNextSound(); + } + } + } + } +} \ No newline at end of file diff --git a/AutoTrackR2/LogHandler.cs b/AutoTrackR2/LogHandler.cs index 73c0f7f..d919078 100644 --- a/AutoTrackR2/LogHandler.cs +++ b/AutoTrackR2/LogHandler.cs @@ -181,7 +181,7 @@ public class LogHandler { // Wait for new lines to be written to the log file - Thread.Sleep(1000); + Thread.Sleep(500); } } Console.WriteLine("Monitor thread stopped"); diff --git a/AutoTrackR2/sounds/double_kill.mp3 b/AutoTrackR2/sounds/double_kill.mp3 new file mode 100644 index 0000000..bf4a0c3 Binary files /dev/null and b/AutoTrackR2/sounds/double_kill.mp3 differ diff --git a/AutoTrackR2/sounds/hells_janitor.mp3 b/AutoTrackR2/sounds/hells_janitor.mp3 new file mode 100644 index 0000000..30d0c04 Binary files /dev/null and b/AutoTrackR2/sounds/hells_janitor.mp3 differ diff --git a/AutoTrackR2/sounds/invincible.mp3 b/AutoTrackR2/sounds/invincible.mp3 new file mode 100644 index 0000000..7acbf3e Binary files /dev/null and b/AutoTrackR2/sounds/invincible.mp3 differ diff --git a/AutoTrackR2/sounds/killimanjaro.mp3 b/AutoTrackR2/sounds/killimanjaro.mp3 new file mode 100644 index 0000000..edbb2a6 Binary files /dev/null and b/AutoTrackR2/sounds/killimanjaro.mp3 differ diff --git a/AutoTrackR2/sounds/killing_frenzy.mp3 b/AutoTrackR2/sounds/killing_frenzy.mp3 new file mode 100644 index 0000000..6d64adf Binary files /dev/null and b/AutoTrackR2/sounds/killing_frenzy.mp3 differ diff --git a/AutoTrackR2/sounds/killing_spree.mp3 b/AutoTrackR2/sounds/killing_spree.mp3 new file mode 100644 index 0000000..5f2504a Binary files /dev/null and b/AutoTrackR2/sounds/killing_spree.mp3 differ diff --git a/AutoTrackR2/sounds/killionaire.mp3 b/AutoTrackR2/sounds/killionaire.mp3 new file mode 100644 index 0000000..0224b43 Binary files /dev/null and b/AutoTrackR2/sounds/killionaire.mp3 differ diff --git a/AutoTrackR2/sounds/killpocalypse.mp3 b/AutoTrackR2/sounds/killpocalypse.mp3 new file mode 100644 index 0000000..c1ce534 Binary files /dev/null and b/AutoTrackR2/sounds/killpocalypse.mp3 differ diff --git a/AutoTrackR2/sounds/killtacular.mp3 b/AutoTrackR2/sounds/killtacular.mp3 new file mode 100644 index 0000000..b0cc69a Binary files /dev/null and b/AutoTrackR2/sounds/killtacular.mp3 differ diff --git a/AutoTrackR2/sounds/killtastrophe.mp3 b/AutoTrackR2/sounds/killtastrophe.mp3 new file mode 100644 index 0000000..e4267cb Binary files /dev/null and b/AutoTrackR2/sounds/killtastrophe.mp3 differ diff --git a/AutoTrackR2/sounds/killtrocity.mp3 b/AutoTrackR2/sounds/killtrocity.mp3 new file mode 100644 index 0000000..5bd5f33 Binary files /dev/null and b/AutoTrackR2/sounds/killtrocity.mp3 differ diff --git a/AutoTrackR2/sounds/overkill.mp3 b/AutoTrackR2/sounds/overkill.mp3 new file mode 100644 index 0000000..83fb2bb Binary files /dev/null and b/AutoTrackR2/sounds/overkill.mp3 differ diff --git a/AutoTrackR2/sounds/perfection.mp3 b/AutoTrackR2/sounds/perfection.mp3 new file mode 100644 index 0000000..c0b7f74 Binary files /dev/null and b/AutoTrackR2/sounds/perfection.mp3 differ diff --git a/AutoTrackR2/sounds/rampage.mp3 b/AutoTrackR2/sounds/rampage.mp3 new file mode 100644 index 0000000..37d9bc9 Binary files /dev/null and b/AutoTrackR2/sounds/rampage.mp3 differ diff --git a/AutoTrackR2/sounds/running_riot.mp3 b/AutoTrackR2/sounds/running_riot.mp3 new file mode 100644 index 0000000..5eec17b Binary files /dev/null and b/AutoTrackR2/sounds/running_riot.mp3 differ diff --git a/AutoTrackR2/sounds/triple_kill.mp3 b/AutoTrackR2/sounds/triple_kill.mp3 new file mode 100644 index 0000000..b489151 Binary files /dev/null and b/AutoTrackR2/sounds/triple_kill.mp3 differ diff --git a/AutoTrackR2/sounds/unstoppable.mp3 b/AutoTrackR2/sounds/unstoppable.mp3 new file mode 100644 index 0000000..7c8a342 Binary files /dev/null and b/AutoTrackR2/sounds/unstoppable.mp3 differ diff --git a/AutoTrackR2/sounds/untouchable.mp3 b/AutoTrackR2/sounds/untouchable.mp3 new file mode 100644 index 0000000..4763213 Binary files /dev/null and b/AutoTrackR2/sounds/untouchable.mp3 differ