🚀 Added (New Features)

• Random Offset feature: Applies random X/Y offset values on each set activation (both mouse buttons pressed)
• Each axis gets independent random values within configurable range (e.g., 0.003 and 0.008)
• New random values generated on every activation
• Toggle to enable/disable the feature

🛠️ Fixed (Bugs resolved)
• Replaced jitter system (burst/cooldown) with simpler random offset system

📂 File-Level Changes Summary
• ConfigLoader.cs: Added randomOffsetEnabled, randomOffsetMin, randomOffsetMax settings
• RecoilEngine.cs: Implemented random offset logic with activation detection
• MainWindow.xaml: Replaced Jitter Settings with Random Offset Settings UI
• MainWindow.xaml.cs: Updated LoadSettingsToUI, GenerateConfigContent, ResetSettings_Click
• helper.cs: Added ParseDoubleFromAssignment helper method
This commit is contained in:
TJhost
2026-09-03 16:00:27 -04:00
parent 86c231773d
commit ae3b4164f3
5 changed files with 96 additions and 85 deletions
+13 -13
View File
@@ -42,11 +42,11 @@ namespace Lua
public static string userName = null; public static string userName = null;
// AA0013 // AA0013
public static bool jitterEnabled = false; public static bool randomOffsetEnabled = false;
// AA0014 // AA0014
public static int jitterBurstTime = 1800; public static double randomOffsetMin = 0.0001;
// AA0015 // AA0015
public static int jitterCooldown = 3000; public static double randomOffsetMax = 0.001;
// AA0016 // AA0016
public static ConsoleColor textColor = ConsoleColor.Magenta; public static ConsoleColor textColor = ConsoleColor.Magenta;
@@ -63,9 +63,9 @@ namespace Lua
favoriteAttackers = null; favoriteAttackers = null;
favoriteDefenders = null; favoriteDefenders = null;
userName = null; userName = null;
jitterEnabled = false; randomOffsetEnabled = false;
jitterBurstTime = 1800; randomOffsetMin = 0.0001;
jitterCooldown = 3000; randomOffsetMax = 0.001;
textColor = ConsoleColor.Magenta; textColor = ConsoleColor.Magenta;
quickSwaps.Clear(); quickSwaps.Clear();
@@ -108,13 +108,13 @@ namespace Lua
favoriteDefenders = s2; favoriteDefenders = s2;
else if (Helper.ParseStringFromAssignment(line, "userName", out var s3)) else if (Helper.ParseStringFromAssignment(line, "userName", out var s3))
userName = s3; userName = s3;
// AA0025 // AA0025 - Random Offset Settings
else if (Helper.ParseBoolFromAssignment(line, "jitterEnabled", out var jb)) else if (Helper.ParseBoolFromAssignment(line, "randomOffsetEnabled", out var roe))
jitterEnabled = jb; randomOffsetEnabled = roe;
else if (Helper.ParseIntFromAssignment(line, "jitterBurstTime", out var jbT)) else if (Helper.ParseDoubleFromAssignment(line, "randomOffsetMin", out var rom))
jitterBurstTime = jbT; randomOffsetMin = rom;
else if (Helper.ParseIntFromAssignment(line, "jitterCooldown", out var jbC)) else if (Helper.ParseDoubleFromAssignment(line, "randomOffsetMax", out var roM))
jitterCooldown = jbC; randomOffsetMax = roM;
// AA0026 // AA0026
else if (Helper.ParseConsoleColorFromAssignment(line, "textColor", out var col)) else if (Helper.ParseConsoleColorFromAssignment(line, "textColor", out var col))
textColor = col; textColor = col;
+16 -7
View File
@@ -239,9 +239,14 @@
</Grid> </Grid>
</GroupBox> </GroupBox>
<!-- Jitter Settings --> <!-- Random Offset Settings -->
<GroupBox Grid.Row="2" Grid.ColumnSpan="2" Header="Jitter Settings" Foreground="White" Margin="5" BorderBrush="#444"> <GroupBox Grid.Row="2" Grid.ColumnSpan="2" Header="Random Offset Settings" Foreground="White" Margin="5" BorderBrush="#444">
<Grid Margin="10"> <StackPanel Margin="10">
<StackPanel Orientation="Horizontal" Margin="0,5">
<CheckBox x:Name="RandomOffsetEnabledCheckBox" Content="Random Offset Enabled" Foreground="White" VerticalAlignment="Center"/>
<TextBlock Text="(Applies random X/Y offset on each set activation)" Foreground="Gray" FontSize="11" Margin="10,0,0,0" VerticalAlignment="Center"/>
</StackPanel>
<Grid Margin="0,5">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
@@ -253,11 +258,15 @@
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Burst Time (ms):" Foreground="White" Margin="0,5,10,5" VerticalAlignment="Center"/> <TextBlock Grid.Row="0" Grid.Column="0" Text="Min Offset:" 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"/> <TextBox Grid.Row="0" Grid.Column="1" x:Name="RandomOffsetMinTextBox" 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"/> <TextBlock Grid.Row="0" Grid.Column="2" Text="Max Offset:" 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"/> <TextBox Grid.Row="0" Grid.Column="3" x:Name="RandomOffsetMaxTextBox" Margin="0,5" Width="80" HorizontalAlignment="Left" Background="#2D2D2D" Foreground="White" BorderBrush="#444"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="(e.g. 0.0001)" Foreground="Gray" FontSize="11" Margin="0,0,10,0" VerticalAlignment="Center"/>
<TextBlock Grid.Row="1" Grid.Column="2" Text="(e.g. 0.001)" Foreground="Gray" FontSize="11" Margin="20,0,10,0" VerticalAlignment="Center"/>
</Grid> </Grid>
</StackPanel>
</GroupBox> </GroupBox>
<!-- User & Favorites --> <!-- User & Favorites -->
+16 -16
View File
@@ -122,7 +122,7 @@ namespace Lithium
DebitFlagCheckBox.IsChecked = ConfigLoader.debitFlag1; DebitFlagCheckBox.IsChecked = ConfigLoader.debitFlag1;
BetaTestCheckBox.IsChecked = ConfigLoader.betaTest; BetaTestCheckBox.IsChecked = ConfigLoader.betaTest;
TtsEnabledCheckBox.IsChecked = ConfigLoader.ttsEnabled; TtsEnabledCheckBox.IsChecked = ConfigLoader.ttsEnabled;
JitterEnabledCheckBox.IsChecked = ConfigLoader.jitterEnabled; RandomOffsetEnabledCheckBox.IsChecked = ConfigLoader.randomOffsetEnabled;
// AA0123 // AA0123
NextSetKeyTextBox.Text = $"0x{ConfigLoader.nextSetKey:X2}"; NextSetKeyTextBox.Text = $"0x{ConfigLoader.nextSetKey:X2}";
@@ -130,9 +130,9 @@ namespace Lithium
RefreshKeyTextBox.Text = $"0x{ConfigLoader.refreshKey:X2}"; RefreshKeyTextBox.Text = $"0x{ConfigLoader.refreshKey:X2}";
SwitchSideKeyTextBox.Text = $"0x{ConfigLoader.switchSideKey:X2}"; SwitchSideKeyTextBox.Text = $"0x{ConfigLoader.switchSideKey:X2}";
// AA0124 // AA0124 - Random Offset Settings
JitterBurstTimeTextBox.Text = ConfigLoader.jitterBurstTime.ToString(); RandomOffsetMinTextBox.Text = ConfigLoader.randomOffsetMin.ToString("0.0000", System.Globalization.CultureInfo.InvariantCulture);
JitterCooldownTextBox.Text = ConfigLoader.jitterCooldown.ToString(); RandomOffsetMaxTextBox.Text = ConfigLoader.randomOffsetMax.ToString("0.0000", System.Globalization.CultureInfo.InvariantCulture);
// AA0125 // AA0125
UserNameTextBox.Text = ConfigLoader.userName ?? ""; UserNameTextBox.Text = ConfigLoader.userName ?? "";
@@ -230,13 +230,13 @@ namespace Lithium
ConfigLoader.debitFlag1 = false; ConfigLoader.debitFlag1 = false;
ConfigLoader.betaTest = false; ConfigLoader.betaTest = false;
ConfigLoader.ttsEnabled = true; ConfigLoader.ttsEnabled = true;
ConfigLoader.jitterEnabled = false; ConfigLoader.randomOffsetEnabled = false;
ConfigLoader.randomOffsetMin = 0.0001;
ConfigLoader.randomOffsetMax = 0.001;
ConfigLoader.nextSetKey = 0x05; ConfigLoader.nextSetKey = 0x05;
ConfigLoader.prevSetKey = 0x06; ConfigLoader.prevSetKey = 0x06;
ConfigLoader.refreshKey = 0x50; ConfigLoader.refreshKey = 0x50;
ConfigLoader.switchSideKey = 0x4D; ConfigLoader.switchSideKey = 0x4D;
ConfigLoader.jitterBurstTime = 1800;
ConfigLoader.jitterCooldown = 3000;
ConfigLoader.userName = null; ConfigLoader.userName = null;
ConfigLoader.favoriteAttackers = null; ConfigLoader.favoriteAttackers = null;
ConfigLoader.favoriteDefenders = null; ConfigLoader.favoriteDefenders = null;
@@ -252,15 +252,15 @@ namespace Lithium
// AA0134 // AA0134
private string GenerateConfigContent() private string GenerateConfigContent()
{ {
// Validate and parse jitter times // Validate and parse random offset values
if (!int.TryParse(JitterBurstTimeTextBox.Text, out int jitterBurstTime)) if (!double.TryParse(RandomOffsetMinTextBox.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double randomOffsetMin))
{ {
AppendConsole("Error: Invalid jitter burst time value"); AppendConsole("Error: Invalid random offset min value");
return null; return null;
} }
if (!int.TryParse(JitterCooldownTextBox.Text, out int jitterCooldown)) if (!double.TryParse(RandomOffsetMaxTextBox.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double randomOffsetMax))
{ {
AppendConsole("Error: Invalid jitter cooldown value"); AppendConsole("Error: Invalid random offset max value");
return null; return null;
} }
@@ -296,7 +296,7 @@ namespace Lithium
sb.AppendLine($"debitFlag1 = {DebitFlagCheckBox.IsChecked.ToString().ToLower()}"); sb.AppendLine($"debitFlag1 = {DebitFlagCheckBox.IsChecked.ToString().ToLower()}");
sb.AppendLine($"betaTest = {BetaTestCheckBox.IsChecked.ToString().ToLower()}"); sb.AppendLine($"betaTest = {BetaTestCheckBox.IsChecked.ToString().ToLower()}");
sb.AppendLine($"ttsEnabled = {TtsEnabledCheckBox.IsChecked.ToString().ToLower()}"); sb.AppendLine($"ttsEnabled = {TtsEnabledCheckBox.IsChecked.ToString().ToLower()}");
sb.AppendLine($"jitterEnabled = {JitterEnabledCheckBox.IsChecked.ToString().ToLower()}"); sb.AppendLine($"randomOffsetEnabled = {RandomOffsetEnabledCheckBox.IsChecked.ToString().ToLower()}");
sb.AppendLine(); sb.AppendLine();
sb.AppendLine("-- Key Bindings (Virtual Key Codes)"); sb.AppendLine("-- Key Bindings (Virtual Key Codes)");
sb.AppendLine($"nextSetKey = {ParseKeyCode(NextSetKeyTextBox.Text)}"); sb.AppendLine($"nextSetKey = {ParseKeyCode(NextSetKeyTextBox.Text)}");
@@ -304,9 +304,9 @@ namespace Lithium
sb.AppendLine($"refreshKey = {ParseKeyCode(RefreshKeyTextBox.Text)}"); sb.AppendLine($"refreshKey = {ParseKeyCode(RefreshKeyTextBox.Text)}");
sb.AppendLine($"switchSideKey = {ParseKeyCode(SwitchSideKeyTextBox.Text)}"); sb.AppendLine($"switchSideKey = {ParseKeyCode(SwitchSideKeyTextBox.Text)}");
sb.AppendLine(); sb.AppendLine();
sb.AppendLine("-- Jitter Settings"); sb.AppendLine("-- Random Offset Settings");
sb.AppendLine($"jitterBurstTime = {jitterBurstTime}"); sb.AppendLine($"randomOffsetMin = {randomOffsetMin.ToString("0.0000", System.Globalization.CultureInfo.InvariantCulture)}");
sb.AppendLine($"jitterCooldown = {jitterCooldown}"); sb.AppendLine($"randomOffsetMax = {randomOffsetMax.ToString("0.0000", System.Globalization.CultureInfo.InvariantCulture)}");
sb.AppendLine(); sb.AppendLine();
sb.AppendLine("-- User & Favorites"); sb.AppendLine("-- User & Favorites");
sb.AppendLine($"userName = \"{UserNameTextBox.Text}\""); sb.AppendLine($"userName = \"{UserNameTextBox.Text}\"");
+25 -37
View File
@@ -14,11 +14,10 @@ namespace Lua
private static extern short GetAsyncKeyState(int vKey); private static extern short GetAsyncKeyState(int vKey);
private static readonly Random _rng = new Random(); private static readonly Random _rng = new Random();
private static bool _jitterActive = false; private static bool _wasBothDown = false;
private static int _jitterStart = 0; private static double _randomOffsetX = 0;
private static int _lastJitterEnd = 0; private static double _randomOffsetY = 0;
private static double _remainderX, _remainderY; private static double _remainderX, _remainderY;
private static double _jitterMultiplierX, _jitterMultiplierY;
public static bool CustomModeActive = false; public static bool CustomModeActive = false;
public static double CustomRecoilX = 0; public static double CustomRecoilX = 0;
@@ -38,18 +37,24 @@ namespace Lua
{ {
while (!_cancellationSource.Token.IsCancellationRequested) while (!_cancellationSource.Token.IsCancellationRequested)
{ {
// FIX: Perform key checks once and reuse the results
bool leftDown = IsDown(VK_LBUTTON); bool leftDown = IsDown(VK_LBUTTON);
bool rightDown = IsDown(VK_RBUTTON); bool rightDown = IsDown(VK_RBUTTON);
bool bothDown = leftDown && rightDown;
if (window.IsRecoilEnabled && leftDown && rightDown) // Detect new activation (transition from not both down to both down)
if (bothDown && !_wasBothDown)
{
OnSetActivated();
}
_wasBothDown = bothDown;
if (window.IsRecoilEnabled && bothDown)
{ {
HandleRecoilTick(); HandleRecoilTick();
} }
else else
{ {
_remainderX = _remainderY = 0; _remainderX = _remainderY = 0;
_jitterActive = false;
} }
Thread.Sleep(2); Thread.Sleep(2);
@@ -61,15 +66,23 @@ namespace Lua
} }
} }
private static void OnSetActivated()
{
if (!ConfigLoader.randomOffsetEnabled) return;
double range = ConfigLoader.randomOffsetMax - ConfigLoader.randomOffsetMin;
if (range <= 0) return;
_randomOffsetX = ConfigLoader.randomOffsetMin + _rng.NextDouble() * range;
_randomOffsetY = ConfigLoader.randomOffsetMin + _rng.NextDouble() * range;
}
private static void HandleRecoilTick() private static void HandleRecoilTick()
{ {
try try
{ {
int now = Environment.TickCount;
if (CustomModeActive) if (CustomModeActive)
{ {
HandleJitter(now);
ApplyRecoil((CustomRecoilX, CustomRecoilY)); ApplyRecoil((CustomRecoilX, CustomRecoilY));
return; return;
} }
@@ -78,7 +91,6 @@ namespace Lua
if (!OperatorSets.mergedSets.TryGetValue(setName, out var recoil)) return; if (!OperatorSets.mergedSets.TryGetValue(setName, out var recoil)) return;
HandleJitter(now);
ApplyRecoil(recoil); ApplyRecoil(recoil);
} }
catch (Exception ex) catch (Exception ex)
@@ -87,34 +99,10 @@ namespace Lua
} }
} }
private static void HandleJitter(int now)
{
if (!ConfigLoader.jitterEnabled) return;
if (!_jitterActive && now - _lastJitterEnd >= ConfigLoader.jitterCooldown)
{
_jitterActive = true;
_jitterStart = now;
_jitterMultiplierX = (_rng.NextDouble() - 0.5) * 0.2;
_jitterMultiplierY = (_rng.NextDouble() - 0.5) * 0.2;
}
if (_jitterActive && now - _jitterStart >= ConfigLoader.jitterBurstTime)
{
_jitterActive = false;
_lastJitterEnd = now;
_jitterMultiplierX = _jitterMultiplierY = 0;
}
}
private static void ApplyRecoil((double recoilX, double recoilY) recoil) private static void ApplyRecoil((double recoilX, double recoilY) recoil)
{ {
double moveX = recoil.recoilX; double moveX = recoil.recoilX + _randomOffsetX;
double moveY = recoil.recoilY; double moveY = recoil.recoilY + _randomOffsetY;
moveX += recoil.recoilX * _jitterMultiplierX;
moveY += recoil.recoilY * _jitterMultiplierY;
if (ConfigLoader.debitFlag1) if (ConfigLoader.debitFlag1)
{ {
+14
View File
@@ -66,6 +66,20 @@ namespace Lua
return int.TryParse(rhs, NumberStyles.Integer, CultureInfo.InvariantCulture, out result); return int.TryParse(rhs, NumberStyles.Integer, CultureInfo.InvariantCulture, out result);
} }
// AA0034b
public static bool ParseDoubleFromAssignment(string line, string key, out double result)
{
result = 0;
var idx = line.IndexOf('=');
if (idx < 0) return false;
var lhs = line.Substring(0, idx).Trim();
if (!string.Equals(lhs, key, StringComparison.OrdinalIgnoreCase)) return false;
var rhs = line.Substring(idx + 1).Trim();
return double.TryParse(rhs, NumberStyles.Float, CultureInfo.InvariantCulture, out result);
}
// AA0035 // AA0035
public static bool ParseStringFromAssignment(string line, string key, out string result) public static bool ParseStringFromAssignment(string line, string key, out string result)
{ {