Compare commits

...

32 commits

Author SHA1 Message Date
Dork Normalize
90d24b4d9b Fix initialization logic 2025-04-06 19:28:24 -07:00
Dork Normalize
82484a6a27 Merge branch 'default' of https://github.com/DorkNormalize/AutoTrackR2 into default 2025-04-06 18:59:59 -07:00
Dork Normalize
3afa615bac Fix feezy theme 2025-04-06 18:59:55 -07:00
Heavy Bob
e28fc836e7 Added unix timestamp to webhandler and consonsole writes. 2025-04-07 11:58:59 +10:00
Dork Normalize
2dcf2e3571 Remove Update and Stats page. Fix Feezy theme. 2025-04-06 18:34:04 -07:00
Dork Normalize
4059eba481 Nuke the installer and update ps1 2025-04-06 18:15:10 -07:00
DorkNormalize
f8849daa79
Merge pull request from DorkNormalize/bob-fork
Bob fork
2025-04-06 18:11:42 -07:00
DorkNormalize
3728de39ac
Merge pull request from DorkNormalize/bob-rez-changes
Fix borked merge conflict resolution
2025-04-06 18:09:06 -07:00
Dork Normalize
5b9a9b925f Fix borked merge conflict resolution 2025-04-06 18:07:23 -07:00
DorkNormalize
7f7be269b0
Merge branch 'default' into bob-fork 2025-04-06 17:59:18 -07:00
Heavy Bob
1acae27793 Fixed all the cursed warnings when building.
Fixed all the values that can be nullable on the client.
2025-04-07 10:18:52 +10:00
Heavy Bob
2cd80970a4 Removed Buttons, fixed application detect + other stuff
When attempting to run the app and close, it wouldn't actually close...
Set default states when starcitizen isn't running to unknown.
Start reading file when starcitizen is detected. Stop when starcitizen isn't running.

Issue, Need to fix reading file when game is already running.
2025-04-07 10:11:12 +10:00
Heavy Bob
0593969f77 Fixed save button on config page going off the page. 2025-04-07 09:29:23 +10:00
Heavy Bob
c2cdd2a6a1 Added Kill Tally for current month. 2025-04-07 09:27:00 +10:00
Heavy Bob
f116793591 Fixed Theme's not being applied correctly
Sometimes when switching themes it wouldn't apply the theme correctly.
2025-04-07 09:20:13 +10:00
Heavy Bob
5fc670b652 Sync'd Reznoks changes 2025-04-07 08:44:42 +10:00
Dork Normalize
666b5ce11f Varius bug fixes 2025-04-06 15:04:09 -07:00
BubbaGumpShrump
2a4a4ebe42 Merge branch 'default' of https://github.com/BubbaGumpShrump/AutoTrackR2 into 2.07 2025-04-05 10:38:32 -04:00
BubbaGumpShrump
82b9e365c1
Merge pull request from Heavybob/default
Updated Readme and added Git Actions
2025-04-05 10:38:07 -04:00
Heavy Bob
408c071a85 Updated Readme. 2025-04-06 00:13:38 +11:00
Heavy Bob
bab96123c5 Added autohotkey scripts to artifacts 2025-04-06 00:11:12 +11:00
Heavy Bob
a09a99c064 Added autohotkey scripts to artifact 2025-04-06 00:06:04 +11:00
Heavy Bob
bd8bbfb365 Added version to git actions. 2025-04-05 23:21:09 +11:00
Heavy Bob
49dfbb2291 debugging 2025-04-05 23:17:29 +11:00
Heavy Bob
dfc2dd5477 Use correct net framework. 2025-04-05 23:15:25 +11:00
Heavy Bob
e2df69526d Git actions v4 2025-04-05 23:12:03 +11:00
Heavy Bob
1236f8b4d6 Merge branch 'default' of https://github.com/Heavybob/AutoTrackR2 into default 2025-04-05 23:09:16 +11:00
Heavy Bob
b680debb49 Main branch is default not main 2025-04-05 23:09:14 +11:00
Heavy Bob
e5f968633d
Merge branch 'BubbaGumpShrump:default' into default 2025-04-05 23:03:35 +11:00
Heavy Bob
4a001801aa Added git actions 2025-04-05 23:02:42 +11:00
BubbaGumpShrump
388b1b774e Merge branch 'default' of https://github.com/BubbaGumpShrump/AutoTrackR2 into 2.07 2025-03-28 08:52:46 -04:00
BubbaGumpShrump
9400a087e2 Location Fix 2025-02-19 16:27:47 -05:00
24 changed files with 1222 additions and 1635 deletions

71
.github/workflows/build.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: Build and Package
on:
push:
branches: [default]
pull_request:
branches: [default]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Extract version
id: version
run: |
$version = (Select-String -Path "AutoTrackR2/UpdatePage.xaml.cs" -Pattern 'currentVersion = "(.+?)"' | Select-Object -First 1).Matches.Groups[1].Value
echo "version=$version" >> $env:GITHUB_OUTPUT
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: "9.0.x"
- name: Restore dependencies
run: dotnet restore AutoTrackR2.sln
- name: Build
run: dotnet build AutoTrackR2.sln --configuration Release --no-restore
- name: List build output directories
run: |
Write-Host "Listing build output directories:"
Get-ChildItem -Recurse -Directory -Filter "Release" | ForEach-Object { Write-Host $_.FullName }
- name: Create artifacts directory
run: mkdir artifacts
- name: Copy build output
run: |
$releaseDir = Get-ChildItem -Recurse -Directory -Filter "Release" | Select-Object -First 1
if ($releaseDir) {
Write-Host "Copying from: $($releaseDir.FullName)"
Copy-Item "$($releaseDir.FullName)\*" "artifacts\" -Recurse
} else {
Write-Host "No Release directory found"
exit 1
}
- name: Upload application artifact
uses: actions/upload-artifact@v4
with:
name: AutoTrackR2-${{ steps.version.outputs.version }}
path: artifacts/
retention-days: 5
- name: Upload visorwipe script
uses: actions/upload-artifact@v4
with:
name: visorwipe.ahk
path: AutoTrackR2/scripts/visorwipe.ahk
retention-days: 5
- name: Upload videorecord script
uses: actions/upload-artifact@v4
with:
name: videorecord.ahk
path: AutoTrackR2/scripts/videorecord.ahk
retention-days: 5

View file

@ -5,8 +5,6 @@ VisualStudioVersion = 17.12.35521.163
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTrackR2", "AutoTrackR2\AutoTrackR2.csproj", "{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}"
EndProject
Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "AutoTrackR2_Setup", "AutoTrackR2_Setup\AutoTrackR2_Setup.vdproj", "{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -17,8 +15,6 @@ Global
Test|x64 = Test|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Debug|Any CPU.ActiveCfg = Release|x64
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Debug|Any CPU.Build.0 = Release|x64
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Debug|x64.ActiveCfg = Release|x64
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Debug|x64.Build.0 = Release|x64
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Release|Any CPU.ActiveCfg = Release|x64
@ -29,13 +25,8 @@ Global
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Test|Any CPU.Build.0 = Test|Any CPU
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Test|x64.ActiveCfg = Test|x64
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Test|x64.Build.0 = Test|x64
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Debug|Any CPU.ActiveCfg = Debug
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Debug|x64.ActiveCfg = Debug
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Release|Any CPU.ActiveCfg = Release
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Release|x64.ActiveCfg = Release
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Release|x64.Build.0 = Release
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Test|Any CPU.ActiveCfg = Debug
{025CBDCE-DE23-47CF-B75F-8C4C6C539E59}.Test|x64.ActiveCfg = Debug
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Debug|Any CPU.ActiveCfg = Debug|x64
{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}.Debug|Any CPU.Build.0 = Debug|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View file

@ -15,20 +15,30 @@
<Color x:Key="TextColor">#FFFFFF</Color>
<Color x:Key="AltTextColor">#A88F2C</Color>
<SolidColorBrush x:Key="TextBrush" Color="{DynamicResource TextColor}" />
<SolidColorBrush x:Key="AccentBrush" Color="{DynamicResource AccentColor}" />
<SolidColorBrush x:Key="BackgroundDarkBrush" Color="{DynamicResource BackgroundDarkColor}" />
<SolidColorBrush x:Key="BackgroundLightBrush" Color="{DynamicResource BackgroundLightColor}" />
<SolidColorBrush x:Key="AltTextBrush" Color="{DynamicResource AltTextColor}" />
<SolidColorBrush x:Key="TextBrush"
Color="{DynamicResource TextColor}"/>
<SolidColorBrush x:Key="AccentBrush"
Color="{DynamicResource AccentColor}"/>
<SolidColorBrush x:Key="BackgroundDarkBrush"
Color="{DynamicResource BackgroundDarkColor}"/>
<SolidColorBrush x:Key="BackgroundLightBrush"
Color="{DynamicResource BackgroundLightColor}"/>
<SolidColorBrush x:Key="AltTextBrush"
Color="{DynamicResource AltTextColor}"/>
<!-- Define the Style for Window -->
<Style TargetType="Window" x:Key="CustomWindowStyle">
<Style TargetType="Window"
x:Key="CustomWindowStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Border BorderBrush="{DynamicResource AccentBrush}" BorderThickness="2" CornerRadius="10" Background="{DynamicResource BackgroundLightBrush}">
<Border BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="10"
Background="{DynamicResource BackgroundLightBrush}">
<Grid>
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<ContentPresenter HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Grid>
</Border>
</ControlTemplate>
@ -37,62 +47,99 @@
</Style>
<!-- Tab Button Style -->
<Style x:Key="TabButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Padding" Value="10"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="FontFamily" Value="{StaticResource Orbitron}"/>
<Style x:Key="TabButtonStyle"
TargetType="Button">
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="Cursor"
Value="Hand"/>
<Setter Property="Padding"
Value="10"/>
<Setter Property="Margin"
Value="5"/>
<Setter Property="FontFamily"
Value="{StaticResource Orbitron}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5">
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<!-- ContentPresenter will automatically inherit Foreground from Button -->
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- General Button Style -->
<Style x:Key="DisabledButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Padding" Value="5"/>
<Style x:Key="DisabledButtonStyle"
TargetType="Button">
<Setter Property="Foreground"
Value="Gray"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="Gray"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="FontWeight"
Value="Bold"/>
<Setter Property="Cursor"
Value="Hand"/>
<Setter Property="Padding"
Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Padding" Value="5"/>
<Style x:Key="ButtonStyle"
TargetType="Button">
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="FontWeight"
Value="Bold"/>
<Setter Property="Cursor"
Value="Hand"/>
<Setter Property="Padding"
Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
@ -100,69 +147,141 @@
</Style>
<!-- Title Bar Button Style -->
<Style x:Key="TitleButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Cursor" Value="Hand"/>
<Style x:Key="TitleButtonStyle"
TargetType="Button">
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="FontWeight"
Value="Bold"/>
<Setter Property="Cursor"
Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="5"
Margin="0,1,4,1">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="5"
Margin="0,1,4,1">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Custom style for text blocks -->
<Style x:Key="RoundedTextBlock" TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="FontFamily" Value="{StaticResource Roboto}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Padding" Value="10,0,10,0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Style x:Key="RoundedTextBlock"
TargetType="TextBlock">
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="FontFamily"
Value="{StaticResource Roboto}"/>
<Setter Property="Background"
Value="Transparent"/>
<Setter Property="FontSize"
Value="14"/>
<Setter Property="Padding"
Value="10,0,10,0"/>
<Setter Property="VerticalAlignment"
Value="Center"/>
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
</Style>
<!-- Wrap TextBlock in Border to apply rounded corners -->
<Style x:Key="RoundedTextBlockWithBorder" TargetType="Border">
<Setter Property="Background" Value="{DynamicResource BackgroundLightBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="CornerRadius" Value="5"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0,10,0,0"/>
<Style x:Key="RoundedTextBlockWithBorder"
TargetType="Border">
<Setter Property="Background"
Value="{DynamicResource BackgroundLightBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="CornerRadius"
Value="5"/>
<Setter Property="Padding"
Value="0"/>
<Setter Property="Margin"
Value="0,10,0,0"/>
</Style>
<!-- Custom Style for Rounded TextBox -->
<Style x:Key="RoundedTextBox" TargetType="TextBox">
<Setter Property="Foreground" Value="{DynamicResource TextBrush}"/>
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="FontFamily" Value="{StaticResource Roboto}"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness" Value="2"/>
<Style x:Key="RoundedTextBox"
TargetType="TextBox">
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="FontFamily"
Value="{StaticResource Roboto}"/>
<Setter Property="Height"
Value="30"/>
<Setter Property="Padding"
Value="5"/>
<Setter Property="VerticalContentAlignment"
Value="Center"/>
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<!-- The actual border with rounded corners -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Custom Style for Rounded PasswordBox -->
<Style x:Key="RoundedPasswordBox"
TargetType="PasswordBox">
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="FontFamily"
Value="{StaticResource Roboto}"/>
<Setter Property="Height"
Value="30"/>
<Setter Property="Padding"
Value="5"/>
<Setter Property="VerticalContentAlignment"
Value="Center"/>
<Setter Property="HorizontalAlignment"
Value="Stretch"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<!-- The actual border with rounded corners -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="PasswordBox">
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="5">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</ControlTemplate>
@ -171,39 +290,57 @@
</Style>
<!-- Custom Style for Slider -->
<Style x:Key="ThreePositionSlider" TargetType="Slider">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="160" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}" />
<Setter Property="BorderThickness" Value="2" />
<Style x:Key="ThreePositionSlider"
TargetType="Slider">
<Setter Property="Height"
Value="40"/>
<Setter Property="Width"
Value="160"/>
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid Width="200" Height="30" HorizontalAlignment="Left" Margin="58,-6,0,0">
<Grid Width="200"
Height="30"
HorizontalAlignment="Left"
Margin="58,-6,0,0">
<!-- Track Background -->
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="2" CornerRadius="15" Margin="0,0,-5,-4" />
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="15"
Margin="0,0,-5,-4"/>
<!-- Track -->
<Track x:Name="PART_Track">
<Track.Thumb>
<Thumb x:Name="PART_Thumb"
Width="22"
Height="22"
Margin="6,4,1,0">
Width="22"
Height="22"
Margin="6,4,1,0">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Ellipse Fill="{DynamicResource AccentBrush}" />
<Ellipse Fill="{DynamicResource AccentBrush}"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
<Track.DecreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
<RepeatButton Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
<RepeatButton Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Track.IncreaseRepeatButton>
</Track>
</Grid>
@ -213,39 +350,56 @@
</Style>
<!-- Toggle Slider Style -->
<Style x:Key="ToggleSliderStyle" TargetType="Slider">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="160" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}" />
<Setter Property="BorderThickness" Value="2" />
<Style x:Key="ToggleSliderStyle"
TargetType="Slider">
<Setter Property="Height"
Value="40"/>
<Setter Property="Width"
Value="160"/>
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="{DynamicResource AccentBrush}"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid Width="50" Height="30" HorizontalAlignment="Left" >
<Grid Width="50"
Height="30"
HorizontalAlignment="Left">
<!-- Track Background -->
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="2" CornerRadius="15" Margin="0,0,-5,-4" />
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="15"
Margin="0,0,-5,-4"/>
<!-- Track -->
<Track x:Name="PART_Track">
<Track.Thumb>
<Thumb x:Name="PART_Thumb"
Width="22"
Height="22"
Margin="6,4,1,0">
Width="22"
Height="22"
Margin="6,4,1,0">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Ellipse Fill="{DynamicResource AccentBrush}" />
<Ellipse Fill="{DynamicResource AccentBrush}"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
<Track.DecreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
<RepeatButton Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
<RepeatButton Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Track.IncreaseRepeatButton>
</Track>
</Grid>
@ -255,39 +409,56 @@
</Style>
<!-- False toggle theme -->
<Style x:Key="FalseToggleStyle" TargetType="Slider">
<Setter Property="Height" Value="40" />
<Setter Property="Width" Value="160" />
<Setter Property="Foreground" Value="{DynamicResource TextBrush}" />
<Setter Property="Background" Value="{DynamicResource BackgroundDarkBrush}" />
<Setter Property="BorderBrush" Value="Gray" />
<Setter Property="BorderThickness" Value="2" />
<Style x:Key="FalseToggleStyle"
TargetType="Slider">
<Setter Property="Height"
Value="40"/>
<Setter Property="Width"
Value="160"/>
<Setter Property="Foreground"
Value="{DynamicResource TextBrush}"/>
<Setter Property="Background"
Value="{DynamicResource BackgroundDarkBrush}"/>
<Setter Property="BorderBrush"
Value="Gray"/>
<Setter Property="BorderThickness"
Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Slider">
<Grid Width="50" Height="30" HorizontalAlignment="Left" >
<Grid Width="50"
Height="30"
HorizontalAlignment="Left">
<!-- Track Background -->
<Border Background="{DynamicResource BackgroundDarkBrush}" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="2" CornerRadius="15" Margin="0,0,-5,-4" />
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="15"
Margin="0,0,-5,-4"/>
<!-- Track -->
<Track x:Name="PART_Track">
<Track.Thumb>
<Thumb x:Name="PART_Thumb"
Width="22"
Height="22"
Margin="6,4,1,0">
Width="22"
Height="22"
Margin="6,4,1,0">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Ellipse Fill="Gray" />
<Ellipse Fill="Gray"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
<Track.DecreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
<RepeatButton Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
<RepeatButton Background="Transparent"
BorderBrush="Transparent"
IsHitTestVisible="False"/>
</Track.IncreaseRepeatButton>
</Track>
</Grid>
@ -298,15 +469,21 @@
<!-- Modern Rounded ScrollBar Style -->
<Style TargetType="ScrollBar">
<Setter Property="Width" Value="6" />
<Setter Property="Width"
Value="6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollBar">
<Grid>
<Track Name="PART_Track" IsDirectionReversed="true" Width="6" Margin="0,0,0,0">
<Track Name="PART_Track"
IsDirectionReversed="true"
Width="6"
Margin="0,0,0,0">
<!-- Decrease Repeat Button -->
<Track.DecreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="0">
<RepeatButton Background="Transparent"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="0">
<RepeatButton.Template>
<ControlTemplate TargetType="RepeatButton">
<Grid x:Name="RepeatButtonGrid">
@ -314,12 +491,18 @@
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="RepeatButtonGrid" To="1" Duration="0:0:0"/>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="RepeatButtonGrid"
To="1"
Duration="0:0:0"/>
</Storyboard>
</VisualState>
<VisualState Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="RepeatButtonGrid" To="0" Duration="0:0:0.1"/>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="RepeatButtonGrid"
To="0"
Duration="0:0:0.1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
@ -338,10 +521,10 @@
<ControlTemplate TargetType="Thumb">
<Grid>
<Border
Background="{DynamicResource AccentBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="0"
CornerRadius="3" />
Background="{DynamicResource AccentBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="0"
CornerRadius="3"/>
</Grid>
</ControlTemplate>
</Thumb.Template>
@ -350,7 +533,9 @@
<!-- Increase Repeat Button -->
<Track.IncreaseRepeatButton>
<RepeatButton Background="Transparent" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="0">
<RepeatButton Background="Transparent"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="0">
<RepeatButton.Template>
<ControlTemplate TargetType="RepeatButton">
<Grid x:Name="RepeatButtonGrid">
@ -358,12 +543,18 @@
<VisualStateGroup Name="CommonStates">
<VisualState Name="Normal">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="RepeatButtonGrid" To="1" Duration="0:0:0"/>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="RepeatButtonGrid"
To="1"
Duration="0:0:0"/>
</Storyboard>
</VisualState>
<VisualState Name="MouseOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Storyboard.TargetName="RepeatButtonGrid" To="0" Duration="0:0:0.1"/>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Storyboard.TargetName="RepeatButtonGrid"
To="0"
Duration="0:0:0.1"/>
</Storyboard>
</VisualState>
</VisualStateGroup>

View file

@ -108,10 +108,4 @@
</Resource>
</ItemGroup>
<ItemGroup>
<None Update="update.ps1">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View file

@ -1,104 +1,236 @@
<UserControl x:Class="AutoTrackR2.ConfigPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="410" Width="626">
Height="410"
Width="626">
<Grid Background="{DynamicResource BackgroundLightBrush}">
<!-- Main Layout Grid -->
<Grid Margin="0,0,5,7">
<Grid.RowDefinitions>
<!-- One row for the content, the other for buttons -->
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<!-- Left column for the main content area -->
<ColumnDefinition Width="*" />
<!-- Right column for the buttons -->
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid Background="{DynamicResource BackgroundLightBrush}">
<!-- Main Layout Grid -->
<Grid Margin="0,0,5,7">
<Grid.RowDefinitions>
<!-- One row for the content, the other for buttons -->
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Section for Config Fields -->
<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="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>
<Grid.ColumnDefinitions>
<!-- Left column for the main content area -->
<ColumnDefinition Width="*"/>
<!-- Right column for the buttons -->
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- 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="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>
<!-- Section for Config Fields -->
<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="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 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="330" Height="30" Margin="33,0,0,0" Style="{StaticResource RoundedTextBox}"/>
</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="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>
<!-- 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="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>
<!-- 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"/>
<PasswordBox Name="ApiKey"
Width="330"
Height="30"
Margin="33,0,0,0"
Style="{StaticResource RoundedPasswordBox}"/>
</StackPanel>
<!-- 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 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="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>
<!-- 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>
<!-- 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>
<!-- Offline Mode Toggle Slider -->
<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>
<!-- 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>
<!-- 3-Position Toggle Slider -->
<StackPanel Margin="0,0,0,15" Orientation="Horizontal">
<TextBlock Text="Theme:" Foreground="{DynamicResource TextBrush}" FontSize="16" Margin="0,7,0,5"/>
<Slider x:Name="ThemeSlider"
Minimum="0"
Maximum="21"
Value="0"
TickFrequency="1"
IsSnapToTickEnabled="True"
ValueChanged="ThemeSlider_ValueChanged" Width="447"
Style="{StaticResource ThreePositionSlider}"
/>
</StackPanel>
<!-- Offline Mode Toggle Slider -->
<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>
</StackPanel>
<!-- 3-Position Toggle Slider -->
<StackPanel Margin="0,0,0,15"
Orientation="Horizontal">
<TextBlock Text="Theme:"
Foreground="{DynamicResource TextBrush}"
FontSize="16"
Margin="0,7,0,5"/>
<Slider x:Name="ThemeSlider"
Minimum="0"
Maximum="21"
Value="0"
TickFrequency="1"
IsSnapToTickEnabled="True"
ValueChanged="ThemeSlider_ValueChanged"
Width="447"
Style="{StaticResource ThreePositionSlider}"/>
</StackPanel>
<!-- Save Button -->
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0">
<Button x:Name="SaveButton" Content="Save" Width="100" Height="40" Style="{StaticResource ButtonStyle}" FontFamily="{StaticResource Orbitron}" Click="SaveButton_Click"/>
</StackPanel>
</StackPanel>
<!-- Save Button -->
<StackPanel Grid.Column="2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="0,0,0,10">
<Button x:Name="SaveButton"
Content="Save"
Width="100"
Height="40"
Style="{StaticResource ButtonStyle}"
FontFamily="{StaticResource Orbitron}"
Click="SaveButton_Click"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
</UserControl>

View file

@ -24,10 +24,10 @@ namespace AutoTrackR2
{
InitializeComponent();
this.mainWindow = mainWindow;
LogFilePath.Text = ConfigManager.LogFile;
ApiUrl.Text = ConfigManager.ApiUrl;
ApiKey.Text = ConfigManager.ApiKey;
ApiKey.Password = ConfigManager.ApiKey;
VideoPath.Text = ConfigManager.VideoPath;
VisorWipeSlider.Value = ConfigManager.VisorWipe;
VideoRecordSlider.Value = ConfigManager.VideoRecord;
@ -70,7 +70,7 @@ namespace AutoTrackR2
// Set the textboxes with the loaded values
LogFilePath.Text = logFile;
ApiUrl.Text = apiUrl;
ApiKey.Text = apiKey;
ApiKey.Password = apiKey;
VideoPath.Text = videoPath;
// Set the sliders with the loaded values
@ -123,7 +123,7 @@ namespace AutoTrackR2
// Apply the selected theme
ApplyTheme(themeIndex);
mainWindow.UpdateTabVisuals();
}
@ -293,11 +293,11 @@ namespace AutoTrackR2
break;
case 16: // Feezy
UpdateThemeColors(
(Color)ColorConverter.ConvertFromString("#FFA500"), // Accent/Border - Orange
(Color)ColorConverter.ConvertFromString("#FFE4B5"), // Button - Moccasin
(Color)ColorConverter.ConvertFromString("#FFF8DC"), // Background - Cornsilk
(Color)ColorConverter.ConvertFromString("#8B4513"), // Text - Saddle Brown
(Color)ColorConverter.ConvertFromString("#FF7F50") // AltText - Coral
(Color)ColorConverter.ConvertFromString("#FFA500"), // Accent/Border
(Color)ColorConverter.ConvertFromString("#1B0C04"), // Button
(Color)ColorConverter.ConvertFromString("#1B0C04"), // Background
(Color)ColorConverter.ConvertFromString("#FFE4B5"), // Text
(Color)ColorConverter.ConvertFromString("#A88F2C") // AltText
);
ChangeLogo("/Assets/chibifox.png", (Color)ColorConverter.ConvertFromString("#FFA500"));
break;
@ -399,11 +399,14 @@ namespace AutoTrackR2
dialog.ValidateNames = false;
dialog.Filter = "All files|*.*";
if (dialog.ShowDialog() == true)
if (dialog.ShowDialog() == true && dialog.FileName != null)
{
// Extract only the directory path from the file
string selectedFolder = Path.GetDirectoryName(dialog.FileName);
VideoPath.Text = selectedFolder; // Set the folder path
string? selectedFolder = Path.GetDirectoryName(dialog.FileName);
if (selectedFolder != null)
{
VideoPath.Text = selectedFolder; // Set the folder path
}
}
}
@ -412,6 +415,11 @@ namespace AutoTrackR2
Slider slider = (Slider)sender;
// Build the dynamic file path for the current user
if (string.IsNullOrEmpty(ConfigManager.AHKScriptFolder))
{
MessageBox.Show("AHK script folder path is not configured.", "Configuration Error", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
string filePath = Path.Combine(
ConfigManager.AHKScriptFolder,
"visorwipe.ahk"
@ -507,7 +515,8 @@ namespace AutoTrackR2
private void SaveButton_Click(object sender, RoutedEventArgs e)
{
ConfigManager.ApiKey = ApiKey.Text;
ConfigManager.ApiKey = ApiKey.Password;
ConfigManager.ApiUrl = ApiUrl.Text;
ConfigManager.LogFile = LogFilePath.Text;
ConfigManager.VideoPath = VideoPath.Text;
@ -515,7 +524,6 @@ namespace AutoTrackR2
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
@ -524,7 +532,7 @@ namespace AutoTrackR2
private void FlashSaveButton()
{
string originalText = SaveButton.Content.ToString();
string? originalText = SaveButton.Content?.ToString() ?? string.Empty;
SaveButton.Content = "Saved";
// Save button color change effect
@ -573,7 +581,7 @@ namespace AutoTrackR2
{
string apiUrl = ApiUrl.Text;
string modifiedUrl = Regex.Replace(apiUrl, @"(https?://[^/]+)/?.*", "$1/test");
string apiKey = ApiKey.Text;
string apiKey = ApiKey.Password;
Debug.WriteLine($"Sending to {modifiedUrl}");
try

View file

@ -1,48 +1,176 @@
<UserControl x:Class="AutoTrackR2.HomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="396" Width="626">
<Grid Background="{DynamicResource BackgroundLightBrush}">
<!-- Main Layout Grid -->
<Grid Margin="0,0,5,7">
<Grid.RowDefinitions>
<!-- One row for the content, the other for buttons -->
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
Height="396"
Width="626">
<Grid Background="{DynamicResource BackgroundLightBrush}">
<!-- Main Layout Grid -->
<Grid Margin="0,0,5,7">
<Grid.RowDefinitions>
<!-- One row for the content, the other for buttons -->
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<!-- Left column for the main content area -->
<ColumnDefinition />
<!-- Right column for the buttons -->
<ColumnDefinition Width="Auto" MinWidth="173" />
</Grid.ColumnDefinitions>
<Grid.ColumnDefinitions>
<!-- Left column for the main content area -->
<ColumnDefinition/>
<!-- Right column for the buttons -->
<ColumnDefinition Width="Auto"
MinWidth="173"/>
</Grid.ColumnDefinitions>
<!-- Border for the kill feed section -->
<!--TextBox Name="OutputTextBox" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Height="NaN" Margin="0,0,20,0" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" IsReadOnly="True" Style="{StaticResource RoundedTextBox}"/-->
<Border Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" BorderBrush="{DynamicResource AccentBrush}" BorderThickness="2" CornerRadius="5" Padding="10,0,0,0" Background="{DynamicResource BackgroundDarkBrush}" Margin="0,0,20,0">
<ScrollViewer VerticalScrollBarVisibility="Auto" Width="419" Margin="0,0,-5,0">
<StackPanel Name="KillFeedStackPanel" Orientation="Vertical" Margin="0,0,0,0" Width="402" HorizontalAlignment="Left"/>
</ScrollViewer>
</Border>
<!-- Border for the kill feed section -->
<!--TextBox Name="OutputTextBox" Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Height="NaN" Margin="0,0,20,0" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" IsReadOnly="True" Style="{StaticResource RoundedTextBox}"/-->
<Border Grid.Row="0"
Grid.Column="0"
Grid.RowSpan="2"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="5"
Padding="10,0,0,0"
Background="{DynamicResource BackgroundDarkBrush}"
Margin="0,0,20,0">
<ScrollViewer VerticalScrollBarVisibility="Auto"
Width="419"
Margin="0,0,-5,0">
<StackPanel Name="KillFeedStackPanel"
Orientation="Vertical"
Margin="0,0,0,0"
Width="402"
HorizontalAlignment="Left"/>
</ScrollViewer>
</Border>
<!-- 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"/>
<StackPanel Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Height="269" 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="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="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="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="KillTallyTextBox" Text="" Width="152" Height="20" Background="Transparent" FontFamily="{StaticResource Orbitron}" Margin="0,0,0,0" Foreground="{DynamicResource TextBrush}" FontSize="10" TextAlignment="Center"/>
<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 Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Center" Height="120" Width="172" >
<Button Name="StartButton" Content="Start" Width="100" Height="40" Style="{StaticResource ButtonStyle}" FontFamily="{StaticResource Orbitron}" Margin="0,20" Click="StartButton_Click"/>
<Button Name="StopButton" Content="Stop" Width="100" Height="40" Style="{StaticResource DisabledButtonStyle}" FontFamily="{StaticResource Orbitron}" IsEnabled="False" Click="StopButton_Click"/>
</StackPanel>
<!-- 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"/>
<StackPanel Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="269"
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="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="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="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="KillTallyTextBox"
Text=""
Width="152"
Height="20"
Background="Transparent"
FontFamily="{StaticResource Orbitron}"
Margin="0,0,0,0"
Foreground="{DynamicResource TextBrush}"
FontSize="10"
TextAlignment="Center"/>
<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 Grid.Row="1"
Grid.Column="1"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Height="120"
Width="172">
<Border Background="{DynamicResource BackgroundDarkBrush}"
BorderBrush="{DynamicResource AccentBrush}"
BorderThickness="2"
CornerRadius="5"
Height="80"
Margin="0,10,0,0">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Ellipse x:Name="StatusLight"
Width="15"
Height="15"
Margin="0,0,10,0"
Fill="Red"/>
<TextBlock x:Name="StatusText"
Text="TrackR&#x0a;Standby"
Foreground="{DynamicResource TextBrush}"
FontFamily="{StaticResource Orbitron}"
FontSize="14"
VerticalAlignment="Center"/>
</StackPanel>
</Border>
</StackPanel>
</Grid>
</Grid>
</Grid>
</UserControl>

View file

@ -9,81 +9,102 @@ using System.IO;
using System.Text;
using System.Windows.Media.Imaging;
using AutoTrackR2.LogEventHandlers;
using System.Timers;
using System.Linq;
namespace AutoTrackR2;
public partial class HomePage : UserControl
{
private Process runningProcess; // Field to store the running process
private LogHandler? _logHandler;
private KillHistoryManager _killHistoryManager;
private bool _UIEventsRegistered = false;
private System.Timers.Timer _statusCheckTimer;
private bool _isLogHandlerRunning = false;
public HomePage()
{
InitializeComponent();
if (string.IsNullOrEmpty(ConfigManager.KillHistoryFile))
{
throw new InvalidOperationException("KillHistoryFile path is not configured.");
}
_killHistoryManager = new KillHistoryManager(ConfigManager.KillHistoryFile);
// Set the TextBlock text
KillTallyTitle.Text = $"Kill Tally - {_killHistoryManager.GetKillsInCurrentMonth().Count}";
KillTallyTitle.Text = $"Kill Tally - {DateTime.Now.ToString("MMMM")}";
KillTallyTextBox.Text = _killHistoryManager.GetKillsInCurrentMonth().Count.ToString();
AdjustFontSize(KillTallyTextBox);
AddKillHistoryKillsToUI();
}
// Update Start/Stop button states based on the isRunning flag
public void UpdateButtonState(bool isRunning)
{
var accentColor = (Color)Application.Current.Resources["AccentColor"];
// Initialize and start the status check timer
_statusCheckTimer = new System.Timers.Timer(1000); // Check every second
_statusCheckTimer.Elapsed += CheckStarCitizenStatus;
_statusCheckTimer.Start();
// Check if Star Citizen is already running and initialize accordingly
if (IsStarCitizenRunning())
{
Dispatcher.Invoke(() =>
{
UpdateStatusIndicator(true);
InitializeLogHandler(); // Then initialize the log handler
});
}
}
private void CheckStarCitizenStatus(object? sender, ElapsedEventArgs e)
{
bool isRunning = IsStarCitizenRunning();
Dispatcher.Invoke(() =>
{
UpdateStatusIndicator(isRunning);
if (isRunning)
{
if (!_isLogHandlerRunning)
{
// Game is running, start log monitoring and read initial states
InitializeLogHandler();
}
}
else
{
// Game is not running, set everything to Unknown
GameModeTextBox.Text = "Unknown";
PlayerShipTextBox.Text = "Unknown";
PilotNameTextBox.Text = "Unknown";
LocalPlayerData.CurrentGameMode = GameMode.Unknown;
LocalPlayerData.PlayerShip = string.Empty;
LocalPlayerData.Username = string.Empty;
// Stop log monitoring if it's running
if (_isLogHandlerRunning)
{
_logHandler?.StopMonitoring();
_isLogHandlerRunning = false;
}
}
});
}
private void UpdateStatusIndicator(bool isRunning)
{
if (isRunning)
{
// Set Start button to "Running..." and apply glow effect
StartButton.Content = "Running...";
StartButton.IsEnabled = false; // Disable Start button
StartButton.Style = (Style)FindResource("DisabledButtonStyle");
// Add glow effect to the Start button
StartButton.Effect = new DropShadowEffect
{
Color = accentColor,
BlurRadius = 30, // Adjust blur radius for desired glow intensity
ShadowDepth = 0, // Set shadow depth to 0 for a pure glow effect
Opacity = 1, // Set opacity for glow visibility
Direction = 0 // Direction doesn't matter for glow
};
StopButton.Style = (Style)FindResource("ButtonStyle");
StopButton.IsEnabled = true; // Enable Stop button
StatusLight.Fill = new SolidColorBrush(Colors.Green);
StatusText.Text = "TrackR\nActive";
}
else
{
// Reset Start button back to its original state
StartButton.Content = "Start";
StartButton.IsEnabled = true; // Enable Start button
// Remove the glow effect from Start button
StartButton.Effect = null;
StopButton.Style = (Style)FindResource("DisabledButtonStyle");
StartButton.Style = (Style)FindResource("ButtonStyle");
StopButton.IsEnabled = false; // Disable Stop button
StatusLight.Fill = new SolidColorBrush(Colors.Red);
StatusText.Text = "TrackR\nStandby";
}
RegisterUIEventHandlers();
}
public void StartButton_Click(object sender, RoutedEventArgs e)
{
UpdateButtonState(true);
//string scriptPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "KillTrackR_MainScript.ps1");
// TailFileAsync(scriptPath);
// _logHandler = new LogHandler(@"U:\\StarCitizen\\StarCitizen\\LIVE\\Game.log");
_logHandler = new LogHandler(ConfigManager.LogFile);
_logHandler.Initialize();
}
private void AddKillHistoryKillsToUI()
{
var kills = _killHistoryManager.GetKills();
@ -97,9 +118,10 @@ public partial class HomePage : UserControl
{
if (_UIEventsRegistered)
return;
// Username
TrackREventDispatcher.PlayerLoginEvent += (username) => {
TrackREventDispatcher.PlayerLoginEvent += (username) =>
{
Dispatcher.Invoke(() =>
{
PilotNameTextBox.Text = username;
@ -107,38 +129,41 @@ public partial class HomePage : UserControl
LocalPlayerData.Username = username;
});
};
// Ship
TrackREventDispatcher.JumpDriveStateChangedEvent += (shipName) => {
Dispatcher.Invoke(() =>
{
PlayerShipTextBox.Text = shipName;
AdjustFontSize(PlayerShipTextBox);
LocalPlayerData.PlayerShip = shipName;
});
};
// Game Mode
TrackREventDispatcher.PlayerChangedGameModeEvent += (mode) => {
TrackREventDispatcher.JumpDriveStateChangedEvent += (shipName) =>
{
Dispatcher.Invoke(() =>
{
GameModeTextBox.Text = mode.ToString();
PlayerShipTextBox.Text = LocalPlayerData.CurrentGameMode == GameMode.PersistentUniverse ? shipName : "Unknown";
AdjustFontSize(PlayerShipTextBox);
LocalPlayerData.PlayerShip = shipName;
});
};
// Game Mode
TrackREventDispatcher.PlayerChangedGameModeEvent += (mode) =>
{
Dispatcher.Invoke(() =>
{
GameModeTextBox.Text = mode == GameMode.PersistentUniverse ? mode.ToString() : GameMode.Unknown.ToString();
AdjustFontSize(GameModeTextBox);
LocalPlayerData.CurrentGameMode = mode;
});
};
// Game Version
TrackREventDispatcher.GameVersionEvent += (version) => {
LocalPlayerData.GameVersion = version;
TrackREventDispatcher.GameVersionEvent += (version) =>
{
LocalPlayerData.GameVersion = version;
};
// Actor Death
TrackREventDispatcher.ActorDeathEvent += async (actorDeathData) => {
TrackREventDispatcher.ActorDeathEvent += async (actorDeathData) =>
{
if (actorDeathData.VictimPilot != LocalPlayerData.Username)
{
var playerData = await WebHandler.GetPlayerData(actorDeathData.VictimPilot);
if (playerData != null)
{
var killData = new KillData
@ -151,12 +176,12 @@ public partial class HomePage : UserControl
Method = actorDeathData.DamageType,
RecordNumber = playerData?.UEERecord,
GameVersion = LocalPlayerData.GameVersion ?? "Unknown",
TrackRver = UpdatePage.currentVersion.Replace("v", "") ?? "Unknown",
TrackRver = LocalPlayerData.GameVersion?.Replace("v", "") ?? "Unknown",
Enlisted = playerData?.JoinDate,
KillTime = DateTime.UtcNow.ToString("dd MMM yyyy HH:mm"),
PFP = playerData?.PFPURL ?? "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg"
};
switch (LocalPlayerData.CurrentGameMode)
{
case GameMode.PersistentUniverse:
@ -166,13 +191,13 @@ public partial class HomePage : UserControl
killData.Mode = "ac";
break;
}
// Add kill to UI
Dispatcher.Invoke(() =>
{
AddKillToScreen(killData);
});
// Only submit kill data if not in offline mode
if (ConfigManager.OfflineMode == 0)
{
@ -185,17 +210,18 @@ public partial class HomePage : UserControl
}
}
};
// Vehicle Destruction
TrackREventDispatcher.VehicleDestructionEvent += (data) => {
TrackREventDispatcher.VehicleDestructionEvent += (data) =>
{
LocalPlayerData.LastSeenVehicleLocation = data.VehicleZone;
};
_UIEventsRegistered = true;
}
private void AddKillToScreen(KillData killData)
{
{
// Fetch the dynamic resource for AltTextColor
var altTextColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AltTextColor"]);
var accentColorBrush = new SolidColorBrush((Color)Application.Current.Resources["AccentColor"]);
@ -236,22 +262,22 @@ public partial class HomePage : UserControl
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killData.OrgAffiliation}\n"));
killTextBlock.Inlines.Add(new Run("Join Date: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killData.Enlisted}\n"));
killTextBlock.Inlines.Add(new Run("UEE Record: ")
{
Foreground = altTextColorBrush,
FontFamily = orbitronFontFamily,
});
killTextBlock.Inlines.Add(new Run($"{killData.RecordNumber}\n"));
killTextBlock.Inlines.Add(new Run("Kill Time: ")
{
Foreground = altTextColorBrush,
@ -284,26 +310,24 @@ public partial class HomePage : UserControl
{
killData.PFP = "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg";
}
// Create the Image for the profile
var profileImage = new Image
{
Source = new BitmapImage(new Uri(killData.PFP)), // Assuming the 8th part contains the profile image URL
Source = new BitmapImage(new Uri(killData.PFP ?? "https://cdn.robertsspaceindustries.com/static/images/account/avatar_default_big.jpg")),
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
};
var imageBorder = new Border();
imageBorder.SetResourceReference(Border.BorderBrushProperty, "AccentBrush");
imageBorder.BorderThickness = new Thickness(2);
imageBorder.Padding = new Thickness(0);
imageBorder.CornerRadius = new CornerRadius(5);
imageBorder.Margin = new Thickness(10, 18, 15, 18);
imageBorder.Child = profileImage;
// Add the Border (with the image inside) to the Grid
Grid.SetColumn(imageBorder, 1);
@ -321,15 +345,7 @@ public partial class HomePage : UserControl
public void StopButton_Click(object sender, RoutedEventArgs e)
{
_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();
_logHandler?.StopMonitoring();
}
private void AdjustFontSize(TextBlock textBlock)
@ -366,23 +382,27 @@ public partial class HomePage : UserControl
VisualTreeHelper.GetDpi(this).PixelsPerDip
);
}
// Apply the adjusted font size
textBlock.FontSize = fontSize;
}
public static void RunAHKScript(string path)
public static void RunAHKScript(string? path)
{
if (string.IsNullOrEmpty(path) || string.IsNullOrEmpty(ConfigManager.AHKScriptFolder))
{
return;
}
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";
@ -397,7 +417,7 @@ public partial class HomePage : UserControl
RunAHKScript(ConfigManager.VisorWipeScript);
}
}
private void VideoRecord()
{
if (ConfigManager.VideoRecord == 1)
@ -405,4 +425,36 @@ public partial class HomePage : UserControl
RunAHKScript(ConfigManager.VideoRecordScript);
}
}
public void InitializeLogHandler()
{
if (_logHandler == null)
{
RegisterUIEventHandlers();
_logHandler = new LogHandler(ConfigManager.LogFile);
_logHandler.Initialize();
_isLogHandlerRunning = true;
}
else if (!_isLogHandlerRunning)
{
_logHandler.Initialize();
_isLogHandlerRunning = true;
}
}
public void Cleanup()
{
// Stop and dispose the status check timer
_statusCheckTimer?.Stop();
_statusCheckTimer?.Dispose();
// Stop the log handler if it's running
_logHandler?.StopMonitoring();
}
private bool IsStarCitizenRunning()
{
return Process.GetProcessesByName("StarCitizen").Length > 0;
}
}

View file

@ -34,7 +34,19 @@ public class KillHistoryManager
// 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());
// Check file can be written to
try
{
using var fileStream = new FileStream(_killHistoryPath, FileMode.Append, FileAccess.Write, FileShare.None);
using var writer = new StreamWriter(fileStream);
writer.Write(csv.ToString());
}
catch (IOException ex)
{
// Handle the exception (e.g., log it)
Console.WriteLine($"Error writing to file: {ex.Message}");
}
}
public List<KillData> GetKills()

View file

@ -3,8 +3,9 @@
public enum GameMode
{
ArenaCommander,
PersistentUniverse
Unknown,
PersistentUniverse,
ArenaCommander
}
public static class LocalPlayerData

View file

@ -19,7 +19,6 @@ public struct VehicleDestructionData
public class VehicleDestructionEvent : ILogEventHandler
{
public Regex Pattern { get; }
public VehicleDestructionEvent()
{
Pattern = new Regex("""
@ -34,6 +33,10 @@ public class VehicleDestructionEvent : ILogEventHandler
public void Handle(LogEntry entry)
{
if (entry.Message == null)
{
return;
}
var match = Pattern.Match(entry.Message);
if (!match.Success)
{

View file

@ -12,7 +12,6 @@ public class LogEntry
{
public DateTime Timestamp { get; set; }
public required string? Message { get; set; }
}
enum GameProcessState
@ -22,16 +21,18 @@ enum GameProcessState
Unknown
}
public class LogHandler(string logPath)
public class LogHandler
{
private readonly string? _logPath = logPath;
private string _logPath;
private FileStream? _fileStream;
private StreamReader? _reader;
private GameProcessState _gameProcessState = GameProcessState.Unknown;
private Thread? _monitorThread;
private CancellationTokenSource? _cancellationTokenSource;
private GameProcessState _gameProcessState = GameProcessState.NotRunning;
private bool _isMonitoring = false;
public bool IsMonitoring => _isMonitoring;
private CancellationTokenSource cancellationToken = new CancellationTokenSource();
Thread? monitorThread;
// Handlers that should be run on every log entry
// Overlap with _startupEventHandlers is fine
private readonly List<ILogEventHandler> _eventHandlers = [
@ -43,18 +44,26 @@ public class LogHandler(string logPath)
new JumpDriveStateChangedEvent(),
new RequestJumpFailedEvent()
];
public LogHandler(string? logPath)
{
if (string.IsNullOrEmpty(logPath))
{
throw new ArgumentNullException(nameof(logPath), "Log path cannot be null or empty");
}
_logPath = logPath;
}
// Initialize the LogHandler and run all startup handlers
public void Initialize()
{
if (!File.Exists(_logPath))
{
throw new FileNotFoundException("Log file not found", _logPath);
}
_fileStream = new FileStream(_logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_reader = new StreamReader(_fileStream);
while (_reader.ReadLine() is { } line)
{
HandleLogEntry(line);
@ -62,28 +71,39 @@ public class LogHandler(string logPath)
// Ensures that any deaths already in log aren't sent to the APIs until the monitor thread is running
_eventHandlers.Add(new ActorDeathEvent());
monitorThread = new Thread(() => MonitorLog(cancellationToken.Token));
monitorThread.Start();
StartMonitoring();
}
public void Stop()
public void StartMonitoring()
{
// Stop the monitor thread
cancellationToken?.Cancel();
if (_isMonitoring) return;
_cancellationTokenSource = new CancellationTokenSource();
_monitorThread = new Thread(() => MonitorLog(_cancellationTokenSource.Token));
_monitorThread.Start();
_isMonitoring = true;
}
public void StopMonitoring()
{
if (!_isMonitoring) return;
_cancellationTokenSource?.Cancel();
_monitorThread?.Join();
_reader?.Close();
_fileStream?.Close();
_isMonitoring = false;
}
// Parse a single line of the log file and run matching handlers
private void HandleLogEntry(string line)
{
Console.WriteLine(line);
// Console.WriteLine(line);
foreach (var handler in _eventHandlers)
{
var match = handler.Pattern.Match(line);
if (!match.Success) continue;
var entry = new LogEntry
{
Timestamp = DateTime.Now,
@ -93,13 +113,18 @@ public class LogHandler(string logPath)
break;
}
}
private void MonitorLog(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
if (_reader == null || _fileStream == null)
{
break;
}
CheckGameProcessState();
List<string> lines = new List<string>();
while (_reader.ReadLine() is { } line)
{
@ -126,21 +151,19 @@ public class LogHandler(string logPath)
{
// Check if the game process is running by window name
var process = Process.GetProcesses().FirstOrDefault(p => p.MainWindowTitle == "Star Citizen");
GameProcessState newGameProcessState = process != null ? GameProcessState.Running : GameProcessState.NotRunning;
if (newGameProcessState == GameProcessState.Running && _gameProcessState == GameProcessState.NotRunning)
{
// Game process went from NotRunning to Running, so reload the Game.log file
Console.WriteLine("Game process started, reloading log file");
_reader?.Close();
_fileStream?.Close();
_fileStream = new FileStream(_logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_reader = new StreamReader(_fileStream);
}
_gameProcessState = newGameProcessState;
}
}

View file

@ -25,8 +25,6 @@
<StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="5,0,0,0">
<Image x:Name="Logo" Height="138" Source="/Assets/AutoTrackR.png" Stretch="Fill" Width="141" RenderOptions.BitmapScalingMode="Fant"/>
<Button Content="Home" Name="HomeTab" Margin="10,40,10,10" Height="40" Style="{StaticResource TabButtonStyle}" Click="TabButton_Click"/>
<Button Content="Stats" Name="StatsTab" Margin="10" Height="40" Style="{StaticResource TabButtonStyle}" Click="TabButton_Click"/>
<Button Content="Update" Name="UpdateTab" Margin="10" Height="40" Style="{StaticResource TabButtonStyle}" Click="TabButton_Click"/>
<Button Content="Config" Name="ConfigTab" Margin="10" Height="40" Style="{StaticResource TabButtonStyle}" Click="TabButton_Click"/>
</StackPanel>

View file

@ -13,7 +13,6 @@ namespace AutoTrackR2
{
public partial class MainWindow : Window
{
private Dictionary<string, bool> tabStates = new Dictionary<string, bool>
{
{ "HomeTab", true }, // HomeTab is selected by default
@ -23,9 +22,7 @@ namespace AutoTrackR2
};
private HomePage homePage; // Persistent HomePage instance
private bool isRunning = false; // Single source of truth for the running state
// Ensure this method is not static
public void ChangeLogoImage(string imagePath)
{
Logo.Source = new BitmapImage(new Uri(imagePath, UriKind.RelativeOrAbsolute));
@ -38,10 +35,6 @@ namespace AutoTrackR2
homePage = new HomePage(); // Create a single instance of HomePage
ContentControl.Content = homePage; // Default to HomePage
// Attach event handlers for the HomePage buttons
homePage.StartButton.Click += StartButton_Click;
homePage.StopButton.Click += StopButton_Click;
// Create ConfigPage and pass the MainWindow reference to it
var configPage = new ConfigPage(this);
@ -51,6 +44,7 @@ namespace AutoTrackR2
UpdateTabVisuals();
Loaded += MainWindow_Loaded; // Handle Loaded event
Closing += MainWindow_Closing; // Handle Closing event
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
@ -59,16 +53,23 @@ namespace AutoTrackR2
var args = Environment.GetCommandLineArgs();
if (args.Contains("-start", StringComparer.OrdinalIgnoreCase))
{
homePage.StartButton_Click(null, null);
// Initialize log handler if needed
homePage.InitializeLogHandler();
}
}
private void MainWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)
{
// Clean up resources
homePage?.Cleanup();
// Make sure the application exits completely
Application.Current.Shutdown();
}
private void CloseWindow(object sender, RoutedEventArgs e)
{
// If runningProcess is not null and still active, terminate it
homePage.StopButton_Click(sender, e);
// Close the main window
// This will trigger the Closing event
this.Close();
}
@ -91,17 +92,6 @@ namespace AutoTrackR2
{
// Reuse the existing HomePage instance
ContentControl.Content = homePage;
// Update the button state on the HomePage
homePage.UpdateButtonState(isRunning);
}
else if (clickedTabName == "StatsTab")
{
ContentControl.Content = new StatsPage();
}
else if (clickedTabName == "UpdateTab")
{
ContentControl.Content = new UpdatePage();
}
else if (clickedTabName == "ConfigTab")
{
@ -158,20 +148,6 @@ namespace AutoTrackR2
}
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
isRunning = true; // Update the running state
homePage.UpdateButtonState(isRunning); // Update HomePage button visuals
// Start your logic here
}
private void StopButton_Click(object sender, RoutedEventArgs e)
{
isRunning = false; // Update the running state
homePage.UpdateButtonState(isRunning); // Update HomePage button visuals
// Stop your logic here
}
private void InitializeConfigPage()
{
// Set the values from the loaded config
@ -179,10 +155,10 @@ namespace AutoTrackR2
// Set the fields in ConfigPage.xaml.cs based on the loaded config
configPage.SetConfigValues(
ConfigManager.LogFile,
ConfigManager.ApiUrl,
ConfigManager.ApiKey,
ConfigManager.VideoPath,
ConfigManager.LogFile ?? string.Empty,
ConfigManager.ApiUrl ?? string.Empty,
ConfigManager.ApiKey ?? string.Empty,
ConfigManager.VideoPath ?? string.Empty,
ConfigManager.VisorWipe,
ConfigManager.VideoRecord,
ConfigManager.OfflineMode,
@ -193,17 +169,14 @@ namespace AutoTrackR2
public static class ConfigManager
{
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; }
public static string? LogFile { get; set; } = string.Empty;
public static string? KillHistoryFile { get; set; } = string.Empty;
public static string? AHKScriptFolder { get; set; } = string.Empty;
public static string? VisorWipeScript { get; set; } = string.Empty;
public static string? VideoRecordScript { get; set; } = string.Empty;
public static string? ApiUrl { get; set; } = string.Empty;
public static string? ApiKey { get; set; } = string.Empty;
public static string? VideoPath { get; set; } = string.Empty;
public static int VisorWipe { get; set; }
public static int VideoRecord { get; set; }
public static int OfflineMode { get; set; }

View file

@ -1,8 +0,0 @@
<UserControl x:Class="AutoTrackR2.StatsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="396" Width="626">
<Grid Background="{DynamicResource BackgroundLightBrush}">
<TextBlock Text="Stats and graphs coming soon!" FontSize="24" Foreground="{DynamicResource TextBrush}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</UserControl>

View file

@ -1,12 +0,0 @@
using System.Windows.Controls;
namespace AutoTrackR2
{
public partial class StatsPage : UserControl
{
public StatsPage()
{
InitializeComponent();
}
}
}

View file

@ -1,39 +0,0 @@
<UserControl x:Class="AutoTrackR2.UpdatePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="396" Width="626">
<Grid Background="{DynamicResource BackgroundLightBrush}">
<Grid Margin="0,0,5,7">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Current Version Display -->
<StackPanel Orientation="Horizontal" Margin="10" Grid.Row="0">
<TextBlock Text="Current Version: " FontSize="16" FontWeight="Bold" VerticalAlignment="Center" Foreground="{DynamicResource AltTextBrush}" />
<TextBlock x:Name="CurrentVersionText" Text="2.0-beta.0" FontSize="16" VerticalAlignment="Center" Foreground="{DynamicResource TextBrush}"/>
</StackPanel>
<!-- Available Version Display -->
<StackPanel Orientation="Horizontal" Margin="10" Grid.Row="1">
<TextBlock Text="Available Version: " FontSize="16" FontWeight="Bold" VerticalAlignment="Center" Foreground="{DynamicResource AltTextBrush}"/>
<TextBlock x:Name="AvailableVersionText" Text="Checking..." FontSize="16" VerticalAlignment="Center" Foreground="{DynamicResource TextBrush}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="20" Grid.Row="2">
<TextBlock Text="Still a work in progress. Please uninstall current version before installing update." FontSize="16" Foreground="{DynamicResource TextBrush}" />
</StackPanel>
<!-- Install Button -->
<StackPanel HorizontalAlignment="Right" VerticalAlignment="Bottom" Grid.Row="2" Grid.Column="2">
<Button x:Name="InstallButton" Content="Download Update" Width="150" Height="40" IsEnabled="False"
Click="InstallButton_Click" Style="{StaticResource DisabledButtonStyle}" FontFamily="{StaticResource Orbitron}"/>
</StackPanel>
</Grid>
</Grid>
</UserControl>

View file

@ -1,145 +0,0 @@
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
namespace AutoTrackR2
{
public partial class UpdatePage : UserControl
{
public static string currentVersion = "v2.09";
private string latestVersion;
public UpdatePage()
{
InitializeComponent();
CurrentVersionText.Text = currentVersion;
CheckForUpdates();
}
private async void CheckForUpdates()
{
try
{
// Fetch the latest release info from GitHub
latestVersion = await GetLatestVersionFromGitHub();
// Update the Available Version field
AvailableVersionText.Text = latestVersion;
// Enable the Install button if a new version is available
if (IsNewVersionAvailable(currentVersion, latestVersion))
{
InstallButton.IsEnabled = true;
InstallButton.Style = (Style)FindResource("ButtonStyle");
}
}
catch (Exception ex)
{
AvailableVersionText.Text = "Error checking updates.";
MessageBox.Show($"Failed to check for updates: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private async Task<string> GetLatestVersionFromGitHub()
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "AutoTrackR2");
string repoOwner = "BubbaGumpShrump";
string repoName = "AutoTrackR2";
try
{
// Attempt to fetch the latest release
var url = $"https://api.github.com/repos/{repoOwner}/{repoName}/releases/latest";
var response = await client.GetStringAsync(url);
// Parse the JSON using System.Text.Json
using var document = System.Text.Json.JsonDocument.Parse(response);
var root = document.RootElement;
var tagName = root.GetProperty("tag_name").GetString();
return tagName;
}
catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
// Fallback to releases list if 'latest' not found
var url = $"https://api.github.com/repos/{repoOwner}/{repoName}/releases";
var response = await client.GetStringAsync(url);
using var document = System.Text.Json.JsonDocument.Parse(response);
var root = document.RootElement;
// Get the tag name of the first release
if (root.GetArrayLength() > 0)
{
var firstRelease = root[0];
return firstRelease.GetProperty("tag_name").GetString();
}
throw new Exception("No releases found.");
}
}
private bool IsNewVersionAvailable(string currentVersion, string latestVersion)
{
// Return true if the versions are different
return !currentVersion.Equals(latestVersion, StringComparison.Ordinal);
}
private async void InstallButton_Click(object sender, RoutedEventArgs e)
{
try
{
InstallButton.IsEnabled = false;
InstallButton.Content = "Preparing to Update...";
// Get the path to the update.ps1 script
string scriptPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "update.ps1");
// Run the PowerShell script
RunPowerShellScript(scriptPath);
// Gracefully close the app after running the script
Application.Current.Shutdown();
MessageBox.Show("Update process has started. Please follow the instructions in the PowerShell script.", "Update Started", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Failed to run the update script: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
InstallButton.IsEnabled = true;
InstallButton.Content = "Install Update";
}
}
private void RunPowerShellScript(string scriptPath)
{
try
{
// Prepare the command to run the PowerShell script with elevation (admin rights)
var processStartInfo = new System.Diagnostics.ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = $"-ExecutionPolicy Bypass -File \"{scriptPath}\"", // Allow script to run
Verb = "runas", // Request elevation (admin rights)
UseShellExecute = true, // Use the shell to execute the process
CreateNoWindow = false // Show the PowerShell window
};
// Start the PowerShell process to run the script with admin rights
System.Diagnostics.Process.Start(processStartInfo);
}
catch (Exception ex)
{
MessageBox.Show($"Failed to run the PowerShell script with admin rights: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
}

View file

@ -4,6 +4,7 @@ using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using AutoTrackR2.LogEventHandlers;
using System.Globalization;
namespace AutoTrackR2;
@ -11,17 +12,18 @@ public static class WebHandler
{
class APIKillData
{
public string? victim_ship { get; set; }
public string? victim{ get; set; }
public string? enlisted{ get; set; }
public string? rsi{ get; set; }
public string? weapon{ get; set; }
public string? method{ get; set; }
public string? loadout_ship{ get; set; }
public string? game_version{ get; set; }
public string? gamemode{ get; set; }
public string? trackr_version{ get; set; }
public string? location{ get; set; }
public string? victim_ship { get; set; }
public string? victim { get; set; }
public string? enlisted { get; set; }
public string? rsi { get; set; }
public string? weapon { get; set; }
public string? method { get; set; }
public string? loadout_ship { get; set; }
public string? game_version { get; set; }
public string? gamemode { get; set; }
public string? trackr_version { get; set; }
public string? location { get; set; }
public long time { get; set; }
}
public static async Task<PlayerData?> GetPlayerData(string enemyPilot)
@ -30,12 +32,12 @@ public static class WebHandler
var ueePattern = new Regex("<p class=\"entry citizen-record\">\\n.*.<span class=\"label\">UEE Citizen Record<\\/span>\\n.*.<strong class=\"value\">#(?<UEERecord>\\d+)<\\/strong>");
var orgPattern = new Regex("\\/orgs\\/(?<OrgURL>[A-z0-9]+)\" .*\\>(?<OrgName>.*)<");
var pfpPattern = new Regex("/media/(.*)\"");
// Make web request to check player data
var playerData = new PlayerData();
var httpClient = new HttpClient();
var response = await httpClient.GetAsync($"https://robertsspaceindustries.com/en/citizens/{enemyPilot}");
if (response.StatusCode != HttpStatusCode.OK)
{
return null;
@ -47,20 +49,20 @@ public static class WebHandler
{
playerData.JoinDate = joinDataMatch.Groups[1].Value;
}
var ueeMatch = ueePattern.Match(content);
if (ueeMatch.Success)
{
playerData.UEERecord = ueeMatch.Groups["UEERecord"].Value == "n/a" ? "-1" : ueeMatch.Groups[1].Value;
}
var orgMatch = orgPattern.Match(content);
if (orgMatch.Success)
{
playerData.OrgName = orgMatch.Groups["OrgName"].Value;
playerData.OrgURL = "https://robertsspaceindustries.com/en/orgs/" + orgMatch.Groups["OrgURL"].Value;
}
var pfpMatch = pfpPattern.Match(content);
if (pfpMatch.Success)
{
@ -77,7 +79,7 @@ public static class WebHandler
return playerData;
}
public static async Task SubmitKill(KillData killData)
{
var apiKillData = new APIKillData
@ -88,18 +90,59 @@ public static class WebHandler
rsi = killData.RecordNumber,
weapon = killData.Weapon,
method = killData.Method,
// loadout_ship = LocalPlayerData.PlayerShip ?? "Unknown",
gamemode = killData.Mode,
loadout_ship = killData.Ship,
game_version = killData.GameVersion,
trackr_version = killData.TrackRver,
location = "Unknown"
location = "Unknown",
time = DateTimeOffset.UtcNow.ToUnixTimeSeconds()
};
if (string.IsNullOrEmpty(apiKillData.rsi))
{
apiKillData.rsi = "-1";
}
if (!apiKillData.enlisted.Contains(","))
{
//Get second whitespace in string
var index = apiKillData.enlisted.IndexOf(" ", apiKillData.enlisted.IndexOf(" ", StringComparison.Ordinal) + 1, StringComparison.Ordinal);
if (index != -1)
{
apiKillData.enlisted = apiKillData.enlisted.Insert(index, ",");
}
}
var httpClient = new HttpClient();
string jsonData = JsonSerializer.Serialize(killData);
string jsonData = JsonSerializer.Serialize(apiKillData);
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + ConfigManager.ApiKey);
httpClient.DefaultRequestHeaders.Add("User-Agent", "AutoTrackR2");
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
await httpClient.PostAsync(ConfigManager.ApiUrl + "register-kill", new StringContent(jsonData, Encoding.UTF8, "application/json"));
Console.WriteLine("\n=== Kill Submission Debug Info ===");
Console.WriteLine($"API URL: {ConfigManager.ApiUrl}register-kill");
Console.WriteLine($"Victim: {apiKillData.victim}");
Console.WriteLine($"Victim Ship: {apiKillData.victim_ship}");
Console.WriteLine($"Weapon: {apiKillData.weapon}");
Console.WriteLine($"Method: {apiKillData.method}");
Console.WriteLine($"Game Mode: {apiKillData.gamemode}");
Console.WriteLine($"Time (Unix): {apiKillData.time}");
Console.WriteLine($"Time (UTC): {DateTimeOffset.UtcNow}");
Console.WriteLine("=== End Debug Info ===\n");
var response = await httpClient.PostAsync(ConfigManager.ApiUrl + "register-kill", new StringContent(jsonData, Encoding.UTF8, "application/json"));
if (response.StatusCode != HttpStatusCode.OK)
{
Console.WriteLine("Failed to submit kill data:");
Console.WriteLine($"Status Code: {response.StatusCode}");
Console.WriteLine($"Response: {await response.Content.ReadAsStringAsync()}");
Console.WriteLine("Request Data:");
Console.WriteLine(jsonData);
}
else if (response.StatusCode == HttpStatusCode.OK)
{
Console.WriteLine("Successfully submitted kill data");
Console.WriteLine($"Response: {await response.Content.ReadAsStringAsync()}");
}
}
}

View file

@ -0,0 +1,2 @@
; AutoHotkey v2 script to press Win + Alt + G
Send("{LWin Down}{Alt Down}g{Alt Up}{LWin Up}") ; Simulate pressing Win + Alt + G

View file

@ -0,0 +1,2 @@
; AutoHotkey v2 script to press Alt + X
Send("{Alt Down}x{Alt Up}") ; Simulate pressing Alt + X

View file

@ -1,68 +0,0 @@
$repoUrl = "https://api.github.com/repos/BubbaGumpShrump/AutoTrackR2/releases/latest"
$outputMsi = Join-Path -Path $env:TEMP -ChildPath "AutoTrackR2_Setup.msi"
$tempFolder = Join-Path -Path $env:TEMP -ChildPath "AutoTrackR2"
$headers = @{ "User-Agent" = "Mozilla/5.0" }
# Fetch latest release data
$response = Invoke-RestMethod -Uri $repoUrl -Headers $headers
# Find the MSI asset
$asset = $response.assets | Where-Object { $_.name -eq "AutoTrackR2_Setup.msi" }
if ($asset -ne $null) {
$downloadUrl = $asset.browser_download_url
Write-Host "Downloading $($asset.name) from $downloadUrl"
Invoke-WebRequest -Uri $downloadUrl -OutFile $outputMsi -Headers $headers
Write-Host "Download completed: $outputMsi"
# Extract MSI contents
if (Test-Path $tempFolder) {
Remove-Item -Recurse -Force $tempFolder
}
Write-Host "Extracting MSI files..."
# Unpack the MSI installer to the temporary folder using msiexec with /a (administrative install) and /qb (quiet mode)
Start-Process msiexec.exe -ArgumentList "/a `"$outputMsi`" /qb TARGETDIR=`"$tempFolder`"" -Wait
# Generate checksums of extracted files and current directory files
$tempFiles = Get-ChildItem -Path $tempFolder -Recurse
$currentFiles = Get-ChildItem -Path (Get-Location) -Recurse
$tempChecksums = @{}
$currentChecksums = @{}
# Generate checksums for the temp folder files
foreach ($file in $tempFiles) {
if (-not $file.PSIsContainer) {
$tempChecksums[$file.FullName] = Get-FileHash $file.FullName -Algorithm SHA256
}
}
# Generate checksums for the current directory files
foreach ($file in $currentFiles) {
if (-not $file.PSIsContainer) {
$currentChecksums[$file.FullName] = Get-FileHash $file.FullName -Algorithm SHA256
}
}
# Compare and overwrite files if changed or missing, excluding update.ps1
foreach ($file in $tempChecksums.Keys) {
$relativePath = $file.Substring($tempFolder.Length)
# Skip the update.ps1 file
if ($relativePath -eq "\update.ps1") {
continue
}
$currentFilePath = Join-Path -Path (Get-Location) -ChildPath $relativePath
if (-not (Test-Path $currentFilePath) -or ($currentChecksums[$currentFilePath].Hash -ne $tempChecksums[$file].Hash)) {
Write-Host "Copying $relativePath to current directory"
Copy-Item -Path $file -Destination $currentFilePath -Force
}
}
Write-Host "Files are successfully updated."
} else {
Write-Host "AutoTrackR2_Setup.msi not found in the latest release."
}

View file

@ -1,779 +0,0 @@
"DeployProject"
{
"VSVersion" = "3:800"
"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"
"IsWebType" = "8:FALSE"
"ProjectName" = "8:AutoTrackR2_Setup"
"LanguageId" = "3:1033"
"CodePage" = "3:1252"
"UILanguageId" = "3:1033"
"SccProjectName" = "8:"
"SccLocalPath" = "8:"
"SccAuxPath" = "8:"
"SccProvider" = "8:"
"Hierarchy"
{
"Entry"
{
"MsmKey" = "8:_647AB2AE75964E44A2518F96EAF8D77D"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_C368A4F254AA4735B9679DC281414D2B"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
}
"Configurations"
{
"Debug"
{
"DisplayName" = "8:Debug"
"IsDebugOnly" = "11:TRUE"
"IsReleaseOnly" = "11:FALSE"
"OutputFilename" = "8:Debug\\AutoTrackR2_Setup.msi"
"PackageFilesAs" = "3:2"
"PackageFileSize" = "3:-2147483648"
"CabType" = "3:1"
"Compression" = "3:2"
"SignOutput" = "11:FALSE"
"CertificateFile" = "8:"
"PrivateKeyFile" = "8:"
"TimeStampServer" = "8:"
"InstallerBootstrapper" = "3:2"
"BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
{
"Enabled" = "11:TRUE"
"PromptEnabled" = "11:TRUE"
"PrerequisitesLocation" = "2:1"
"Url" = "8:"
"ComponentsUrl" = "8:"
"Items"
{
"{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
{
"Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
"ProductCode" = "8:.NETFramework,Version=v4.7.2"
}
}
}
}
"Release"
{
"DisplayName" = "8:Release"
"IsDebugOnly" = "11:FALSE"
"IsReleaseOnly" = "11:TRUE"
"OutputFilename" = "8:Release\\AutoTrackR2_Setup.msi"
"PackageFilesAs" = "3:2"
"PackageFileSize" = "3:-2147483648"
"CabType" = "3:1"
"Compression" = "3:2"
"SignOutput" = "11:FALSE"
"CertificateFile" = "8:"
"PrivateKeyFile" = "8:"
"TimeStampServer" = "8:"
"InstallerBootstrapper" = "3:2"
"BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"
{
"Enabled" = "11:TRUE"
"PromptEnabled" = "11:TRUE"
"PrerequisitesLocation" = "2:1"
"Url" = "8:"
"ComponentsUrl" = "8:"
"Items"
{
"{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:.NETFramework,Version=v4.7.2"
{
"Name" = "8:Microsoft .NET Framework 4.7.2 (x86 and x64)"
"ProductCode" = "8:.NETFramework,Version=v4.7.2"
}
}
}
}
}
"Deployable"
{
"CustomAction"
{
}
"DefaultFeature"
{
"Name" = "8:DefaultFeature"
"Title" = "8:"
"Description" = "8:"
}
"ExternalPersistence"
{
"LaunchCondition"
{
"{A06ECF26-33A3-4562-8140-9B0E340D4F24}:_276C583D35A94D9E9E0B547565F576F3"
{
"Name" = "8:.NET Core"
"Message" = "8:[VSDNETCOREMSG]"
"AllowLaterVersions" = "11:FALSE"
"InstallUrl" = "8:https://dotnet.microsoft.com/download/dotnet-core/[NetCoreVerMajorDotMinor]"
"IsNETCore" = "11:TRUE"
"Architecture" = "2:0"
"Runtime" = "2:0"
}
}
}
"File"
{
"{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_647AB2AE75964E44A2518F96EAF8D77D"
{
"SourcePath" = "8:..\\..\\..\\..\\Downloads\\AutoTrackR2.ico"
"TargetName" = "8:AutoTrackR2.ico"
"Tag" = "8:"
"Folder" = "8:_DEFDA4997C74429F99A6EA3C6AFECAD3"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
}
}
"FileType"
{
}
"Folder"
{
"{1525181F-901A-416C-8A58-119130FE478E}:_7E841D8A7938485C942B9E382D55836B"
{
"Name" = "8:#1916"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:DesktopFolder"
"Folders"
{
}
}
"{1525181F-901A-416C-8A58-119130FE478E}:_B9ADF94E042543B5B1221BEFB26FF6C3"
{
"Name" = "8:#1919"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:ProgramMenuFolder"
"Folders"
{
}
}
"{3C67513D-01DD-4637-8A68-80971EB9504F}:_DEFDA4997C74429F99A6EA3C6AFECAD3"
{
"DefaultLocation" = "8:[ProgramFiles64Folder][Manufacturer]\\[ProductName]"
"Name" = "8:#1925"
"AlwaysCreate" = "11:FALSE"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Property" = "8:TARGETDIR"
"Folders"
{
}
}
}
"LaunchCondition"
{
}
"Locator"
{
}
"MsiBootstrapper"
{
"LangId" = "3:1033"
"RequiresElevation" = "11:FALSE"
}
"Product"
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:AutoTrackR2_Setup"
"ProductCode" = "8:{EA6F4A24-93AD-4470-8F1F-B7C30E1B0F3B}"
"PackageCode" = "8:{9D14EC78-0C53-4066-8C2F-325ED9C6ACE4}"
"UpgradeCode" = "8:{0B78A147-D0DE-4F72-8906-A62611787CA7}"
"AspNetVersion" = "8:"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:FALSE"
"InstallAllUsers" = "11:TRUE"
"ProductVersion" = "8:2.0.6"
"Manufacturer" = "8:GrieferNET"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:discord.gg/griefernet"
"Title" = "8:AutoTrackR2_Setup"
"Subject" = "8:"
"ARPCONTACT" = "8:Fisk"
"Keywords" = "8:"
"ARPCOMMENTS" = "8:Star Citizen Kill Tracking App"
"ARPURLINFOABOUT" = "8:https://GrieferNET.org"
"ARPPRODUCTICON" = "8:"
"ARPIconIndex" = "3:0"
"SearchPath" = "8:"
"UseSystemSearchPath" = "11:TRUE"
"TargetPlatform" = "3:1"
"PreBuildEvent" = "8:"
"PostBuildEvent" = "8:"
"RunPostBuildEvent" = "3:0"
}
"Registry"
{
"HKLM"
{
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_2F3BD2498FC542DEB1965C4BC4085DD1"
{
"Name" = "8:Software"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_ED395372F679421DA161DF2744926FD3"
{
"Name" = "8:[Manufacturer]"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
}
"Values"
{
}
}
}
"Values"
{
}
}
}
}
"HKCU"
{
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_0DE359661B62468F9B0C73472B457E7B"
{
"Name" = "8:Software"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
"{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_A8ECE3DCE8AE4DCE8DBB79D6D95B92F2"
{
"Name" = "8:[Manufacturer]"
"Condition" = "8:"
"AlwaysCreate" = "11:FALSE"
"DeleteAtUninstall" = "11:FALSE"
"Transitive" = "11:FALSE"
"Keys"
{
}
"Values"
{
}
}
}
"Values"
{
}
}
}
}
"HKCR"
{
"Keys"
{
}
}
"HKU"
{
"Keys"
{
}
}
"HKPU"
{
"Keys"
{
}
}
}
"Sequences"
{
}
"Shortcut"
{
"{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_024675C1BAB04F3792A2073CDE2E501F"
{
"Name" = "8:AutoTrackR2"
"Arguments" = "8:"
"Description" = "8:"
"ShowCmd" = "3:1"
"IconIndex" = "3:0"
"Transitive" = "11:FALSE"
"Target" = "8:_C368A4F254AA4735B9679DC281414D2B"
"Folder" = "8:_B9ADF94E042543B5B1221BEFB26FF6C3"
"WorkingFolder" = "8:_DEFDA4997C74429F99A6EA3C6AFECAD3"
"Icon" = "8:_647AB2AE75964E44A2518F96EAF8D77D"
"Feature" = "8:"
}
"{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_C32D358287C9451C8D5F3F24777C476A"
{
"Name" = "8:AutoTrackR2"
"Arguments" = "8:"
"Description" = "8:"
"ShowCmd" = "3:1"
"IconIndex" = "3:0"
"Transitive" = "11:FALSE"
"Target" = "8:_C368A4F254AA4735B9679DC281414D2B"
"Folder" = "8:_7E841D8A7938485C942B9E382D55836B"
"WorkingFolder" = "8:_DEFDA4997C74429F99A6EA3C6AFECAD3"
"Icon" = "8:_647AB2AE75964E44A2518F96EAF8D77D"
"Feature" = "8:"
}
}
"UserInterface"
{
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_09D37C5DAF50432FAFE946DC2C89EECF"
{
"Name" = "8:#1902"
"Sequence" = "3:2"
"Attributes" = "3:3"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7197CF07741C42CC924DC7B4BBDCD776"
{
"Sequence" = "3:100"
"DisplayName" = "8:Finished"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_1C953A3AD06B4E2D8726A57902525E93"
{
"UseDynamicProperties" = "11:FALSE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim"
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_25A3388A62654BA2A95CBCF1EA37DA16"
{
"Name" = "8:#1901"
"Sequence" = "3:1"
"Attributes" = "3:2"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C23E70A1FA414511BFF4551092323DD2"
{
"Sequence" = "3:100"
"DisplayName" = "8:Progress"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"ShowProgress"
{
"Name" = "8:ShowProgress"
"DisplayName" = "8:#1009"
"Description" = "8:#1109"
"Type" = "3:5"
"ContextData" = "8:1;True=1;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:1"
"DefaultValue" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_271F117A8A994C278BBE51122646302C"
{
"Name" = "8:#1900"
"Sequence" = "3:2"
"Attributes" = "3:1"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_45664FEBC1F14857A58C61C0243CFF19"
{
"Sequence" = "3:300"
"DisplayName" = "8:Confirm Installation"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_75DBBE7328854B96BD74863ADFB756E9"
{
"Sequence" = "3:100"
"DisplayName" = "8:Welcome"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"CopyrightWarning"
{
"Name" = "8:CopyrightWarning"
"DisplayName" = "8:#1002"
"Description" = "8:#1102"
"Type" = "3:3"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:1"
"Value" = "8:#1202"
"DefaultValue" = "8:#1202"
"UsePlugInResources" = "11:TRUE"
}
"Welcome"
{
"Name" = "8:Welcome"
"DisplayName" = "8:#1003"
"Description" = "8:#1103"
"Type" = "3:3"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:1"
"Value" = "8:#1203"
"DefaultValue" = "8:#1203"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_8B9F468AAD25451AB530842E9E18CA91"
{
"Sequence" = "3:200"
"DisplayName" = "8:Installation Folder"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_A2E96B970BB24DA7B0690F48DB6FCAFA"
{
"UseDynamicProperties" = "11:FALSE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim"
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_BC406471F57045DD858B49D1AA5347A6"
{
"Name" = "8:#1900"
"Sequence" = "3:1"
"Attributes" = "3:1"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_074E57B64CA644A58139156EA9DCF5F8"
{
"Sequence" = "3:100"
"DisplayName" = "8:Welcome"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:0"
"UsePlugInResources" = "11:TRUE"
}
"CopyrightWarning"
{
"Name" = "8:CopyrightWarning"
"DisplayName" = "8:#1002"
"Description" = "8:#1102"
"Type" = "3:3"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:2"
"Value" = "8:GNU GENERAL PUBLIC LICENSE v3"
"DefaultValue" = "8:#1202"
"UsePlugInResources" = "11:TRUE"
}
"Welcome"
{
"Name" = "8:Welcome"
"DisplayName" = "8:#1003"
"Description" = "8:#1103"
"Type" = "3:3"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:1"
"Value" = "8:#1203"
"DefaultValue" = "8:#1203"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_299DEEF75E974038985108A67F002846"
{
"Sequence" = "3:200"
"DisplayName" = "8:Installation Folder"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"InstallAllUsersVisible"
{
"Name" = "8:InstallAllUsersVisible"
"DisplayName" = "8:#1059"
"Description" = "8:#1159"
"Type" = "3:5"
"ContextData" = "8:1;True=1;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:1"
"DefaultValue" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_B3648A393F14437C94AA44A5C900315A"
{
"Sequence" = "3:300"
"DisplayName" = "8:Confirm Installation"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_D847AC6800D0442595843337523D21BD"
{
"Name" = "8:#1901"
"Sequence" = "3:2"
"Attributes" = "3:2"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_FCB2747515C94BA68B985D2715B41786"
{
"Sequence" = "3:100"
"DisplayName" = "8:Progress"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"ShowProgress"
{
"Name" = "8:ShowProgress"
"DisplayName" = "8:#1009"
"Description" = "8:#1109"
"Type" = "3:5"
"ContextData" = "8:1;True=1;False=0"
"Attributes" = "3:0"
"Setting" = "3:0"
"Value" = "3:1"
"DefaultValue" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
"{DF760B10-853B-4699-99F2-AFF7185B4A62}:_F3C2D7B1337A40D09E957F167799C69B"
{
"Name" = "8:#1902"
"Sequence" = "3:1"
"Attributes" = "3:3"
"Dialogs"
{
"{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F49A9187003D4D8DBB8E8AAF2491D61B"
{
"Sequence" = "3:100"
"DisplayName" = "8:Finished"
"UseDynamicProperties" = "11:TRUE"
"IsDependency" = "11:FALSE"
"SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid"
"Properties"
{
"BannerBitmap"
{
"Name" = "8:BannerBitmap"
"DisplayName" = "8:#1001"
"Description" = "8:#1101"
"Type" = "3:8"
"ContextData" = "8:Bitmap"
"Attributes" = "3:4"
"Setting" = "3:1"
"UsePlugInResources" = "11:TRUE"
}
"UpdateText"
{
"Name" = "8:UpdateText"
"DisplayName" = "8:#1058"
"Description" = "8:#1158"
"Type" = "3:15"
"ContextData" = "8:"
"Attributes" = "3:0"
"Setting" = "3:1"
"Value" = "8:#1258"
"DefaultValue" = "8:#1258"
"UsePlugInResources" = "11:TRUE"
}
}
}
}
}
}
"MergeModule"
{
}
"ProjectOutput"
{
"{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_C368A4F254AA4735B9679DC281414D2B"
{
"SourcePath" = "8:..\\AutoTrackR2\\obj\\x64\\Release\\net9.0-windows\\apphost.exe"
"TargetName" = "8:"
"Tag" = "8:"
"Folder" = "8:_DEFDA4997C74429F99A6EA3C6AFECAD3"
"Condition" = "8:"
"Transitive" = "11:FALSE"
"Vital" = "11:TRUE"
"ReadOnly" = "11:FALSE"
"Hidden" = "11:FALSE"
"System" = "11:FALSE"
"Permanent" = "11:FALSE"
"SharedLegacy" = "11:FALSE"
"PackageAs" = "3:1"
"Register" = "3:1"
"Exclude" = "11:FALSE"
"IsDependency" = "11:FALSE"
"IsolateTo" = "8:"
"ProjectOutputGroupRegister" = "3:1"
"OutputConfiguration" = "8:"
"OutputGroupCanonicalName" = "8:PublishItems"
"OutputProjectGuid" = "8:{31093634-8FBB-4BC6-BEA4-DAD6C11404F3}"
"ShowKeyOutput" = "11:TRUE"
"ExcludeFilters"
{
}
}
}
}
}

148
README.md
View file

@ -1,90 +1,104 @@
AutoTrackR2 - Star Citizen Kill-Tracking Tool
# 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.
🚀 Features
Log File Integration: Point to Star Citizen's live game.log to track kills in real-time.
## Features
API Integration (Optional):
Configure a desired API to send kill data for external tracking or display.
Secure your data with an optional API key.
- **Log File Integration**: Point to Star Citizen's live game.log to track kills in real-time.
- **API Integration (Optional)**:
- Configure a desired API to send kill data for external tracking or display.
- Secure your data with an optional API key.
- **Video Clipping (Optional)**:
- Set a path to your clipping software to save kills automatically.
- **Visor Wipe Integration (Optional)**:
- Automates visor wiping using an AutoHotkey script (`visorwipe.ahk`).
- Requires AutoHotkey v2.
- Script must be placed in `%LOCALAPPDATA%\AutoTrackR2\`.
- **Video Record Integration (Optional)**:
- Customize the `videorecord.ahk` script for your specific video recording keybinds.
- Requires AutoHotkey v2.
- Script must be placed in `%LOCALAPPDATA%\AutoTrackR2\`
- **Offline Mode**:
- Disables API submissions. The tool will still scrape and display information from the RobertsSpaceIndustries website for the profile of whomever you have killed.
- **Custom Themes**:
- Easily add or modify themes by adjusting the `ThemeSlider_ValueChanged` function in `ConfigPage.xaml.cs`.
- Update the ThemeSlider maximum value in `ConfigPage.xaml` to reflect the number of themes added.
Video Clipping (Optional):
Set a path to your clipping software to save kills automatically.
## Setup
Visor Wipe Integration:
Automates visor wiping using an AutoHotkey script (visorwipe.ahk).
Requires AutoHotkey v2.
Script must be placed in C:\Users\<Username>\AppData\Local\AutoTrackR2\.
1. **Prerequisites**:
Video Record Integration:
Customize the videorecord.ahk script for your specific video recording keybinds.
Requires AutoHotkey v2.
Script must be placed in C:\Users\<Username>\AppData\Local\AutoTrackR2\
- Windows 10 or later
- .NET Framework 4.7.2 or higher
- Star Citizen installed
- AutoHotkey v2 (optional - only needed for visor wipe and video recording features):
- Download from the official website at https://www.autohotkey.com/
- Install AutoHotkey v2 (not v1.x as they are not compatible)
- Verify installation by right-clicking on your desktop and confirming "New > AutoHotkey v2 Script" appears in the context menu
Offline Mode:
Disables API submissions. The tool will still scrape and display information from the RobertsSpaceIndustries website for the profile of whomever you have killed.
2. **Installation Steps**:
Custom Themes:
Easily add or modify themes by adjusting the ThemeSlider_ValueChanged function in ConfigPage.xaml.cs.
Update the ThemeSlider maximum value in ConfigPage.xaml to reflect the number of themes added.
- Download the latest release package from the releases page
- Run the installer and follow the on-screen instructions
- Launch AutoTrackR2 after installation completes
📁 Configuration
Log File:
Specify the path to Star Citizen's game.log.
3. **Initial Configuration**:
- Open the Configuration panel within the application
- Set the path to your Star Citizen game.log file (typically found in `[Star Citizen Install Path]\LIVE\game.log`)
- Configure API settings if desired (leave blank for offline mode)
- Set up video clipping paths if using this feature
- If using AutoHotkey features, verify the scripts are properly placed in the `%LOCALAPPDATA%\AutoTrackR2\` location
API Settings (Optional):
## Configuration
API URL: Provide the endpoint for posting kill data.
- **Log File**:
- Specify the path to Star Citizen's `game.log`.
- **API Settings (Optional)**:
- API URL: Provide the endpoint for posting kill data.
- API Key: Secure access to the API with your unique key.
- **Video Clipping Path (Optional)**:
- Set the directory where your clipping software saves kills.
- **Visor Wipe Setup (Optional)**:
- Place `visorwipe.ahk` in `%LOCALAPPDATA%\AutoTrackR2\`.
- AutoHotkey v2 is required.
- **Video Recording Setup (Optional)**:
- Modify `videorecord.ahk` to use the keybinds of your video recording software.
- Place `videorecord.ahk` in `%LOCALAPPDATA%\AutoTrackR2\`.
- AutoHotkey v2 is required.
- **Offline Mode**:
- Enable to disable API submission. Restart the tracker to apply changes.
API Key: Secure access to the API with your unique key.
## Privacy & Data Usage
Video Clipping Path (Optional):
Set the directory where your clipping software saves kills.
- **No Personal Data Collection**:
- AutoTrackR2 does not collect or store personal or system information, other than common file paths to manage necessary files.
- **Access and Permissions**:
- The tool reads its own `config.ini` and the `game.log` from Star Citizen. It will also create a CSV file of all your logged kills, stored locally on your machine in the `%LOCALAPPDATA%\AutoTrackR2\` folder.
- **Optional Data Submission**:
- Data is only sent to an API if explicitly configured by the user. Offline Mode disables all outgoing submissions.
- **Killfeed Scraping**:
- The program scrapes the profile page of killed players to display their information locally. This feature remains active even in Offline Mode.
Visor Wipe Setup:
Place visorwipe.ahk in C:\Users\<Username>\AppData\Local\AutoTrackR2\.
AutoHotkey v2 is required.
## Customization
Video Recording Setup:
Modify videorecord.ahk to use the keybinds of your video recording software.
Place videorecord.ahk in C:\Users\<Username>\AppData\Local\AutoTrackR2\.
AutoHotkey v2 is required.
Offline Mode:
Enable to disable API submission. Restart the tracker to apply changes.
🛡️ Privacy & Data Usage
No Personal Data Collection:
AutoTrackR2 does not collect or store personal or system information, other than common file paths to manage necessary files.
Access and Permissions:
The tool reads its own config.ini and the game.log from Star Citizen. It will also create a CSV file of all your logged kills, stored locally on your machine in the AppData folder.
Optional Data Submission:
Data is only sent to an API if explicitly configured by the user. Offline Mode disables all outgoing submissions.
Killfeed Scraping:
The program scrapes the profile page of killed players to display their information locally. This feature remains active even in Offline Mode.
⚙️ Installation
Download the latest release from the releases page.
Follow the setup instructions included in the installer.
Configure the tool using the settings outlined above.
💡 Customization
To customize themes or behaviors:
Add Themes:
Update the ThemeSlider_ValueChanged function in ConfigPage.xaml.cs with your desired colors and logos.
Adjust the ThemeSlider maximum value in ConfigPage.xaml to match the number of themes.
- **Add Themes**:
- Update the `ThemeSlider_ValueChanged` function in `ConfigPage.xaml.cs` with your desired colors and logos.
- Adjust the ThemeSlider maximum value in `ConfigPage.xaml` to match the number of themes.
- **Modify AHK Scripts (Optional)**:
- Edit `visorwipe.ahk` and `videorecord.ahk` to fit your specific keybinds and preferences.
Modify AHK Scripts:
Edit visorwipe.ahk and videorecord.ahk to fit your specific keybinds and preferences.
## Support
📞 Support
For questions, issues, or feature requests, please visit discord.gg/griefernet.
For questions, issues, or feature requests:
- Join our Discord server: [discord.gg/griefernet](https://discord.gg/griefernet)
- Report bugs through the Discord's #autotrackr-bugs channel
- For urgent issues, you can escalate in Discord by tagging moderators
## License
🔒 License
AutoTrackR2 is released under the GNU v3 License.
GRIEFERNET VICTORY!