Added dath and other tracking

It is now possible to record death and other fatal events by setting a slider.

The CSV structure has been changed but this updates the script automatically.

Api still only sends in case of a kill event.
This commit is contained in:
Koda-Dog 2025-01-18 11:06:46 +01:00
parent e43286bde1
commit db66bc0a89
9 changed files with 642 additions and 168 deletions

View file

@ -54,22 +54,28 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<!-- Visor Wipe Toggle Slider --> <!-- Visor Wipe & KillLog Toggle Slider -->
<StackPanel Margin="0,0,0,15" Orientation="Horizontal"> <StackPanel Margin="0,0,0,15" Orientation="Horizontal">
<TextBlock Text="Visor Wipe:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/> <TextBlock Text="Visorr 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"/> <Slider Name="VisorWipeSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="21,-4,0,0" ValueChanged="VisorWipeSlider_ValueChanged"/>
<TextBlock Text="KillLog:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/>
<Slider Name="KillLogSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="44,-4,0,0" ValueChanged="OfflineModeSlider_ValueChanged"/>
</StackPanel> </StackPanel>
<!-- Video Record Toggle Slider --> <!-- Video Record & DeathLog Toggle Slider -->
<StackPanel Margin="0,0,0,15" Orientation="Horizontal"> <StackPanel Margin="0,0,0,15" Orientation="Horizontal">
<TextBlock Text="Video Record:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,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"/> <Slider Name="VideoRecordSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="10,-4,0,0" ValueChanged="VideoRecordSlider_ValueChanged"/>
<TextBlock Text="DeathLog:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/>
<Slider Name="DeathLogSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="22,-4,0,0" ValueChanged="OfflineModeSlider_ValueChanged"/>
</StackPanel> </StackPanel>
<!-- Offline Mode Toggle Slider --> <!-- Offline Mode & OtherLog Toggle Slider -->
<StackPanel Margin="0,0,0,15" Orientation="Horizontal"> <StackPanel Margin="0,0,0,15" Orientation="Horizontal">
<TextBlock Text="Offline Mode:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,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"/> <Slider Name="OfflineModeSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="12,-4,0,0" ValueChanged="OfflineModeSlider_ValueChanged"/>
<TextBlock Text="OtherLog:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/>
<Slider Name="OtherLogSlider" Minimum="0" Maximum="1" TickFrequency="1" IsSnapToTickEnabled="True" Value="0" Style="{StaticResource ToggleSliderStyle}" Margin="10,-4,0,0" ValueChanged="OfflineModeSlider_ValueChanged"/>
</StackPanel> </StackPanel>
<!-- 3-Position Toggle Slider --> <!-- 3-Position Toggle Slider -->

View file

@ -32,9 +32,12 @@ namespace AutoTrackR2
VisorWipeSlider.Value = ConfigManager.VisorWipe; VisorWipeSlider.Value = ConfigManager.VisorWipe;
VideoRecordSlider.Value = ConfigManager.VideoRecord; VideoRecordSlider.Value = ConfigManager.VideoRecord;
OfflineModeSlider.Value = ConfigManager.OfflineMode; OfflineModeSlider.Value = ConfigManager.OfflineMode;
KillLogSlider.Value = ConfigManager.KillLog;
DeathLogSlider.Value = ConfigManager.DeathLog;
OtherLogSlider.Value = ConfigManager.OtherLog;
ThemeSlider.Value = ConfigManager.Theme; ThemeSlider.Value = ConfigManager.Theme;
ApplyToggleModeStyle(OfflineModeSlider.Value, VisorWipeSlider.Value, VideoRecordSlider.Value); ApplyToggleModeStyle(OfflineModeSlider.Value, VisorWipeSlider.Value, VideoRecordSlider.Value, KillLogSlider.Value, DeathLogSlider.Value, OtherLogSlider.Value);
} }
// Method to change the logo image in MainWindow // Method to change the logo image in MainWindow
@ -65,7 +68,7 @@ namespace AutoTrackR2
// This method will set the loaded config values to the UI controls // This method will set the loaded config values to the UI controls
public void SetConfigValues(string logFile, string apiUrl, string apiKey, string videoPath, public void SetConfigValues(string logFile, string apiUrl, string apiKey, string videoPath,
int visorWipe, int videoRecord, int offlineMode, int theme) int visorWipe, int videoRecord, int offlineMode, int killLog, int deathLog, int otherLog, int theme)
{ {
// Set the textboxes with the loaded values // Set the textboxes with the loaded values
LogFilePath.Text = logFile; LogFilePath.Text = logFile;
@ -77,6 +80,9 @@ namespace AutoTrackR2
VideoRecordSlider.Value = videoRecord; VideoRecordSlider.Value = videoRecord;
VisorWipeSlider.Value = visorWipe; VisorWipeSlider.Value = visorWipe;
OfflineModeSlider.Value = offlineMode; OfflineModeSlider.Value = offlineMode;
KillLogSlider.Value = killLog;
DeathLogSlider.Value = deathLog;
OtherLogSlider.Value = otherLog;
// Handle themes // Handle themes
if (theme >= 0 && theme <= 3) if (theme >= 0 && theme <= 3)
@ -89,14 +95,17 @@ namespace AutoTrackR2
} }
} }
private void ApplyToggleModeStyle(double offlineModeValue, double visorWipeValue, double videoRecordValue) private void ApplyToggleModeStyle(double offlineModeValue, double visorWipeValue, double videoRecordValue, double killLogValue, double deathLogvalue, double otherLogValue)
{ {
// Get the slider // Get the slider
Slider offlineModeSlider = OfflineModeSlider; Slider offlineModeSlider = OfflineModeSlider;
Slider visorWipeSlider = VisorWipeSlider; Slider visorWipeSlider = VisorWipeSlider;
Slider videoRecordSlider = VideoRecordSlider; Slider videoRecordSlider = VideoRecordSlider;
Slider killLogSlider = KillLogSlider;
Slider deathLogSlider = DeathLogSlider;
Slider otherLogSlider = OtherLogSlider;
// Set the appropriate style based on the offlineMode value (0 or 1) // Set the appropriate style based on value (0 or 1)
if (offlineModeValue == 0) if (offlineModeValue == 0)
{ {
offlineModeSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle"); offlineModeSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
@ -111,6 +120,21 @@ namespace AutoTrackR2
{ {
videoRecordSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle"); videoRecordSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
} }
if (killLogValue == 0)
{
killLogSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
}
if (deathLogvalue == 0)
{
deathLogSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
}
if (otherLogValue == 0)
{
otherLogSlider.Style = (Style)Application.Current.FindResource("FalseToggleStyle");
}
} }
private void ThemeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) private void ThemeSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
@ -384,12 +408,14 @@ namespace AutoTrackR2
// Video Path Browse Button Handler // Video Path Browse Button Handler
private void VideoPathBrowseButton_Click(object sender, RoutedEventArgs e) private void VideoPathBrowseButton_Click(object sender, RoutedEventArgs e)
{ {
var dialog = new OpenFileDialog(); // Prepare a dummy string, thos would appear in the dialog
dialog.CheckFileExists = false; string dummyFileName = "Path where the videos should be";
dialog.ValidateNames = false;
dialog.Filter = "All files|*.*";
if (dialog.ShowDialog() == true) SaveFileDialog dialog = new SaveFileDialog();
// Feed the dummy name to the save dialog
dialog.FileName = dummyFileName;
if(dialog.ShowDialog() == true)
{ {
// Extract only the directory path from the file // Extract only the directory path from the file
string selectedFolder = Path.GetDirectoryName(dialog.FileName); string selectedFolder = Path.GetDirectoryName(dialog.FileName);
@ -495,7 +521,6 @@ namespace AutoTrackR2
} }
} }
private void SaveButton_Click(object sender, RoutedEventArgs e) private void SaveButton_Click(object sender, RoutedEventArgs e)
{ {
// Get the directory for the user's local application data // Get the directory for the user's local application data
@ -522,6 +547,9 @@ namespace AutoTrackR2
writer.WriteLine($"VisorWipe={(int)VisorWipeSlider.Value}"); writer.WriteLine($"VisorWipe={(int)VisorWipeSlider.Value}");
writer.WriteLine($"VideoRecord={(int)VideoRecordSlider.Value}"); writer.WriteLine($"VideoRecord={(int)VideoRecordSlider.Value}");
writer.WriteLine($"OfflineMode={(int)OfflineModeSlider.Value}"); writer.WriteLine($"OfflineMode={(int)OfflineModeSlider.Value}");
writer.WriteLine($"KillLog={(int)KillLogSlider.Value}");
writer.WriteLine($"DeathLog={(int)DeathLogSlider.Value}");
writer.WriteLine($"OtherLog={(int)OtherLogSlider.Value}");
writer.WriteLine($"Theme={(int)ThemeSlider.Value}"); // Assumes you are saving the theme slider value (0, 1, or 2) writer.WriteLine($"Theme={(int)ThemeSlider.Value}"); // Assumes you are saving the theme slider value (0, 1, or 2)
} }

View file

@ -27,16 +27,25 @@
</Border> </Border>
<!-- StackPanel for Start and Stop buttons --> <!-- StackPanel for Start and Stop buttons -->
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" Grid.Row="0" Grid.Column="1" BorderThickness="2" CornerRadius="5" Margin="0,0,0,82"/> <Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" Grid.Row="0" Grid.Column="1" BorderThickness="2" CornerRadius="5" Margin="0,0,0,62"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Height="269" Width="152"> <StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Height="264" Width="152">
<TextBlock Name="PilotNameTitle" Text="Pilot" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14"/> <TextBlock Name="PilotNameTitle" Text="Pilot" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14"/>
<TextBlock Name="PilotNameTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/> <TextBlock Name="PilotNameTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
<TextBlock Name="PlayerShipTitle" Text="Ship" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14" /> <TextBlock Name="PlayerShipTitle" Text="Ship" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14" />
<TextBlock Name="PlayerShipTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/> <TextBlock Name="PlayerShipTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
<TextBlock Name="GameModeTitle" Text="Game Mode" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14"/> <TextBlock Name="GameModeTitle" Text="Game Mode" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14"/>
<TextBlock Name="GameModeTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/> <TextBlock Name="GameModeTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
<TextBlock Name="KillTallyTitle" Text="Kill Tally" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14"/> <TextBlock Name="KillTallyTitle" Text="Tally" Width="152" Height="18" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="14"/>
<TextBlock Name="KillTallyTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/> <StackPanel Orientation="Horizontal">
<TextBlock Name="TallyKTitle" Text="K" Width="51" Height="18" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="12" TextAlignment="Center"/>
<TextBlock Name="TallyDTitle" Text="D" Width="51" Height="18" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="12" TextAlignment="Center"/>
<TextBlock Name="TallyOTitle" Text="O" Width="50" Height="18" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,5,0,0" Foreground="{DynamicResource AltTextBrush}" FontSize="12" TextAlignment="Center"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Name="KillTallyTextBox" Text="K" Width="51" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
<TextBlock Name="DeathTallyTextBox" Text="D" Width="51" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
<TextBlock Name="OtherTallyTextBox" Text="O" Width="50" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
</StackPanel>
<TextBox x:Name="DebugPanel" Text="" Width="152" Height="98" Background="Transparent" FontFamily="{StaticResource Orbitron}" Foreground="{DynamicResource TextBrush}" FontSize="8" BorderThickness="0" Margin="0,9,0,0"/> <TextBox x:Name="DebugPanel" Text="" Width="152" Height="98" Background="Transparent" FontFamily="{StaticResource Orbitron}" Foreground="{DynamicResource TextBrush}" FontSize="8" BorderThickness="0" Margin="0,9,0,0"/>
</StackPanel> </StackPanel>
<StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Height="120" Width="172" > <StackPanel Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Height="120" Width="172" >

View file

@ -20,7 +20,7 @@ namespace AutoTrackR2
string currentMonth = DateTime.Now.ToString("MMMM", CultureInfo.InvariantCulture); string currentMonth = DateTime.Now.ToString("MMMM", CultureInfo.InvariantCulture);
// Set the TextBlock text // Set the TextBlock text
KillTallyTitle.Text = $"Kill Tally - {currentMonth}"; KillTallyTitle.Text = $"Tally - {currentMonth}";
} }
private Process runningProcess; // Field to store the running process private Process runningProcess; // Field to store the running process
@ -122,6 +122,18 @@ namespace AutoTrackR2
KillTallyTextBox.Text = killTally; KillTallyTextBox.Text = killTally;
AdjustFontSize(KillTallyTextBox); AdjustFontSize(KillTallyTextBox);
} }
else if (e.Data.Contains("DeathTally="))
{
string deathTally = e.Data.Split('=')[1].Trim();
DeathTallyTextBox.Text = deathTally;
AdjustFontSize(DeathTallyTextBox);
}
else if (e.Data.Contains("OtherTally="))
{
string otherTally = e.Data.Split('=')[1].Trim();
OtherTallyTextBox.Text = otherTally;
AdjustFontSize(OtherTallyTextBox);
}
else if (e.Data.Contains("NewKill=")) else if (e.Data.Contains("NewKill="))
{ {
// Parse the kill data // Parse the kill data
@ -147,6 +159,14 @@ namespace AutoTrackR2
}; };
// Add styled content using Run elements // Add styled content using Run elements
killTextBlock.Inlines.Add(new Run("Event Type: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run("Kill\n"));
// Repeat for other lines
killTextBlock.Inlines.Add(new Run("Victim Name: ") killTextBlock.Inlines.Add(new Run("Victim Name: ")
{ {
Foreground = altTextColorBrush, Foreground = altTextColorBrush,
@ -154,7 +174,6 @@ namespace AutoTrackR2
}); });
killTextBlock.Inlines.Add(new Run($"{killParts[1]}\n")); killTextBlock.Inlines.Add(new Run($"{killParts[1]}\n"));
// Repeat for other lines
killTextBlock.Inlines.Add(new Run("Victim Ship: ") killTextBlock.Inlines.Add(new Run("Victim Ship: ")
{ {
Foreground = altTextColorBrush, Foreground = altTextColorBrush,
@ -200,7 +219,7 @@ namespace AutoTrackR2
var killGrid = new Grid var killGrid = new Grid
{ {
Width = 400, // Adjust the width of the Grid Width = 400, // Adjust the width of the Grid
Height = 130, // Adjust the height as needed Height = 150, // Adjust the height as needed
}; };
// Define two columns in the Grid: one for the text and one for the image // Define two columns in the Grid: one for the text and one for the image
@ -241,6 +260,205 @@ namespace AutoTrackR2
// Add the new Border to the StackPanel inside the Border // Add the new Border to the StackPanel inside the Border
KillFeedStackPanel.Children.Insert(0, killBorder); KillFeedStackPanel.Children.Insert(0, killBorder);
} }
else if (e.Data.Contains("NewDeath="))
{
// Parse the death data
var killData = e.Data.Split('=')[1].Trim(); // Assume the death data follows after "NewKill="
var killParts = killData.Split(',');
// Fetch the dynamic resource for AltTextColor
var altTextColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AltTextColor"]);
var accentColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AccentColor"]);
// Fetch the Orbitron FontFamily from resources
var orbitronFontFamily = (FontFamily)Application.Current.Resources["Orbitron"];
var gemunuFontFamily = (FontFamily)Application.Current.Resources["Gemunu"];
// Create a new TextBlock for each Death
var killTextBlock = new TextBlock
{
Margin = new Thickness(0, 10, 0, 10),
Style = (Style)Application.Current.Resources["RoundedTextBlock"], // Apply style for text
FontSize = 14,
FontWeight = FontWeights.Bold,
FontFamily = gemunuFontFamily,
};
// Add styled content using Run elements
killTextBlock.Inlines.Add(new Run("Event Type: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run("Death\n"));
// Repeat for other lines
killTextBlock.Inlines.Add(new Run("Agressor Name: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[1]}\n"));
killTextBlock.Inlines.Add(new Run("Agressor Ship: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[2]}\n"));
killTextBlock.Inlines.Add(new Run("Agressor Org: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[3]}\n"));
killTextBlock.Inlines.Add(new Run("Join Date: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[4]}\n"));
killTextBlock.Inlines.Add(new Run("UEE Record: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[5]}\n"));
killTextBlock.Inlines.Add(new Run("Death Time: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[6]}"));
// Create a Border and apply the RoundedTextBlockWithBorder style
var killBorder = new Border
{
Style = (Style)Application.Current.Resources["RoundedTextBlockWithBorder"], // Apply border style
};
// Create a Grid to hold the TextBlock and the Image
var killGrid = new Grid
{
Width = 400, // Adjust the width of the Grid
Height = 150, // Adjust the height as needed
};
// Define two columns in the Grid: one for the text and one for the image
killGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(3, GridUnitType.Star) }); // Text column
killGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Auto) }); // Image column
// Add the TextBlock to the first column of the Grid
Grid.SetColumn(killTextBlock, 0);
killGrid.Children.Add(killTextBlock);
// Create the Image for the profile
var profileImage = new Image
{
Source = new BitmapImage(new Uri(killParts[7])), // Assuming the 8th part contains the profile image URL
Width = 90,
Height = 90,
Stretch = Stretch.Fill, // Adjust how the image fits
};
// Create a Border around the Image
var imageBorder = new Border
{
BorderBrush = accentColorBrush, // Set the border color
BorderThickness = new Thickness(2), // Set the border thickness
Padding = new Thickness(0), // Optional padding inside the border
CornerRadius = new CornerRadius(5),
Margin = new Thickness(10,18,15,18),
Child = profileImage // Set the Image as the content of the Border
};
// Add the Border (with the image inside) to the Grid
Grid.SetColumn(imageBorder, 1);
killGrid.Children.Add(imageBorder);
// Set the Grid as the child of the Border
killBorder.Child = killGrid;
// Add the new Border to the StackPanel inside the Border
KillFeedStackPanel.Children.Insert(0, killBorder);
}
else if (e.Data.Contains("NewOther="))
{
// Parse the death data
var killData = e.Data.Split('=')[1].Trim(); // Assume the death data follows after "NewKill="
var killParts = killData.Split(',');
// Fetch the dynamic resource for AltTextColor
var altTextColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AltTextColor"]);
var accentColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AccentColor"]);
// Fetch the Orbitron FontFamily from resources
var orbitronFontFamily = (FontFamily)Application.Current.Resources["Orbitron"];
var gemunuFontFamily = (FontFamily)Application.Current.Resources["Gemunu"];
// Create a new TextBlock for each Death
var killTextBlock = new TextBlock
{
Margin = new Thickness(0, 10, 0, 10),
Style = (Style)Application.Current.Resources["RoundedTextBlock"], // Apply style for text
FontSize = 14,
FontWeight = FontWeights.Bold,
FontFamily = gemunuFontFamily,
};
// Add styled content using Run elements
killTextBlock.Inlines.Add(new Run("Event Type: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run("Other\n"));
killTextBlock.Inlines.Add(new Run("Death by: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[1]}\n"));
// Repeat for other lines
killTextBlock.Inlines.Add(new Run("Sueside Time: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killParts[2]}"));
// Create a Border and apply the RoundedTextBlockWithBorder style
var killBorder = new Border
{
Style = (Style)Application.Current.Resources["RoundedTextBlockWithBorder"], // Apply border style
};
// Create a Grid to hold the TextBlock and the Image
var killGrid = new Grid
{
Width = 400, // Adjust the width of the Grid
Height = 70, // Adjust the height as needed
};
// Define two columns in the Grid: one for the text and one for the image
killGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(3, GridUnitType.Star) }); // Text column
// Add the TextBlock to the first column of the Grid
Grid.SetColumn(killTextBlock, 0);
killGrid.Children.Add(killTextBlock);
// Set the Grid as the child of the Border
killBorder.Child = killGrid;
// Add the new Border to the StackPanel inside the Border
KillFeedStackPanel.Children.Insert(0, killBorder);
}
else else
{ {
@ -291,7 +509,9 @@ namespace AutoTrackR2
PilotNameTextBox.Text = string.Empty; PilotNameTextBox.Text = string.Empty;
PlayerShipTextBox.Text = string.Empty; PlayerShipTextBox.Text = string.Empty;
GameModeTextBox.Text = string.Empty; GameModeTextBox.Text = string.Empty;
KillTallyTextBox.Text = string.Empty; KillTallyTextBox.Text = "K";
DeathTallyTextBox.Text = "D";
OtherTallyTextBox.Text = "O";
KillFeedStackPanel.Children.Clear(); KillFeedStackPanel.Children.Clear();
} }

View file

@ -1,4 +1,4 @@
$TrackRver = "2.06" $TrackRver = "2.06-mod"
# Path to the config file # Path to the config file
$appName = "AutoTrackR2" $appName = "AutoTrackR2"
@ -30,6 +30,9 @@ $videoPath = $config.VideoPath
$visorWipe = $config.VisorWipe $visorWipe = $config.VisorWipe
$videoRecord = $config.VideoRecord $videoRecord = $config.VideoRecord
$offlineMode = $config.OfflineMode $offlineMode = $config.OfflineMode
$killLog = $config.KillLog
$deathLog = $config.DeathLog
$otherLog = $config.OtherLog
if ($offlineMode -eq 1){ if ($offlineMode -eq 1){
$offlineMode = $true $offlineMode = $true
@ -69,6 +72,27 @@ If ($null -ne $apiUrl){
Write-output "PlayerName=$apiURL" Write-output "PlayerName=$apiURL"
} }
if ($killLog -eq 1){
$killLog = $true
} else {
$killLog = $false
}
Write-Output "PlayerName=KillLog: $killLog"
if ($deathLog -eq 1){
$deathLog = $true
} else {
$deathLog = $false
}
Write-Output "PlayerName=DeathLog: $deathLog"
if ($otherLog -eq 1){
$otherLog = $true
} else {
$otherLog = $false
}
Write-Output "PlayerName=OtherLog: $otherLog"
# Ship Manufacturers # Ship Manufacturers
$prefixes = @( $prefixes = @(
"ORIG", "ORIG",
@ -92,7 +116,7 @@ $prefixes = @(
) )
# Define the regex pattern to extract information # 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>[^']+)'" $killPattern = "<Actor Death> CActor::Kill: '(?<VictimPilot>[^']+)' \[\d+\] in zone '(?<VictimShip>[^']+)' killed by '(?<AgressorPilot>[^']+)' \[[^']+\] 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=[^ ]+ status="Finished" runningTime=\d+\.\d+ numRuns=\d+ map="megamap" gamerules="SC_Default" sessionId="[a-f0-9\-]+" \[Team_Network\]\[Network\]\[Replication\]\[Loading\]\[Persistence\]' $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=[^ ]+ status="Finished" runningTime=\d+\.\d+ numRuns=\d+ map="megamap" gamerules="SC_Default" sessionId="[a-f0-9\-]+" \[Team_Network\]\[Network\]\[Replication\]\[Loading\]\[Persistence\]'
$acPattern = "ArenaCommanderFeature" $acPattern = "ArenaCommanderFeature"
$loadoutPattern = '\[InstancedInterior\] OnEntityLeaveZone - InstancedInterior \[(?<InstancedInterior>[^\]]+)\] \[\d+\] -> Entity \[(?<Entity>[^\]]+)\] \[\d+\] -- m_openDoors\[\d+\], m_managerGEID\[(?<ManagerGEID>\d+)\], m_ownerGEID\[(?<OwnerGEID>[^\[]+)\]' $loadoutPattern = '\[InstancedInterior\] OnEntityLeaveZone - InstancedInterior \[(?<InstancedInterior>[^\]]+)\] \[\d+\] -> Entity \[(?<Entity>[^\]]+)\] \[\d+\] -- m_openDoors\[\d+\], m_managerGEID\[(?<ManagerGEID>\d+)\], m_ownerGEID\[(?<OwnerGEID>[^\[]+)\]'
@ -112,28 +136,94 @@ $vehiclePattern = "<(?<timestamp>[^>]+)> \[Notice\] <Vehicle Destruction> CVehic
$joinDatePattern = '<span class="label">Enlisted</span>\s*<strong class="value">([^<]+)</strong>' $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>' $ueePattern = '<p class="entry citizen-record">\s*<span class="label">UEE Citizen Record<\/span>\s*<strong class="value">#?(n\/a|\d+)<\/strong>\s*<\/p>'
#csv variables
$CSVPath = "$scriptFolder\Kill-log.csv"
$CSVBackupPath = "$scriptFolder\_backup_Kill-log.csv"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$process = Get-Process | Where-Object {$_.Name -like "AutoTrackR2"} $process = Get-Process | Where-Object {$_.Name -like "AutoTrackR2"}
$global:killTally = 0 $global:killTally = 0
$global:deathTally = 0
$global:otherTally = 0
# Load historic kills from csv # Load historic data from csv
if (Test-Path "$scriptFolder\Kill-Log.csv") { if (Test-Path $CSVPath) {
$historicKills = Import-CSV "$scriptFolder\Kill-log.csv" $historicKills = Import-CSV $CSVPath
$currentDate = Get-Date $currentDate = Get-Date
$dateFormat = "dd MMM yyyy HH:mm UTC" $dateFormat = "dd MMM yyyy HH:mm UTC"
#Convert old csv to new
if($null -eq $($historicKills.Type)){
#Move old file to a Backup
Move-Item $csvPath $csvBackupPath
#now convert Backup to new File
foreach ($row in $historicKills) {
$csvData = [PSCustomObject]@{
Type = "Kill"
KillTime = $($row.KillTime)
EnemyPilot = $($row.EnemyPilot)
EnemyShip = $($row.EnemyShip)
Enlisted = $($row.Enlisted)
RecordNumber = $($row.RecordNumber)
OrgAffiliation = $($row.OrgAffiliation)
Player = $($row.Player)
Weapon = $($row.Weapon)
Ship = $($row.Ship)
Method = $($row.Method)
Mode = $($row.Mode)
GameVersion = $($row.GameVersion)
TrackRver = $($row.TrackRver)
Logged = $($row.Logged)
PFP = $($row.PFP)
}
if ($killLog -eq $true -or $deathLog -eq $true -or $otherLog -eq $true) {
# Export to CSV
if (-Not (Test-Path $CSVPath)) {
# If file doesn't exist, create it with headers
$csvData | Export-Csv -Path $CSVPath -NoTypeInformation
} else {
# Append data to the existing file without adding headers
$csvData | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append -Encoding utf8 -FilePath $CSVPath
}
}
}
#load new File
$historicKills = Import-CSV $CSVPath
}
foreach ($kill in $historicKills) { foreach ($kill in $historicKills) {
$killDate = [datetime]::ParseExact($kill.KillTime.Trim(), $dateFormat, [System.Globalization.CultureInfo]::InvariantCulture) $killDate = [datetime]::ParseExact($kill.KillTime.Trim(), $dateFormat, [System.Globalization.CultureInfo]::InvariantCulture)
If ($killdate.year -eq $currentDate.Year -and $killdate.month -eq $currentDate.Month) { If ($killdate.year -eq $currentDate.Year -and $killdate.month -eq $currentDate.Month) {
$global:killTally++ IF ($kill.type -eq "Kill" -and $killLog -eq $true){
} $global:killTally++
Try { Try {
Write-Output "NewKill=throwaway,$($kill.EnemyPilot),$($kill.EnemyShip),$($kill.OrgAffiliation),$($kill.Enlisted),$($kill.RecordNumber),$($kill.KillTime), $($kill.PFP)" Write-Output "NewKill=throwaway,$($kill.EnemyPilot),$($kill.EnemyShip),$($kill.OrgAffiliation),$($kill.Enlisted),$($kill.RecordNumber),$($kill.KillTime), $($kill.PFP)"
} Catch { } Catch {
Write-Output "Error Loading Kill: $($kill.EnemyPilot)" Write-Output "Error Loading Kill: $($kill.EnemyPilot)"
}
}elseif($kill.type -eq "Death" -and $deathLog -eq $true){
$global:deathTally++
Try {
Write-Output "NewDeath=throwaway,$($kill.EnemyPilot),$($kill.EnemyShip),$($kill.OrgAffiliation),$($kill.Enlisted),$($kill.RecordNumber),$($kill.KillTime), $($kill.PFP)"
} Catch {
Write-Output "Error Loading Death: $($kill.EnemyPilot)"
}
}elseif($otherLog -eq $true){
$global:otherTally++
Try {
Write-Output "NewOther=throwaway,$($kill.Method),$($kill.KillTime)"
} Catch {
Write-Output "Error Loading Other: $($kill.Method)"
}
}
} }
} }
} }
Write-Output "KillTally=$global:killTally" Write-Output "KillTally=$global:killTally"
Write-Output "DeathTally=$global:deathTally"
Write-Output "OtherTally=$global:otherTally"
# Match and extract username from gamelog # Match and extract username from gamelog
Do { Do {
@ -142,7 +232,7 @@ Do {
# Initialize variable to store username # Initialize variable to store username
$global:userName = $null $global:userName = $null
$global:loadout = "Player" $global:loadout = "Person"
# Loop through each line in the log to find the matching line # Loop through each line in the log to find the matching line
foreach ($line in $authLog) { foreach ($line in $authLog) {
@ -165,10 +255,11 @@ Do {
} }
} }
Write-Output "PlayerShip=$global:loadOut" Write-Output "PlayerShip=$global:loadOut"
#Get SC Version
If ($line -match $versionPattern){ If ($line -match $versionPattern){
$global:GameVersion = $matches['gameversion'] $global:GameVersion = $matches['gameversion']
} }
#Get Game Mode
if ($line -match $acPattern){ if ($line -match $acPattern){
$global:GameMode = "AC" $global:GameMode = "AC"
} }
@ -188,31 +279,30 @@ Do {
$authLog = $null $authLog = $null
} until ($null -ne $global:userName) } until ($null -ne $global:userName)
# Function to process new log entries and write to the host # Function to process new log entries and write to the host
function Read-LogEntry { function Read-LogEntry {
param ( param (
[string]$line [string]$line
) )
# Look for vehicle events # Look for vehicle events
if ($line -match $vehiclePattern) { if ($line -match $vehiclePattern) {
# Access the named capture groups from the regex match # Access the named capture groups from the regex match
$global:vehicle_id = $matches['vehicle'] $global:vehicle_id = $matches['vehicle']
$global:location = $matches['vehicle_zone'] $global:location = $matches['vehicle_zone']
} }
# Apply the regex pattern to the line # Apply the regex pattern to the line
if ($line -match $killPattern) { if ($line -match $killPattern) {
# Access the named capture groups from the regex match # Access the named capture groups from the regex match
$enemyPilot = $matches['EnemyPilot'] $victimPilot = $matches['VictimPilot']
$enemyShip = $matches['EnemyShip'] $victimShip = $matches['VictimShip']
$player = $matches['Player'] $agressorPilot = $matches['AgressorPilot']
$weapon = $matches['Weapon'] $weapon = $matches['Weapon']
$damageType = $matches['DamageType'] $damageType = $matches['DamageType']
$ship = $global:loadOut $ship = $global:loadOut
If ($enemyShip -ne "vehicle_id"){ If ($victimShip -ne "vehicle_id"){
$global:got_location = $location $global:got_location = $location
} }
@ -221,66 +311,88 @@ function Read-LogEntry {
$global:got_location = "NONE" $global:got_location = "NONE"
} }
Try { #Define the Type
$page1 = Invoke-WebRequest -uri "https://robertsspaceindustries.com/citizens/$enemyPilot" IF ($agressorPilot -eq $global:userName -and $victimPilot -ne $global:userName){
} Catch { $type = "Kill"
$page1 = $null Try {
$page1 = Invoke-WebRequest -uri "https://robertsspaceindustries.com/citizens/$victimPilot"
} Catch {
$page1 = $null
$type = "none"
}
}elseif ($agressorPilot -ne $global:userName -and $victimPilot -eq $global:userName) {
$type = "Death"
$victimShip = "unknown"
Try {
$page1 = Invoke-WebRequest -uri "https://robertsspaceindustries.com/citizens/$agressorPilot"
} Catch {
$page1 = $null
$type = "none"
}
}elseif($agressorPilot -eq $global:userName -or $victimPilot -eq $global:userName) {
$type = "Other"
}else {
$type = "none"
} }
If ($null -ne $page1){ if ($type -ne "none") {
# Check if the Autotrackr2 process is running # Check if the Autotrackr2 process is running
if ($null -eq (Get-Process -ID $parentApp -ErrorAction SilentlyContinue)) { if ($null -eq (Get-Process -ID $parentApp -ErrorAction SilentlyContinue)) {
Stop-Process -Id $PID -Force Stop-Process -Id $PID -Force
} }
If ($enemyShip -ne "Player"){
If ($enemyShip -eq $global:lastKill){ If ($victimShip -ne "Person"){
$enemyShip = "Passenger" If ($victimShip -eq $global:lastKill){
$victimShip = "Passenger"
} Else { } Else {
$global:lastKill = $enemyShip $global:lastKill = $victimShip
} }
} }
If ($player -eq $global:userName -and $enemyPilot -ne $global:userName){ If ($victimShip -match $cleanupPattern){
If ($enemyShip -match $cleanupPattern){ $victimShip = $matches[1]
$enemyShip = $matches[1] }
} If ($weapon -match $cleanupPattern){
If ($weapon -match $cleanupPattern){ $weapon = $matches[1]
$weapon = $matches[1] }
} If ($weapon -eq "KLWE_MassDriver_S10"){
If ($weapon -eq "KLWE_MassDriver_S10"){ if ($type -eq "Kill"){
$global:loadOut = "AEGS_Idris" $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)$', ''
} }
$ship = "AEGS_Idris"
}
if ($damageType -eq "Bullet" -or $weapon -like "apar_special_ballistic*") {
$ship = "Person"
$victimShip = "Person"
}
If ($ship -match $cleanupPattern){
$ship = $matches[1]
}
if ($ship -notmatch $shipManPattern){
$ship = "Person"
}
If ($victimShip -notmatch $shipManPattern -and $victimShip -notlike "Passenger" ) {
$victimShip = "Person"
}
# Repeatedly remove all suffixes
while ($victimShip -match '_(PU|AI|CIV|MIL|PIR)$') {
$victimShip = $victimShip -replace '_(PU|AI|CIV|MIL|PIR)$', ''
}
while ($ship -match '_(PU|AI|CIV|MIL|PIR)$') {
$ship = $ship -replace '_(PU|AI|CIV|MIL|PIR)$', ''
}
while ($victimShip -match '-00(1|2|3|4|5|6|7|8|9|0)$') {
$victimShip = $victimShip -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) $KillTime = (Get-Date).ToUniversalTime().ToString("dd MMM yyyy HH:mm 'UTC'", [System.Globalization.CultureInfo]::InvariantCulture)
#If get Enemy Player data
If ($null -ne $page1){
# Get Enlisted Date # Get Enlisted Date
if ($($page1.content) -match $joinDatePattern) { if ($($page1.content) -match $joinDatePattern) {
$joinDate = $matches[1] $joinDate = $matches[1]
@ -296,10 +408,6 @@ function Read-LogEntry {
$enemyOrgs = $page1.links[3].innerHTML $enemyOrgs = $page1.links[3].innerHTML
} }
if ($null -eq $enemyOrgs) {
$enemyOrgs = "-"
}
# Get UEE Number # Get UEE Number
if ($($page1.content) -match $ueePattern) { if ($($page1.content) -match $ueePattern) {
# The matched UEE Citizen Record number is in $matches[1] # The matched UEE Citizen Record number is in $matches[1]
@ -316,67 +424,64 @@ function Read-LogEntry {
# Get PFP # Get PFP
if ($page1.images[0].src -like "/media/*") { if ($page1.images[0].src -like "/media/*") {
$victimPFP = "https://robertsspaceindustries.com$($page1.images[0].src)" $enemyPFP = "https://robertsspaceindustries.com$($page1.images[0].src)"
} Else { } Else {
$victimPFP = "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg" $enemyPFP = "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg"
}
}
$global:GameMode = $global:GameMode.ToLower()
# Send to API (Kill only)
# Define the data to send
If ($null -ne $apiUrl -and $offlineMode -eq $false -and $type -eq "Kill"){
$data = @{
victim_ship = $victimShip
victim = $victimPilot
enlisted = $joinDate
rsi = $citizenRecordAPI
weapon = $weapon
method = $damageType
loadout_ship = $ship
game_version = $global:GameVersion
gamemode = $global:GameMode
trackr_version = $TrackRver
location = $got_location
} }
$global:killTally++ # Headers which may or may not be necessary
Write-Output "KillTally=$global:killTally" $headers = @{
Write-Output "NewKill=throwaway,$enemyPilot,$enemyShip,$enemyOrgs,$joinDate2,$citizenRecord,$killTime,$victimPFP" "Authorization" = "Bearer $apiKey"
"Content-Type" = "application/json"
$global:GameMode = $global:GameMode.ToLower() "User-Agent" = "AutoTrackR2"
# 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"
} }
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 #process Kill data
$csvPath = "$scriptFolder\Kill-log.csv" if ($type -eq "Kill" -and $killLog -eq $true) {
# Create an object to hold the data for a kill
# Create an object to hold the data $csvData = [PSCustomObject]@{
$killData = [PSCustomObject]@{ Type = $type
KillTime = $killTime KillTime = $killTime
EnemyPilot = $enemyPilot EnemyPilot = $victimPilot
EnemyShip = $enemyShip EnemyShip = $victimShip
Enlisted = $joinDate2 Enlisted = $joinDate2
RecordNumber = $citizenRecord RecordNumber = $citizenRecord
OrgAffiliation = $enemyOrgs OrgAffiliation = $enemyOrgs
Player = $player Player = $agressorPilot
Weapon = $weapon Weapon = $weapon
Ship = $ship Ship = $ship
Method = $damageType Method = $damageType
@ -384,29 +489,100 @@ function Read-LogEntry {
GameVersion = $global:GameVersion GameVersion = $global:GameVersion
TrackRver = $TrackRver TrackRver = $TrackRver
Logged = $logMode Logged = $logMode
PFP = $victimPFP PFP = $enemyPFP
} }
# Remove commas from all properties # Remove commas from all properties
foreach ($property in $killData.PSObject.Properties) { foreach ($property in $csvData.PSObject.Properties) {
if ($property.Value -is [string]) { if ($property.Value -is [string]) {
$property.Value = $property.Value -replace ',', '' $property.Value = $property.Value -replace ',', ''
} }
}
#write Kill
$global:killTally++
Write-Output "KillTally=$global:killTally"
Write-Output "NewKill=throwaway,$victimPilot,$victimShip,$enemyOrgs,$joinDate2,$citizenRecord,$killTime,$enemyPFP"
#process Death data
} elseif ($type -eq "Death" -and $deathLog -eq $true) {
# Create an object to hold the data for a death
$csvData = [PSCustomObject]@{
Type = $type
KillTime = $killTime
EnemyPilot = $agressorPilot
EnemyShip = $ship
Enlisted = $joinDate2
RecordNumber = $citizenRecord
OrgAffiliation = $enemyOrgs
Player = $victimPilot
Weapon = $weapon
Ship = $victimShip
Method = $damageType
Mode = $global:GameMode
GameVersion = $global:GameVersion
TrackRver = $TrackRver
Logged = $logMode
PFP = $enemyPFP
} }
# Remove commas from all properties
foreach ($property in $csvData.PSObject.Properties) {
if ($property.Value -is [string]) {
$property.Value = $property.Value -replace ',', ''
}
}
#write Death
$global:deathTally++
Write-Output "DeathTally=$global:deathTally"
Write-Output "NewDeath=throwaway,$agressorPilot,$ship,$enemyOrgs,$joinDate2,$citizenRecord,$killTime,$enemyPFP"
#process Other data
} elseif ($type -eq "Other" -and $otherLog -eq $true) {
# Create an object to hold the data for a other
$csvData = [PSCustomObject]@{
Type = $type
KillTime = $killTime
EnemyPilot = ""
EnemyShip = ""
Enlisted = ""
RecordNumber = ""
OrgAffiliation = ""
Player = $global:userName
Weapon = $weapon
Ship = $victimShip
Method = $damageType
Mode = $global:GameMode
GameVersion = $global:GameVersion
TrackRver = $TrackRver
Logged = $logMode
PFP = ""
}
# Remove commas from all properties
foreach ($property in $csvData.PSObject.Properties) {
if ($property.Value -is [string]) {
$property.Value = $property.Value -replace ',', ''
}
}
#write Other
$global:otherTally++
Write-Output "OtherTally=$global:otherTally"
Write-Output "NewOther=throwaway,$damageType,$killTime"
}
if ($killLog -eq $true -or $deathLog -eq $true -or $otherLog -eq $true) {
# Export to CSV # Export to CSV
if (-Not (Test-Path $csvPath)) { if (-Not (Test-Path $CSVPath)) {
# If file doesn't exist, create it with headers # If file doesn't exist, create it with headers
$killData | Export-Csv -Path $csvPath -NoTypeInformation $csvData | Export-Csv -Path $CSVPath -NoTypeInformation
} else { } else {
# Append data to the existing file without adding headers # Append data to the existing file without adding headers
$killData | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append -Encoding utf8 -FilePath $csvPath $csvData | ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Out-File -Append -Encoding utf8 -FilePath $CSVPath
} }
$sleeptimer = 10 $sleeptimer = 10
# VisorWipe # VisorWipe
If ($visorwipe -eq $true -and $enemyShip -ne "Passenger" -and $damageType -notlike "*Bullet*"){ If ($visorWipe -eq $true -and $victimShip -ne "Passenger" -and $damageType -notlike "*Bullet*" -and $type -ne "Other"){
# send keybind for visorwipe # send keybind for visorwipe
start-sleep 1 start-sleep 1
$sleeptimer = $sleeptimer -1 $sleeptimer = $sleeptimer -1
@ -414,7 +590,7 @@ function Read-LogEntry {
} }
# Record video # Record video
if ($videoRecord -eq $true -and $enemyShip -ne "Passenger"){ if ($videoRecord -eq $true -and $victimShip -ne "Passenger" -and $damageType -ne "Suicide"){
# send keybind for windows game bar recording # send keybind for windows game bar recording
Start-Sleep 2 Start-Sleep 2
$sleeptimer = $sleeptimer -9 $sleeptimer = $sleeptimer -9
@ -428,19 +604,19 @@ function Read-LogEntry {
if ($fileAgeInSeconds -le 30) { if ($fileAgeInSeconds -le 30) {
# Generate a timestamp in ddMMMyyyy-HH:mm format # Generate a timestamp in ddMMMyyyy-HH:mm format
$timestamp = (Get-Date).ToString("ddMMMyyyy-HHmm") $timestamp = (Get-Date).ToString("ddMMMyyyy-HHmm")
# Extract the file extension to preserve it # Extract the file extension to preserve it
$fileExtension = $latestFile.Extension $fileExtension = $latestFile.Extension
# Rename the file, preserving the original file extension # Rename the file, preserving the original file extension
Rename-Item -Path $latestFile.FullName -NewName "$enemyPilot.$enemyShip.$timestamp$fileExtension" Rename-Item -Path $latestFile.FullName -NewName "$type.$victimPilot.$victimShip.$timestamp$fileExtension"
} else {} } else {}
} else {} } else {}
} }
Start-Sleep $sleeptimer Start-Sleep $sleeptimer
} }
} }
} }
# Get Logged-in User # Get Logged-in User
If ($line -match $loginPattern) { If ($line -match $loginPattern) {
@ -483,7 +659,6 @@ function Read-LogEntry {
} }
} }
# Monitor the log file and process new lines as they are added # Monitor the log file and process new lines as they are added
Get-Content -Path $logFilePath -Wait -Tail 0 | ForEach-Object { Get-Content -Path $logFilePath -Wait -Tail 0 | ForEach-Object {
Read-LogEntry $_ Read-LogEntry $_
@ -517,4 +692,4 @@ finally {
$reader.Close() $reader.Close()
$fileStream.Close() $fileStream.Close()
} }
#> #>

View file

@ -187,6 +187,9 @@ namespace AutoTrackR2
ConfigManager.VisorWipe, ConfigManager.VisorWipe,
ConfigManager.VideoRecord, ConfigManager.VideoRecord,
ConfigManager.OfflineMode, ConfigManager.OfflineMode,
ConfigManager.KillLog,
ConfigManager.DeathLog,
ConfigManager.OtherLog,
ConfigManager.Theme ConfigManager.Theme
); );
} }
@ -201,6 +204,9 @@ namespace AutoTrackR2
public static int VisorWipe { get; set; } public static int VisorWipe { get; set; }
public static int VideoRecord { get; set; } public static int VideoRecord { get; set; }
public static int OfflineMode { get; set; } public static int OfflineMode { get; set; }
public static int KillLog { get; set; }
public static int DeathLog { get; set; }
public static int OtherLog { get; set; }
public static int Theme { get; set; } public static int Theme { get; set; }
public static void LoadConfig() public static void LoadConfig()
@ -230,6 +236,12 @@ namespace AutoTrackR2
VideoRecord = int.Parse(line.Substring("VideoRecord=".Length).Trim()); VideoRecord = int.Parse(line.Substring("VideoRecord=".Length).Trim());
else if (line.StartsWith("OfflineMode=")) else if (line.StartsWith("OfflineMode="))
OfflineMode = int.Parse(line.Substring("OfflineMode=".Length).Trim()); OfflineMode = int.Parse(line.Substring("OfflineMode=".Length).Trim());
else if (line.StartsWith("KillLog="))
KillLog = int.Parse(line.Substring("KillLog=".Length).Trim());
else if (line.StartsWith("DeathLog="))
DeathLog = int.Parse(line.Substring("DeathLog=".Length).Trim());
else if (line.StartsWith("OtherLog="))
OtherLog = int.Parse(line.Substring("OtherLog=".Length).Trim());
else if (line.StartsWith("Theme=")) else if (line.StartsWith("Theme="))
Theme = int.Parse(line.Substring("Theme=".Length).Trim()); Theme = int.Parse(line.Substring("Theme=".Length).Trim());
} }
@ -262,6 +274,9 @@ namespace AutoTrackR2
writer.WriteLine($"VisorWipe={VisorWipe}"); writer.WriteLine($"VisorWipe={VisorWipe}");
writer.WriteLine($"VideoRecord={VideoRecord}"); writer.WriteLine($"VideoRecord={VideoRecord}");
writer.WriteLine($"OfflineMode={OfflineMode}"); writer.WriteLine($"OfflineMode={OfflineMode}");
writer.WriteLine($"KillLog={KillLog}");
writer.WriteLine($"DeathLog={DeathLog}");
writer.WriteLine($"OtherLog={OtherLog}");
writer.WriteLine($"Theme={Theme}"); writer.WriteLine($"Theme={Theme}");
} }
} }

View file

@ -9,7 +9,7 @@ namespace AutoTrackR2
{ {
public partial class UpdatePage : UserControl public partial class UpdatePage : UserControl
{ {
private string currentVersion = "v2.06-stable"; private string currentVersion = "v2.06-mod";
private string latestVersion; private string latestVersion;
public UpdatePage() public UpdatePage()
@ -86,8 +86,8 @@ namespace AutoTrackR2
private bool IsNewVersionAvailable(string currentVersion, string latestVersion) private bool IsNewVersionAvailable(string currentVersion, string latestVersion)
{ {
// Return true if the versions are different // Compare version strings (you can implement more complex version parsing logic if needed)
return !currentVersion.Equals(latestVersion, StringComparison.Ordinal); return string.Compare(currentVersion, latestVersion, StringComparison.Ordinal) < 0;
} }
private async void InstallButton_Click(object sender, RoutedEventArgs e) private async void InstallButton_Click(object sender, RoutedEventArgs e)

View file

@ -4,5 +4,8 @@ ApiKey=
VideoPath= VideoPath=
VisorWipe=0 VisorWipe=0
VideoRecord=0 VideoRecord=0
OfflineMode=0 OfflineMode=1
Theme=0 KillLog=1
DeathLog=0
OtherLog=0
Theme=0

View file

@ -2,14 +2,14 @@ AutoTrackR2 - Star Citizen Kill-Tracking Tool
AutoTrackR2 is a powerful and customizable kill-tracking tool for Star Citizen. Designed with gankers and combat enthusiasts in mind, it integrates seamlessly with the game to log, display, and manage your kills, providing detailed information and optional API integration for advanced tracking. AutoTrackR2 is a powerful and customizable kill-tracking tool for Star Citizen. Designed with gankers and combat enthusiasts in mind, it integrates seamlessly with the game to log, display, and manage your kills, providing detailed information and optional API integration for advanced tracking.
🚀 Features 🚀 Features
Log File Integration: Point to Star Citizen's live game.log to track kills in real-time. Log File Integration: Point to Star Citizen's live game.log to track kills, death and other way's to die, in real-time.
API Integration (Optional): API Integration (Optional):
Configure a desired API to send kill data for external tracking or display. Configure a desired API to send kill data for external tracking or display.
Secure your data with an optional API key. Secure your data with an optional API key.
Video Clipping (Optional): Video Clipping (Optional):
Set a path to your clipping software to save kills automatically. Set a path to your clipping software to save log events except suicides automatically.
Visor Wipe Integration: Visor Wipe Integration:
Automates visor wiping using an AutoHotkey script (visorwipe.ahk). Automates visor wiping using an AutoHotkey script (visorwipe.ahk).
@ -53,6 +53,21 @@ AutoHotkey v2 is required.
Offline Mode: Offline Mode:
Enable to disable API submission. Restart the tracker to apply changes. Enable to disable API submission. Restart the tracker to apply changes.
KillLog:
Enable to disable the log of a Kill event.
There will also no wipe or Video Recording if disabled.
DeathLog:
Enable to disable the log of a Death event.
There will also no wipe or Video Recording if disabled.
OtherLog:
Enable to disable the log of a Oter way to die event.
There will also no wipe or Video Recording if disabled.
Suicide event will never be Recorded.
🛡️ Privacy & Data Usage 🛡️ Privacy & Data Usage
No Personal Data Collection: No Personal Data Collection:
AutoTrackR2 does not collect or store personal or system information, other than common file paths to manage necessary files. AutoTrackR2 does not collect or store personal or system information, other than common file paths to manage necessary files.
@ -71,6 +86,9 @@ Download the latest release from the releases page.
Follow the setup instructions included in the installer. Follow the setup instructions included in the installer.
Configure the tool using the settings outlined above. Configure the tool using the settings outlined above.
❗Update
Log-Files 2.06-stable and older will be automatically backup into _backup_Kill-log.csv and converted.
💡 Customization 💡 Customization
To customize themes or behaviors: To customize themes or behaviors: