Update 0.01 D
This commit is contained in:
@@ -0,0 +1,80 @@
|
|||||||
|
using Lua;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Lithium
|
||||||
|
{
|
||||||
|
internal static class HotkeyHandler
|
||||||
|
{
|
||||||
|
private const int CAPSLOCK = 0x14;
|
||||||
|
|
||||||
|
private static bool nextSetHeld, prevSetHeld, refreshHeld, switchSideHeld, capsHeld;
|
||||||
|
private static MainWindow mainWindow;
|
||||||
|
|
||||||
|
public static void Start(MainWindow window)
|
||||||
|
{
|
||||||
|
mainWindow = window;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
HandleToggleCapsLock();
|
||||||
|
HandleNextSet();
|
||||||
|
HandlePrevSet();
|
||||||
|
HandleRefresh();
|
||||||
|
HandleSwitchSide();
|
||||||
|
Thread.Sleep(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleToggleCapsLock()
|
||||||
|
{
|
||||||
|
bool capsDown = Utils.IsPressed(CAPSLOCK);
|
||||||
|
if (capsDown && !capsHeld)
|
||||||
|
{
|
||||||
|
capsHeld = true;
|
||||||
|
mainWindow.SetRecoilEnabled(!mainWindow.IsRecoilEnabled);
|
||||||
|
}
|
||||||
|
if (!capsDown) capsHeld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleNextSet()
|
||||||
|
{
|
||||||
|
if (Utils.IsPressed(ConfigLoader.nextSetKey) && !nextSetHeld)
|
||||||
|
{
|
||||||
|
nextSetHeld = true;
|
||||||
|
mainWindow.HandleNextSet();
|
||||||
|
}
|
||||||
|
else if (!Utils.IsPressed(ConfigLoader.nextSetKey)) nextSetHeld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandlePrevSet()
|
||||||
|
{
|
||||||
|
if (Utils.IsPressed(ConfigLoader.prevSetKey) && !prevSetHeld)
|
||||||
|
{
|
||||||
|
prevSetHeld = true;
|
||||||
|
mainWindow.HandlePrevSet();
|
||||||
|
}
|
||||||
|
else if (!Utils.IsPressed(ConfigLoader.prevSetKey)) prevSetHeld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleRefresh()
|
||||||
|
{
|
||||||
|
if (Utils.IsPressed(ConfigLoader.refreshKey) && !refreshHeld)
|
||||||
|
{
|
||||||
|
refreshHeld = true;
|
||||||
|
mainWindow.HandleRefresh();
|
||||||
|
}
|
||||||
|
else if (!Utils.IsPressed(ConfigLoader.refreshKey)) refreshHeld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleSwitchSide()
|
||||||
|
{
|
||||||
|
if (Utils.IsPressed(ConfigLoader.switchSideKey) && !switchSideHeld)
|
||||||
|
{
|
||||||
|
switchSideHeld = true;
|
||||||
|
mainWindow.HandleSwitchSide();
|
||||||
|
}
|
||||||
|
else if (!Utils.IsPressed(ConfigLoader.switchSideKey)) switchSideHeld = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -113,7 +113,9 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</ApplicationDefinition>
|
</ApplicationDefinition>
|
||||||
|
<Compile Include="HotkeyHandler.cs" />
|
||||||
<Compile Include="RecoilControl.cs" />
|
<Compile Include="RecoilControl.cs" />
|
||||||
|
<Compile Include="RecoilEngine.cs" />
|
||||||
<Compile Include="Utils.cs" />
|
<Compile Include="Utils.cs" />
|
||||||
<Page Include="MainWindow.xaml">
|
<Page Include="MainWindow.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -149,7 +151,6 @@
|
|||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
<None Include="AppDomain.AssemblyResolve" />
|
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
<None Include="Properties\Settings.settings">
|
<None Include="Properties\Settings.settings">
|
||||||
<Generator>SettingsSingleFileGenerator</Generator>
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
|||||||
+163
-8
@@ -2,7 +2,7 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:wv="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
xmlns:wv="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
||||||
Title="Lithium" Height="570" Width="900"
|
Title="Lithium" Height="650" Width="1000"
|
||||||
Background="#1E1E1E"
|
Background="#1E1E1E"
|
||||||
WindowStyle="None"
|
WindowStyle="None"
|
||||||
AllowsTransparency="True">
|
AllowsTransparency="True">
|
||||||
@@ -110,6 +110,8 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Website Tab -->
|
<!-- Website Tab -->
|
||||||
<TabItem Header="Website">
|
<TabItem Header="Website">
|
||||||
<Grid Background="#252525">
|
<Grid Background="#252525">
|
||||||
@@ -130,33 +132,186 @@
|
|||||||
<!-- Operator Details -->
|
<!-- Operator Details -->
|
||||||
<StackPanel Grid.Row="0" Margin="20" VerticalAlignment="Top">
|
<StackPanel Grid.Row="0" Margin="20" VerticalAlignment="Top">
|
||||||
<TextBlock Text="Operator Name:" Foreground="White" FontSize="14" Margin="0,5"/>
|
<TextBlock Text="Operator Name:" Foreground="White" FontSize="14" Margin="0,5"/>
|
||||||
<TextBox x:Name="OperatorNameTextBox" Margin="0,5"/>
|
<TextBox x:Name="OperatorNameTextBox" Margin="0,5" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
|
||||||
<TextBlock Text="Recoil X:" Foreground="White" FontSize="14" Margin="0,5"/>
|
<TextBlock Text="Recoil X:" Foreground="White" FontSize="14" Margin="0,5"/>
|
||||||
<TextBox x:Name="RecoilXTextBox" Margin="0,5"/>
|
<TextBox x:Name="RecoilXTextBox" Margin="0,5" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
|
||||||
<TextBlock Text="Recoil Y:" Foreground="White" FontSize="14" Margin="0,5"/>
|
<TextBlock Text="Recoil Y:" Foreground="White" FontSize="14" Margin="0,5"/>
|
||||||
<TextBox x:Name="RecoilYTextBox" Margin="0,5"/>
|
<TextBox x:Name="RecoilYTextBox" Margin="0,5" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
|
||||||
<TextBlock Text="Type:" Foreground="White" FontSize="14" Margin="0,5"/>
|
<TextBlock Text="Type:" Foreground="White" FontSize="14" Margin="0,5"/>
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,5">
|
<StackPanel Orientation="Horizontal" Margin="0,5">
|
||||||
<RadioButton x:Name="AttackerRadioButton" Content="Attacker" IsChecked="True" Margin="0,0,10,0"/>
|
<RadioButton x:Name="AttackerRadioButton" Content="Attacker" IsChecked="True" Margin="0,0,10,0" Foreground="White"/>
|
||||||
<RadioButton x:Name="DefenderRadioButton" Content="Defender"/>
|
<RadioButton x:Name="DefenderRadioButton" Content="Defender" Foreground="White"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Button x:Name="ToggleCustomSetButton" Content="Toggle ON/OFF" Width="120" Margin="0,15" Click="ToggleCustomSet_Click"/>
|
<Button x:Name="ToggleCustomSetButton" Content="Toggle ON/OFF" Width="120" Margin="0,15" Click="ToggleCustomSet_Click" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<!-- Console & Publish -->
|
<!-- Console & Publish -->
|
||||||
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="20">
|
<StackPanel Grid.Row="1" Orientation="Vertical" Margin="20">
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,0,5">
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,0,5">
|
||||||
<Button Content="Publish Set" Width="120" Margin="0,0,10,0" Click="PublishSet_Click"/>
|
<Button Content="Publish Set" Width="120" Margin="0,0,10,0" Click="PublishSet_Click" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<Button Content="Save Set" Width="80" Margin="0,0,10,0" Click="SaveSet_Click" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<Button Content="Load Set" Width="80" Click="LoadSet_Click" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<TextBlock x:Name="CustomSetConsole" Foreground="Lime" FontFamily="Consolas" FontSize="12" Text="Set is OFF" Margin="0,5"/>
|
<TextBlock x:Name="CustomSetConsole" Foreground="Lime" FontFamily="Consolas" FontSize="12" Text="Set is OFF" Margin="0,5"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
|
|
||||||
|
<!-- Settings Tab -->
|
||||||
|
<TabItem Header="Settings">
|
||||||
|
<ScrollViewer VerticalScrollBarVisibility="Auto">
|
||||||
|
<Grid Background="#252525" Margin="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- Basic Settings -->
|
||||||
|
<GroupBox Grid.Row="0" Grid.ColumnSpan="2" Header="Basic Settings" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<StackPanel Margin="10">
|
||||||
|
<StackPanel Orientation="Horizontal" Margin="0,5">
|
||||||
|
<CheckBox x:Name="DebitFlagCheckBox" Content="Debit Flag (Fine-tuning)" Foreground="White" VerticalAlignment="Center"/>
|
||||||
|
<TextBlock Text="(1.282x X, 1.351x Y scaling)" Foreground="Gray" FontSize="11" Margin="10,0,0,0" VerticalAlignment="Center"/>
|
||||||
|
</StackPanel>
|
||||||
|
<CheckBox x:Name="BetaTestCheckBox" Content="Beta Test Mode (Merge All Operators)" Foreground="White" Margin="0,5"/>
|
||||||
|
<CheckBox x:Name="TtsEnabledCheckBox" Content="Text-to-Speech Enabled" Foreground="White" Margin="0,5"/>
|
||||||
|
<CheckBox x:Name="JitterEnabledCheckBox" Content="Jitter Enabled" Foreground="White" Margin="0,5"/>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- Key Bindings -->
|
||||||
|
<GroupBox Grid.Row="1" Grid.ColumnSpan="2" Header="Key Bindings (Virtual Key Codes)" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<Grid Margin="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Next Set:" Foreground="White" Margin="0,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="1" x:Name="NextSetKeyTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="2" Text="Previous Set:" Foreground="White" Margin="20,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="3" x:Name="PrevSetKeyTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="Refresh:" Foreground="White" Margin="0,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="1" x:Name="RefreshKeyTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="2" Text="Switch Side:" Foreground="White" Margin="20,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="3" x:Name="SwitchSideKeyTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
</Grid>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- Jitter Settings -->
|
||||||
|
<GroupBox Grid.Row="2" Grid.ColumnSpan="2" Header="Jitter Settings" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<Grid Margin="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Burst Time (ms):" Foreground="White" Margin="0,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="1" x:Name="JitterBurstTimeTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="2" Text="Cooldown (ms):" Foreground="White" Margin="20,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="3" x:Name="JitterCooldownTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
</Grid>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- User & Favorites -->
|
||||||
|
<GroupBox Grid.Row="3" Grid.ColumnSpan="2" Header="User & Favorites" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<Grid Margin="10">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="0" Text="Username:" Foreground="White" Margin="0,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="1" x:Name="UserNameTextBox" Margin="0,5" HorizontalAlignment="Stretch" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<TextBlock Grid.Row="0" Grid.Column="2" Text="Favorite Attackers:" Foreground="White" Margin="20,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="0" Grid.Column="3" x:Name="FavoriteAttackersTextBox" Margin="0,5" HorizontalAlignment="Stretch" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0" Text="Favorite Defenders:" Foreground="White" Margin="0,5,10,5" VerticalAlignment="Center"/>
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="1" x:Name="FavoriteDefendersTextBox" Margin="0,5" HorizontalAlignment="Stretch" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
</Grid>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- Console Settings -->
|
||||||
|
<GroupBox Grid.Row="4" Grid.Column="0" Header="Console Settings" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<StackPanel Margin="10">
|
||||||
|
<TextBlock Text="Text Color:" Foreground="White" Margin="0,5"/>
|
||||||
|
<ComboBox x:Name="TextColorComboBox" Width="120" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="Black" BorderBrush="#444">
|
||||||
|
<ComboBoxItem Content="White"/>
|
||||||
|
<ComboBoxItem Content="Magenta"/>
|
||||||
|
<ComboBoxItem Content="Cyan"/>
|
||||||
|
<ComboBoxItem Content="Green"/>
|
||||||
|
<ComboBoxItem Content="Yellow"/>
|
||||||
|
<ComboBoxItem Content="Red"/>
|
||||||
|
<ComboBoxItem Content="Blue"/>
|
||||||
|
<ComboBoxItem Content="Gray"/>
|
||||||
|
</ComboBox>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- Action Buttons -->
|
||||||
|
<GroupBox Grid.Row="4" Grid.Column="1" Header="Actions" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<StackPanel Margin="10">
|
||||||
|
<Button x:Name="SaveSettingsButton" Content="Save Settings" Click="SaveSettings_Click" Margin="0,5" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<Button x:Name="ReloadSettingsButton" Content="Reload Settings" Click="ReloadSettings_Click" Margin="0,5" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
<Button x:Name="ResetSettingsButton" Content="Reset to Defaults" Click="ResetSettings_Click" Margin="0,5" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
|
||||||
|
</StackPanel>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- Key Code Reference -->
|
||||||
|
<GroupBox Grid.Row="5" Grid.ColumnSpan="2" Header="Common Virtual Key Codes" Foreground="White" Margin="5" BorderBrush="#444">
|
||||||
|
<ScrollViewer MaxHeight="120" VerticalScrollBarVisibility="Auto">
|
||||||
|
<TextBlock x:Name="KeyCodeReferenceText" Foreground="LightGray" FontFamily="Consolas" FontSize="10" Margin="10" TextWrapping="Wrap">
|
||||||
|
0x01: Left Mouse, 0x02: Right Mouse, 0x04: Middle Mouse
|
||||||
|
0x05: XButton1, 0x06: XButton2
|
||||||
|
0x20: Space, 0x25: Left, 0x26: Up, 0x27: Right, 0x28: Down
|
||||||
|
0x30-0x39: 0-9, 0x41-0x5A: A-Z
|
||||||
|
0x70-0x87: F1-F24
|
||||||
|
Full list: https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
|
||||||
|
</TextBlock>
|
||||||
|
</ScrollViewer>
|
||||||
|
</GroupBox>
|
||||||
|
|
||||||
|
<!-- Status -->
|
||||||
|
<Border Grid.Row="6" Grid.ColumnSpan="2" Background="#2D2D2D" Margin="5" BorderBrush="#444" BorderThickness="1">
|
||||||
|
<TextBlock x:Name="SettingsStatusText" Foreground="Lime" FontFamily="Consolas" FontSize="11" Margin="10,5" Text="Settings loaded successfully" TextWrapping="Wrap"/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
</ScrollViewer>
|
||||||
|
</TabItem>
|
||||||
|
|
||||||
</TabControl>
|
</TabControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
+233
-113
@@ -6,164 +6,254 @@ using System.Text;
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Lithium
|
namespace Lithium
|
||||||
{
|
{
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
private bool customSetEnabled = false;
|
private bool customSetEnabled = false;
|
||||||
private bool nextSetHeld, prevSetHeld, refreshHeld, switchSideHeld, capsHeld;
|
|
||||||
private bool recoilEnabled = true;
|
private bool recoilEnabled = true;
|
||||||
|
|
||||||
private DateTime nextSetAllowed = DateTime.MinValue;
|
private DateTime nextSetAllowed = DateTime.MinValue;
|
||||||
private DateTime prevSetAllowed = DateTime.MinValue;
|
private DateTime prevSetAllowed = DateTime.MinValue;
|
||||||
|
|
||||||
private double remX = 0, remY = 0;
|
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
AppendConsole($"Initializing Lithium...");
|
AppendConsole("Initializing Lithium...");
|
||||||
ConfigLoader.LoadInitConfig();
|
ConfigLoader.LoadInitConfig();
|
||||||
OperatorSets.LoadOperatorSets();
|
OperatorSets.LoadOperatorSets();
|
||||||
AppendConsole($"Loaded Operators | Current Set: {OperatorSets.CurrentSet} | Side: {(OperatorSets.onAttackers ? "Attackers" : "Defenders")}");
|
|
||||||
|
AppendConsole(
|
||||||
|
$"Loaded Operators | Current Set: {OperatorSets.CurrentSet} | Side: {(OperatorSets.onAttackers ? "Attackers" : "Defenders")}"
|
||||||
|
);
|
||||||
|
|
||||||
Browser.Source = !string.IsNullOrEmpty(OperatorSets.ConfigExportUrl)
|
Browser.Source = !string.IsNullOrEmpty(OperatorSets.ConfigExportUrl)
|
||||||
? new Uri(OperatorSets.ConfigExportUrl)
|
? new Uri(OperatorSets.ConfigExportUrl)
|
||||||
: new Uri("https://jj.giggity.gay/exindex.html");
|
: new Uri("https://jj.giggity.gay/exindex.html");
|
||||||
|
|
||||||
|
// Load settings into UI
|
||||||
|
LoadSettingsToUI();
|
||||||
|
|
||||||
StartThread(HotkeyLoop);
|
StartThread(HotkeyLoop);
|
||||||
StartThread(RecoilLoop);
|
StartThread(RecoilLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void StartThread(ThreadStart action)
|
private void StartThread(ThreadStart action)
|
||||||
{
|
{
|
||||||
var thread = new Thread(action) { IsBackground = true };
|
var t = new Thread(action)
|
||||||
thread.Start();
|
{
|
||||||
|
IsBackground = true
|
||||||
|
};
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RecoilLoop() => RecoilEngine.Start();
|
||||||
|
|
||||||
|
private void HotkeyLoop() => HotkeyHandler.Start(this);
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// SETTINGS MANAGEMENT
|
||||||
|
// ============================================================
|
||||||
|
private void LoadSettingsToUI()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Basic settings
|
||||||
|
DebitFlagCheckBox.IsChecked = ConfigLoader.debitFlag1;
|
||||||
|
BetaTestCheckBox.IsChecked = ConfigLoader.betaTest;
|
||||||
|
TtsEnabledCheckBox.IsChecked = ConfigLoader.ttsEnabled;
|
||||||
|
JitterEnabledCheckBox.IsChecked = ConfigLoader.jitterEnabled;
|
||||||
|
|
||||||
|
// Key bindings
|
||||||
|
NextSetKeyTextBox.Text = $"0x{ConfigLoader.nextSetKey:X2}";
|
||||||
|
PrevSetKeyTextBox.Text = $"0x{ConfigLoader.prevSetKey:X2}";
|
||||||
|
RefreshKeyTextBox.Text = $"0x{ConfigLoader.refreshKey:X2}";
|
||||||
|
SwitchSideKeyTextBox.Text = $"0x{ConfigLoader.switchSideKey:X2}";
|
||||||
|
|
||||||
|
// Jitter settings
|
||||||
|
JitterBurstTimeTextBox.Text = ConfigLoader.jitterBurstTime.ToString();
|
||||||
|
JitterCooldownTextBox.Text = ConfigLoader.jitterCooldown.ToString();
|
||||||
|
|
||||||
|
// User & favorites
|
||||||
|
UserNameTextBox.Text = ConfigLoader.userName ?? "";
|
||||||
|
FavoriteAttackersTextBox.Text = ConfigLoader.favoriteAttackers ?? "";
|
||||||
|
FavoriteDefendersTextBox.Text = ConfigLoader.favoriteDefenders ?? "";
|
||||||
|
|
||||||
|
// Console color
|
||||||
|
foreach (ComboBoxItem item in TextColorComboBox.Items)
|
||||||
|
{
|
||||||
|
if (item.Content.ToString() == ConfigLoader.textColor.ToString())
|
||||||
|
{
|
||||||
|
TextColorComboBox.SelectedItem = item;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsStatusText.Text = "Settings loaded successfully";
|
||||||
|
SettingsStatusText.Foreground = new SolidColorBrush(Colors.Lime);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SettingsStatusText.Text = $"Error loading settings: {ex.Message}";
|
||||||
|
SettingsStatusText.Foreground = new SolidColorBrush(Colors.Red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveSettings_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string configContent = GenerateConfigContent();
|
||||||
|
File.WriteAllText("init.config", configContent);
|
||||||
|
|
||||||
|
// Reload configuration
|
||||||
|
ConfigLoader.LoadInitConfig();
|
||||||
|
LoadSettingsToUI();
|
||||||
|
|
||||||
|
SettingsStatusText.Text = "Settings saved and reloaded successfully!";
|
||||||
|
SettingsStatusText.Foreground = new SolidColorBrush(Colors.Lime);
|
||||||
|
AppendConsole("Settings updated from UI");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
SettingsStatusText.Text = $"Error saving settings: {ex.Message}";
|
||||||
|
SettingsStatusText.Foreground = new SolidColorBrush(Colors.Red);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReloadSettings_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ConfigLoader.LoadInitConfig();
|
||||||
|
LoadSettingsToUI();
|
||||||
|
SettingsStatusText.Text = "Settings reloaded from file";
|
||||||
|
SettingsStatusText.Foreground = new SolidColorBrush(Colors.Lime);
|
||||||
|
AppendConsole("Settings reloaded from init.config");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetSettings_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// Reset to defaults
|
||||||
|
ConfigLoader.debitFlag1 = false;
|
||||||
|
ConfigLoader.betaTest = false;
|
||||||
|
ConfigLoader.ttsEnabled = true;
|
||||||
|
ConfigLoader.jitterEnabled = false;
|
||||||
|
ConfigLoader.nextSetKey = 0x05;
|
||||||
|
ConfigLoader.prevSetKey = 0x06;
|
||||||
|
ConfigLoader.refreshKey = 0x50;
|
||||||
|
ConfigLoader.switchSideKey = 0x4D;
|
||||||
|
ConfigLoader.jitterBurstTime = 1800;
|
||||||
|
ConfigLoader.jitterCooldown = 3000;
|
||||||
|
ConfigLoader.userName = null;
|
||||||
|
ConfigLoader.favoriteAttackers = null;
|
||||||
|
ConfigLoader.favoriteDefenders = null;
|
||||||
|
ConfigLoader.textColor = System.ConsoleColor.Magenta;
|
||||||
|
|
||||||
|
LoadSettingsToUI();
|
||||||
|
SettingsStatusText.Text = "Settings reset to defaults (save to apply)";
|
||||||
|
SettingsStatusText.Foreground = new SolidColorBrush(Colors.Yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateConfigContent()
|
||||||
|
{
|
||||||
|
return $@"-- Lithium Configuration File
|
||||||
|
-- Generated from UI on {DateTime.Now}
|
||||||
|
|
||||||
|
-- Basic Settings
|
||||||
|
debitFlag1 = {DebitFlagCheckBox.IsChecked.ToString().ToLower()}
|
||||||
|
betaTest = {BetaTestCheckBox.IsChecked.ToString().ToLower()}
|
||||||
|
ttsEnabled = {TtsEnabledCheckBox.IsChecked.ToString().ToLower()}
|
||||||
|
jitterEnabled = {JitterEnabledCheckBox.IsChecked.ToString().ToLower()}
|
||||||
|
|
||||||
|
-- Key Bindings (Virtual Key Codes)
|
||||||
|
nextSetKey = {ParseKeyCode(NextSetKeyTextBox.Text)}
|
||||||
|
prevSetKey = {ParseKeyCode(PrevSetKeyTextBox.Text)}
|
||||||
|
refreshKey = {ParseKeyCode(RefreshKeyTextBox.Text)}
|
||||||
|
switchSideKey = {ParseKeyCode(SwitchSideKeyTextBox.Text)}
|
||||||
|
|
||||||
|
-- Jitter Settings
|
||||||
|
jitterBurstTime = {int.Parse(JitterBurstTimeTextBox.Text)}
|
||||||
|
jitterCooldown = {int.Parse(JitterCooldownTextBox.Text)}
|
||||||
|
|
||||||
|
-- User & Favorites
|
||||||
|
userName = ""{UserNameTextBox.Text}""
|
||||||
|
favoriteAttackers = ""{FavoriteAttackersTextBox.Text}""
|
||||||
|
favoriteDefenders = ""{FavoriteDefendersTextBox.Text}""
|
||||||
|
|
||||||
|
-- Console Settings
|
||||||
|
textColor = {((ComboBoxItem)TextColorComboBox.SelectedItem)?.Content.ToString() ?? "Magenta"}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ParseKeyCode(string text)
|
||||||
|
{
|
||||||
|
if (text.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(text, 16);
|
||||||
|
}
|
||||||
|
return int.Parse(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// RECOIL ENGINE (fractional X/Y tracking for precise Ricoh-style movement)
|
// HANDLERS CALLED BY HOTKEYHANDLER
|
||||||
// ============================================================
|
// ============================================================
|
||||||
private void RecoilLoop()
|
public void SetRecoilEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
const int RIGHT_MOUSE = 0x02;
|
recoilEnabled = enabled;
|
||||||
|
AppendConsole(enabled ? "Recoil Enabled" : "Recoil Disabled");
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (!recoilEnabled)
|
|
||||||
{
|
|
||||||
Thread.Sleep(1);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Utils.IsPressed(ConfigLoader.shootKey) && Utils.IsPressed(RIGHT_MOUSE))
|
public bool IsRecoilEnabled => recoilEnabled;
|
||||||
|
|
||||||
|
public void HandleNextSet()
|
||||||
{
|
{
|
||||||
var recoil = OperatorSets.GetCurrentRecoil();
|
if (DateTime.Now < nextSetAllowed) return;
|
||||||
|
|
||||||
double moveX = recoil.recoilX + remX;
|
|
||||||
double moveY = recoil.recoilY + remY;
|
|
||||||
|
|
||||||
int ix = (int)Math.Round(moveX);
|
|
||||||
int iy = (int)Math.Round(moveY);
|
|
||||||
|
|
||||||
remX = moveX - ix;
|
|
||||||
remY = moveY - iy;
|
|
||||||
|
|
||||||
Utils.MoveMouse(ix, iy);
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// HOTKEY LOOP
|
|
||||||
// ============================================================
|
|
||||||
private void HotkeyLoop()
|
|
||||||
{
|
|
||||||
const int CAPSLOCK = 0x14;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
HandleToggleCapsLock(CAPSLOCK);
|
|
||||||
HandleNextSet();
|
|
||||||
HandlePrevSet();
|
|
||||||
HandleRefresh();
|
|
||||||
HandleSwitchSide();
|
|
||||||
Thread.Sleep(8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleToggleCapsLock(int capsKey)
|
|
||||||
{
|
|
||||||
bool capsDown = Utils.IsPressed(capsKey);
|
|
||||||
if (capsDown && !capsHeld)
|
|
||||||
{
|
|
||||||
capsHeld = true;
|
|
||||||
recoilEnabled = !recoilEnabled;
|
|
||||||
AppendConsole(recoilEnabled ? "Recoil Enabled" : "Recoil Disabled");
|
|
||||||
}
|
|
||||||
if (!capsDown) capsHeld = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleNextSet()
|
|
||||||
{
|
|
||||||
if (Utils.IsPressed(ConfigLoader.nextSetKey) && !nextSetHeld && DateTime.Now >= nextSetAllowed)
|
|
||||||
{
|
|
||||||
nextSetHeld = true;
|
|
||||||
nextSetAllowed = DateTime.Now.AddMilliseconds(200);
|
nextSetAllowed = DateTime.Now.AddMilliseconds(200);
|
||||||
OperatorSets.NextSet();
|
OperatorSets.NextSet();
|
||||||
// Only announce operator, no side
|
|
||||||
AppendConsole($"Next Set → {OperatorSets.CurrentSet}");
|
AppendConsole($"Next Set → {OperatorSets.CurrentSet}");
|
||||||
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
||||||
}
|
}
|
||||||
else if (!Utils.IsPressed(ConfigLoader.nextSetKey)) nextSetHeld = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandlePrevSet()
|
public void HandlePrevSet()
|
||||||
{
|
{
|
||||||
if (Utils.IsPressed(ConfigLoader.prevSetKey) && !prevSetHeld && DateTime.Now >= prevSetAllowed)
|
if (DateTime.Now < prevSetAllowed) return;
|
||||||
{
|
|
||||||
prevSetHeld = true;
|
|
||||||
prevSetAllowed = DateTime.Now.AddMilliseconds(200);
|
prevSetAllowed = DateTime.Now.AddMilliseconds(200);
|
||||||
OperatorSets.PreviousSet();
|
OperatorSets.PreviousSet();
|
||||||
// Only announce operator, no side
|
|
||||||
AppendConsole($"Previous Set → {OperatorSets.CurrentSet}");
|
AppendConsole($"Previous Set → {OperatorSets.CurrentSet}");
|
||||||
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
||||||
}
|
}
|
||||||
else if (!Utils.IsPressed(ConfigLoader.prevSetKey)) prevSetHeld = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleRefresh()
|
public void HandleRefresh()
|
||||||
{
|
{
|
||||||
if (Utils.IsPressed(ConfigLoader.refreshKey) && !refreshHeld)
|
string oldSet = OperatorSets.CurrentSet;
|
||||||
{
|
bool oldSide = OperatorSets.onAttackers;
|
||||||
refreshHeld = true;
|
|
||||||
string current = OperatorSets.CurrentSet; // store current
|
|
||||||
OperatorSets.LoadOperatorSets();
|
OperatorSets.LoadOperatorSets();
|
||||||
OperatorSets.SetCurrentSet(current); // restore operator after refresh
|
|
||||||
AppendConsole($"Reloaded config | Current Set: {OperatorSets.CurrentSet} | Side: {(OperatorSets.onAttackers ? "Attackers" : "Defenders")}");
|
OperatorSets.SetCurrentSet(oldSet);
|
||||||
|
OperatorSets.onAttackers = oldSide;
|
||||||
|
|
||||||
|
AppendConsole(
|
||||||
|
$"Reloaded config | Current Set: {OperatorSets.CurrentSet} | Side: {(OperatorSets.onAttackers ? "Attackers" : "Defenders")}"
|
||||||
|
);
|
||||||
|
|
||||||
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
||||||
}
|
}
|
||||||
else if (!Utils.IsPressed(ConfigLoader.refreshKey)) refreshHeld = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleSwitchSide()
|
public void HandleSwitchSide()
|
||||||
{
|
{
|
||||||
if (Utils.IsPressed(ConfigLoader.switchSideKey) && !switchSideHeld)
|
|
||||||
{
|
|
||||||
switchSideHeld = true;
|
|
||||||
OperatorSets.SwitchSide();
|
OperatorSets.SwitchSide();
|
||||||
// Announce operator + side only on side switch
|
|
||||||
AppendConsole($"Switched side → {(OperatorSets.onAttackers ? "Attackers" : "Defenders")} | Current Set: {OperatorSets.CurrentSet}");
|
AppendConsole($"Switched side → {(OperatorSets.onAttackers ? "Attackers" : "Defenders")} | Current Set: {OperatorSets.CurrentSet}");
|
||||||
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
Utils.SafeSpeak(OperatorSets.CurrentSet);
|
||||||
}
|
}
|
||||||
else if (!Utils.IsPressed(ConfigLoader.switchSideKey)) switchSideHeld = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// UI CONSOLE
|
// UI CONSOLE
|
||||||
@@ -174,6 +264,7 @@ namespace Lithium
|
|||||||
{
|
{
|
||||||
ConsoleOutput.Text += msg + Environment.NewLine;
|
ConsoleOutput.Text += msg + Environment.NewLine;
|
||||||
ConsoleScroll.ScrollToBottom();
|
ConsoleScroll.ScrollToBottom();
|
||||||
|
Utils.AutoClearIfNearBottom();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,25 +293,40 @@ namespace Lithium
|
|||||||
|
|
||||||
double.TryParse(RecoilXTextBox.Text, out double x);
|
double.TryParse(RecoilXTextBox.Text, out double x);
|
||||||
double.TryParse(RecoilYTextBox.Text, out double y);
|
double.TryParse(RecoilYTextBox.Text, out double y);
|
||||||
|
|
||||||
string type = AttackerRadioButton.IsChecked == true ? "attackers" : "defenders";
|
string type = AttackerRadioButton.IsChecked == true ? "attackers" : "defenders";
|
||||||
|
|
||||||
var payload = new { type, name, recoilX = x, recoilY = y };
|
var payload = new
|
||||||
|
{
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
recoilX = x,
|
||||||
|
recoilY = y
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using HttpClient client = new HttpClient();
|
using HttpClient client = new HttpClient();
|
||||||
string json = JsonSerializer.Serialize(payload);
|
string json = JsonSerializer.Serialize(payload);
|
||||||
var response = await client.PostAsync("https://jj.giggity.gay/api/global/add",
|
|
||||||
new StringContent(json, Encoding.UTF8, "application/json"));
|
var response = await client.PostAsync(
|
||||||
|
"https://jj.giggity.gay/api/global/add",
|
||||||
|
new StringContent(json, Encoding.UTF8, "application/json")
|
||||||
|
);
|
||||||
|
|
||||||
if (response.IsSuccessStatusCode)
|
if (response.IsSuccessStatusCode)
|
||||||
UpdateCustomSetConsole($"Successfully published: {name} ({type}) X:{x} Y:{y}");
|
{
|
||||||
|
UpdateCustomSetConsole($"Published: {name} ({type}) X:{x} Y:{y}");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
UpdateCustomSetConsole($"Failed: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}");
|
{
|
||||||
|
string body = await response.Content.ReadAsStringAsync();
|
||||||
|
UpdateCustomSetConsole($"HTTP Error {response.StatusCode}: {body}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
UpdateCustomSetConsole("Error publishing set: " + ex.Message);
|
UpdateCustomSetConsole("Error: " + ex.Message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,11 +334,17 @@ namespace Lithium
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.WriteAllText("custom_set.txt",
|
File.WriteAllText(
|
||||||
$"{OperatorNameTextBox.Text}|{RecoilXTextBox.Text}|{RecoilYTextBox.Text}|{(AttackerRadioButton.IsChecked == true ? "attacker" : "defender")}");
|
"custom_set.txt",
|
||||||
|
$"{OperatorNameTextBox.Text}|{RecoilXTextBox.Text}|{RecoilYTextBox.Text}|{(AttackerRadioButton.IsChecked == true ? "attacker" : "defender")}"
|
||||||
|
);
|
||||||
|
|
||||||
UpdateCustomSetConsole("Custom set saved");
|
UpdateCustomSetConsole("Custom set saved");
|
||||||
}
|
}
|
||||||
catch { UpdateCustomSetConsole("Failed to save custom set"); }
|
catch
|
||||||
|
{
|
||||||
|
UpdateCustomSetConsole("Failed to save custom set");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadSet_Click(object sender, RoutedEventArgs e)
|
private void LoadSet_Click(object sender, RoutedEventArgs e)
|
||||||
@@ -246,11 +358,13 @@ namespace Lithium
|
|||||||
}
|
}
|
||||||
|
|
||||||
string[] parts = File.ReadAllText("custom_set.txt").Split('|');
|
string[] parts = File.ReadAllText("custom_set.txt").Split('|');
|
||||||
if (parts.Length != 4) throw new Exception("Invalid file");
|
if (parts.Length != 4)
|
||||||
|
throw new Exception("Invalid file");
|
||||||
|
|
||||||
OperatorNameTextBox.Text = parts[0];
|
OperatorNameTextBox.Text = parts[0];
|
||||||
RecoilXTextBox.Text = parts[1];
|
RecoilXTextBox.Text = parts[1];
|
||||||
RecoilYTextBox.Text = parts[2];
|
RecoilYTextBox.Text = parts[2];
|
||||||
|
|
||||||
if (parts[3].Equals("attacker", StringComparison.OrdinalIgnoreCase))
|
if (parts[3].Equals("attacker", StringComparison.OrdinalIgnoreCase))
|
||||||
AttackerRadioButton.IsChecked = true;
|
AttackerRadioButton.IsChecked = true;
|
||||||
else
|
else
|
||||||
@@ -258,20 +372,26 @@ namespace Lithium
|
|||||||
|
|
||||||
UpdateCustomSetConsole("Custom set loaded");
|
UpdateCustomSetConsole("Custom set loaded");
|
||||||
}
|
}
|
||||||
catch { UpdateCustomSetConsole("Failed to load custom set"); }
|
catch
|
||||||
|
{
|
||||||
|
UpdateCustomSetConsole("Failed to load custom set");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// WINDOW CONTROLS
|
||||||
|
// ============================================================
|
||||||
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
|
private void TitleBar_MouseDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.ChangedButton == MouseButton.Left) DragMove();
|
if (e.ChangedButton == MouseButton.Left)
|
||||||
|
DragMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Minimize_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized;
|
private void Minimize_Click(object sender, RoutedEventArgs e) =>
|
||||||
|
WindowState = WindowState.Minimized;
|
||||||
|
|
||||||
private void MaximizeRestore_Click(object sender, RoutedEventArgs e)
|
private void MaximizeRestore_Click(object sender, RoutedEventArgs e) =>
|
||||||
{
|
|
||||||
WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
|
WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
|
||||||
}
|
|
||||||
|
|
||||||
private void Close_Click(object sender, RoutedEventArgs e) => Close();
|
private void Close_Click(object sender, RoutedEventArgs e) => Close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Lua
|
||||||
|
{
|
||||||
|
internal static class RecoilEngine
|
||||||
|
{
|
||||||
|
private const int VK_LBUTTON = 0x01;
|
||||||
|
private const int VK_RBUTTON = 0x02;
|
||||||
|
|
||||||
|
private static Random rng = new Random();
|
||||||
|
private static bool jitterActive = false;
|
||||||
|
private static int jitterStart = 0;
|
||||||
|
private static int lastJitterEnd = 0;
|
||||||
|
private static double remX, remY;
|
||||||
|
private static double jitterMultX, jitterMultY;
|
||||||
|
|
||||||
|
public static void Start()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (Utils.IsCapsLockOn() && Utils.IsPressed(VK_RBUTTON))
|
||||||
|
{
|
||||||
|
HandleRecoilTick();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
remX = remY = 0;
|
||||||
|
jitterActive = false;
|
||||||
|
}
|
||||||
|
Thread.Sleep(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleRecoilTick()
|
||||||
|
{
|
||||||
|
if (!Utils.IsPressed(VK_LBUTTON))
|
||||||
|
return;
|
||||||
|
|
||||||
|
string setName = OperatorSets.CurrentSet;
|
||||||
|
|
||||||
|
if (!OperatorSets.mergedSets.TryGetValue(setName, out var recoil))
|
||||||
|
return;
|
||||||
|
|
||||||
|
int now = Environment.TickCount;
|
||||||
|
|
||||||
|
HandleJitter(now);
|
||||||
|
ApplyRecoil(recoil, now);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HandleJitter(int now)
|
||||||
|
{
|
||||||
|
if (ConfigLoader.jitterEnabled)
|
||||||
|
{
|
||||||
|
if (!jitterActive && now - lastJitterEnd >= ConfigLoader.jitterCooldown)
|
||||||
|
{
|
||||||
|
jitterActive = true;
|
||||||
|
jitterStart = now;
|
||||||
|
|
||||||
|
double strength = 0.1 + rng.NextDouble() * 0.8;
|
||||||
|
jitterMultX = jitterMultY = 0;
|
||||||
|
|
||||||
|
switch (rng.Next(1, 5))
|
||||||
|
{
|
||||||
|
case 1: jitterMultX = -strength; break;
|
||||||
|
case 2: jitterMultX = strength; break;
|
||||||
|
case 3: jitterMultY = -strength; break;
|
||||||
|
case 4: jitterMultY = strength; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jitterActive && now - jitterStart >= ConfigLoader.jitterBurstTime)
|
||||||
|
{
|
||||||
|
jitterActive = false;
|
||||||
|
lastJitterEnd = now;
|
||||||
|
jitterMultX = jitterMultY = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ApplyRecoil((double recoilX, double recoilY) recoil, int now)
|
||||||
|
{
|
||||||
|
double jitterX = recoil.recoilX * jitterMultX;
|
||||||
|
double jitterY = recoil.recoilY * jitterMultY;
|
||||||
|
|
||||||
|
double moveX = recoil.recoilX + remX + jitterX;
|
||||||
|
double moveY = recoil.recoilY + remY + jitterY;
|
||||||
|
|
||||||
|
if (ConfigLoader.debitFlag1)
|
||||||
|
{
|
||||||
|
moveX *= 1.282;
|
||||||
|
moveY *= 1.351;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ix = (int)Math.Round(moveX);
|
||||||
|
int iy = (int)Math.Round(moveY);
|
||||||
|
|
||||||
|
remX = moveX - ix;
|
||||||
|
remY = moveY - iy;
|
||||||
|
|
||||||
|
Utils.MoveMouse(ix, iy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-8
@@ -1,5 +1,4 @@
|
|||||||
// Utils.cs (patched)
|
using System;
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Speech.Synthesis;
|
using System.Speech.Synthesis;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -16,8 +15,8 @@ namespace Lua
|
|||||||
[DllImport("user32.dll")] public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, UIntPtr dwExtraInfo);
|
[DllImport("user32.dll")] public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, UIntPtr dwExtraInfo);
|
||||||
public const uint MOUSEEVENTF_MOVE = 0x0001;
|
public const uint MOUSEEVENTF_MOVE = 0x0001;
|
||||||
|
|
||||||
const int VK_CAPITAL = 0x14;
|
private const int VK_CAPITAL = 0x14;
|
||||||
static bool previousCapsState;
|
private static bool previousCapsState;
|
||||||
|
|
||||||
public static void InitializeCapsState()
|
public static void InitializeCapsState()
|
||||||
{
|
{
|
||||||
@@ -73,15 +72,12 @@ namespace Lua
|
|||||||
: $"🚀 Standard Mode Enabled | Current Set: {OperatorSets.CurrentSet}";
|
: $"🚀 Standard Mode Enabled | Current Set: {OperatorSets.CurrentSet}";
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------
|
|
||||||
// NEW: Auto console clear when near bottom
|
|
||||||
// -----------------------------------------------------
|
|
||||||
public static void AutoClearIfNearBottom()
|
public static void AutoClearIfNearBottom()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int current = Console.CursorTop;
|
int current = Console.CursorTop;
|
||||||
int limit = Console.WindowHeight - 2; // keep 2-row buffer
|
int limit = Console.WindowHeight - 2;
|
||||||
|
|
||||||
if (current >= limit)
|
if (current >= limit)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user