6 Commits

Author SHA1 Message Date
TJhost 19556f2d26 Relocate app data and package build output
Adds a new `AppPaths` helper and moves runtime/user-generated files (`init.config`, `custom_set.txt`, cache, WebView2 data) into `%LocalAppData%\Lithium` with readable fallback to portable files. WebView2 initialization now sets a loader DLL path, uses an explicit user data folder, and surfaces runtime-missing errors.

The build/publish pipeline is updated to emit a clean `Build\` layout with dependencies under `lib\`, remove duplicate root DLL/docs, and align probing/runtime settings for net48 x64 output. Supporting updates include ignore rules for build/runtime artifacts, refreshed agent build/release docs, and endpoint URL/domain updates.
2026-09-13 19:33:09 -04:00
TJhost 5f993f98b8 Tweak input polling timings
Increase the hotkey and recoil loop sleep intervals to reduce CPU churn and smooth input handling. The hotkey loop now waits 15ms instead of 8ms, and the recoil loop waits 10ms instead of 2ms, which helps reduce jitter while keeping responsiveness stable. This also updates the packaged release artifact by replacing the older archive with Lithium-0.01.7z.
2026-09-13 18:27:58 -04:00
TJhost ae3b4164f3 🚀 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
2026-09-03 16:00:27 -04:00
TJhost 86c231773d 📂 File-Level Changes Summary
• AGENTS.md: Added build & release workflow documentation
• session-ses_1101.md: Added session tracking file
2026-09-03 15:27:40 -04:00
Trenten Pettry b6037e0c91 🚀 Added (New Features)
• Custom Set Builder Testing Mode: The Custom Set Builder tab now functions as a live recoil testing tool. When toggled ON while the tab is active, the custom X/Y recoil values are applied instead of the selected operator's recoil, allowing real-time dial-in of recoil sets. Switching to any other tab automatically restores normal operator recoil.

📂 File-Level Changes Summary
• MainWindow.xaml: Named TabControl and added SelectionChanged handler for tab tracking.
• MainWindow.xaml.cs: Added UpdateCustomSetState() to sync custom recoil mode with RecoilEngine based on tab focus and toggle state.
• RecoilEngine.cs: Added CustomModeActive, CustomRecoilX, CustomRecoilY fields; HandleRecoilTick() checks custom mode first before falling back to mergedSets lookup.
2026-06-22 11:48:10 -04:00
Trenten Pettry 60b519335f 🛠️ Fixed (Bugs resolved)
- Quick Swap Side Restoration: Fixed a bug where quickswap would fail to switch sides when toggling back to the original operator. The issue occurred because the baseline set was captured after the side had already switched, so the revert logic couldn't determine it needed to switch sides again. Now the baseline is captured before any side change, ensuring correct toggle behavior.
📂 File-Level Changes Summary
- OperatorSets.cs: Captured preSwitchSet before the SwitchSide() call in QuickSwapTo() and used it when storing originalSetBeforeQuickSwap.
2026-06-22 11:33:26 -04:00
16 changed files with 3582 additions and 134 deletions
+14
View File
@@ -17,6 +17,9 @@
mono_crash.* mono_crash.*
# Build results # Build results
[Bb]in/
[Oo]bj/
[Bb]uild/
[Dd]ebug/ [Dd]ebug/
[Dd]ebugPublic/ [Dd]ebugPublic/
[Rr]elease/ [Rr]elease/
@@ -228,6 +231,17 @@ _pkginfo.txt
# but keep track of directories ending in .cache # but keep track of directories ending in .cache
!?*.[Cc]ache/ !?*.[Cc]ache/
# Runtime-generated application data
*.exe.WebView2/
# Local release archives
*.7z
*.zip
# Local Claude Code and VS Code settings
.claude/
.vscode/
# Others # Others
ClientBin/ ClientBin/
~$* ~$*
+87
View File
@@ -0,0 +1,87 @@
# Build & Release Workflow
## Prerequisites
- Git remote: `https://git.scpsmp.site/JJ/Lithium.git`
- Auth: OAuth token stored in Windows Credential Manager (via git)
- Visual Studio 2022 or newer with the .NET desktop development workload
- NuGet package restore enabled
- .NET Framework 4.8 Developer Pack for building
- Microsoft Edge WebView2 Runtime for the Website tab at runtime
## Build
```powershell
# Kill running process first
Stop-Process -Name "Lithium" -ErrorAction SilentlyContinue
# Locate MSBuild, restore packages, and compile the Release build
$msbuild = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | Select-Object -First 1
& $msbuild Lithium.sln /t:Restore,Rebuild /p:Configuration=Release /p:Platform="x64"
# Create the clean file-deployment layout under Build\.
& $msbuild Lithium\Lithium.csproj /t:Publish /p:Configuration=Release /p:Platform="x64"
# Keep Lithium.exe, Lithium.exe.config, and the complete lib directory together.
```
## Stage & Commit
```powershell
# Stage only intentional files (not build artifacts, .vs/, bin/, obj/)
git add Lithium/MainWindow.xaml Lithium/MainWindow.xaml.cs Lithium/RecoilEngine.cs
# Commit with changelog format
git commit -m "🚀 Added (New Features)
• Description of feature
🛠️ Fixed (Bugs resolved)
• Description of fix
📂 File-Level Changes Summary
• File.cs: Specific change description."
```
## Push & Release
```powershell
# Use naming scheme: 0.XX (e.g. 0.05, 0.06)
$version = "0.XX"
# Create and push tag
git tag $version
git push origin master
git push origin $version
# Retrieve OAuth token from git credential store
$cred = "protocol=https`nhost=git.scpsmp.site`n`n" | git credential fill
$token = ($cred -split "`n" | Where-Object { $_ -like "password=*" }) -replace "password=",""
# Archive the published x64 Release output; run from anywhere inside the repository
$repoRoot = (git rev-parse --show-toplevel).Trim()
$archivePath = Join-Path $repoRoot "Lithium-$version.7z"
$releaseOutput = Join-Path $repoRoot "Build\*"
$sevenZip = (Get-Command 7z.exe -ErrorAction Stop).Source
& $sevenZip a -mx=9 "$archivePath" "$releaseOutput"
# Create release via Gitea API
$body = @"
{"tag_name":"$version","target_commitish":"master","name":"$version @ Lithium","body":"🚀 Added (New Features)\\n• Description\\n\\n📂 File-Level Changes Summary\\n• File.cs: Change.","draft":false,"prerelease":false}
"@
[System.IO.File]::WriteAllText("$env:TEMP\release.json", $body)
$response = curl.exe -s -X POST "https://git.scpsmp.site/api/v1/repos/JJ/Lithium/releases" -H "Authorization: Bearer $token" -H "Content-Type: application/json" -d "@$env:TEMP\release.json"
$releaseId = ($response | ConvertFrom-Json).id
# Upload 7z asset
curl.exe -s -X POST "https://git.scpsmp.site/api/v1/repos/JJ/Lithium/releases/$releaseId/assets?name=Lithium-$version.7z" -H "Authorization: Bearer $token" -H "Content-Type: application/x-7z-compressed" --data-binary "$archivePath"
```
## Post-Release Cleanup
```powershell
# Delete the local archive after successful upload
Remove-Item -LiteralPath "$archivePath" -Force
Remove-Item -LiteralPath "$env:TEMP\release.json" -Force
```
## Notes
- Do NOT stage build artifacts (bin/, obj/, .vs/, .7z files)
- Tag naming scheme: `0.01`, `0.02`, `0.03`, etc. (not `v1.0.0`)
- Release naming scheme: `0.XX @ Lithium`
- Use PATCH to edit existing release tag via API if you mess up the tag name
- Add `7z.exe` to `PATH` before running the release archive command
BIN
View File
Binary file not shown.
+5 -2
View File
@@ -1,8 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
<runtime> <runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib;dependencies;bin" /> <probing privatePath="lib" />
</assemblyBinding> </assemblyBinding>
</runtime> </runtime>
</configuration> </configuration>
-1
View File
@@ -7,7 +7,6 @@
<package id="System.Memory" version="4.6.3" targetFramework="net48" /> <package id="System.Memory" version="4.6.3" targetFramework="net48" />
<package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net48" /> <package id="System.Numerics.Vectors" version="4.6.1" targetFramework="net48" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net48" /> <package id="System.Runtime.CompilerServices.Unsafe" version="6.1.2" targetFramework="net48" />
<package id="System.Speech" version="10.0.0" targetFramework="net48" />
<package id="System.Text.Encodings.Web" version="10.0.0" targetFramework="net48" /> <package id="System.Text.Encodings.Web" version="10.0.0" targetFramework="net48" />
<package id="System.Text.Json" version="10.0.0" targetFramework="net48" /> <package id="System.Text.Json" version="10.0.0" targetFramework="net48" />
<package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net48" /> <package id="System.Threading.Tasks.Extensions" version="4.6.3" targetFramework="net48" />
+55
View File
@@ -0,0 +1,55 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace Lua
{
internal static class AppPaths
{
private const string ApplicationDirectoryName = "Lithium";
public static string ExecutableDirectory => AppDomain.CurrentDomain.BaseDirectory;
public static string UserDataDirectory => Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
ApplicationDirectoryName);
public static string WebViewUserDataDirectory => Path.Combine(UserDataDirectory, "WebView2");
public static string WebViewLoaderDirectory => Path.Combine(
ExecutableDirectory,
"lib",
"runtimes",
GetRuntimeIdentifier(),
"native");
private static string GetRuntimeIdentifier()
{
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X64:
return "win-x64";
case Architecture.Arm64:
return "win-arm64";
default:
return "win-x86";
}
}
public static string GetUserFilePath(string fileName)
{
Directory.CreateDirectory(UserDataDirectory);
return Path.Combine(UserDataDirectory, fileName);
}
public static string GetReadableFilePath(string fileName)
{
string userPath = Path.Combine(UserDataDirectory, fileName);
if (File.Exists(userPath))
return userPath;
string portablePath = Path.Combine(ExecutableDirectory, fileName);
return File.Exists(portablePath) ? portablePath : null;
}
}
}
+16 -15
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,18 +63,19 @@ 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();
SetConsoleColor(); SetConsoleColor();
// AA0019 // AA0019
if (!File.Exists("init.config")) return; string configPath = AppPaths.GetReadableFilePath("init.config");
if (configPath == null) return;
var lines = Helper.ReadLinesSafe("init.config"); var lines = Helper.ReadLinesSafe(configPath);
// AA0020 // AA0020
foreach (var raw in lines) foreach (var raw in lines)
@@ -108,13 +109,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;
+1 -1
View File
@@ -35,7 +35,7 @@ namespace Lithium
HandleRefresh(); HandleRefresh();
HandleSwitchSide(); HandleSwitchSide();
HandleQuickSwaps(); HandleQuickSwaps();
Thread.Sleep(8); Thread.Sleep(15);
} }
catch (Exception ex) catch (Exception ex)
{ {
+30 -17
View File
@@ -16,7 +16,7 @@
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
<NuGetPackageImportStamp> <NuGetPackageImportStamp>
</NuGetPackageImportStamp> </NuGetPackageImportStamp>
<PublishUrl>publish\</PublishUrl> <PublishUrl>..\Build\</PublishUrl>
<Install>true</Install> <Install>true</Install>
<InstallFrom>Disk</InstallFrom> <InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled> <UpdateEnabled>false</UpdateEnabled>
@@ -62,7 +62,7 @@
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath> <OutputPath>bin\x64\Release\</OutputPath>
@@ -72,7 +72,7 @@
<PlatformTarget>x64</PlatformTarget> <PlatformTarget>x64</PlatformTarget>
<LangVersion>7.3</LangVersion> <LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
@@ -96,7 +96,6 @@
<Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.IO, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath> <HintPath>..\packages\System.IO.4.3.0\lib\net462\System.IO.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.IO.Pipelines, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="System.IO.Pipelines, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Pipelines.10.0.0\lib\net462\System.IO.Pipelines.dll</HintPath> <HintPath>..\packages\System.IO.Pipelines.10.0.0\lib\net462\System.IO.Pipelines.dll</HintPath>
@@ -107,7 +106,6 @@
<Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Net.Http, Version=4.1.1.3, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath> <HintPath>..\packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Numerics" /> <Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Numerics.Vectors, Version=4.1.6.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
@@ -116,7 +114,6 @@
<Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Runtime, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath> <HintPath>..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath> <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.2\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
@@ -124,22 +121,18 @@
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Security.Cryptography.Algorithms, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath> <HintPath>..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath> <HintPath>..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath> <HintPath>..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"> <Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath> <HintPath>..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
<Private>True</Private> <Private>True</Private>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Speech" /> <Reference Include="System.Speech" />
<Reference Include="System.Text.Encodings.Web, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL"> <Reference Include="System.Text.Encodings.Web, Version=10.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
@@ -168,6 +161,7 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="AppPaths.cs" />
<Compile Include="HotkeyHandler.cs" /> <Compile Include="HotkeyHandler.cs" />
<Compile Include="RecoilEngine.cs" /> <Compile Include="RecoilEngine.cs" />
<Compile Include="Utils.cs" /> <Compile Include="Utils.cs" />
@@ -238,16 +232,35 @@
<Error Condition="!Exists('..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets'))" /> <Error Condition="!Exists('..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets'))" />
</Target> </Target>
<Import Project="..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets" Condition="Exists('..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets')" /> <Import Project="..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets" Condition="Exists('..\packages\System.ValueTuple.4.6.1\build\net471\System.ValueTuple.targets')" />
<ItemGroup>
<!-- Include all referenced DLLs -->
<ReferenceCopyLocalPaths Include="@(ReferencePath)" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="A1\a23ae8c4c6863364165637fb70679eb3.ico" /> <Resource Include="A1\a23ae8c4c6863364165637fb70679eb3.ico" />
</ItemGroup> </ItemGroup>
<Target Name="CopyDllsToLib" AfterTargets="Build"> <Target Name="ClearGeneratedLib" BeforeTargets="CopyFilesToOutputDirectory">
<MakeDir Directories="$(OutputPath)lib" /> <RemoveDir Directories="$(TargetDir)lib" Condition="Exists('$(TargetDir)lib')" />
<Copy SourceFiles="@(ReferenceCopyLocalPaths)" DestinationFolder="$(OutputPath)lib" SkipUnchangedFiles="true" /> </Target>
<Target Name="OrganizeBuildOutput" AfterTargets="CopyFilesToOutputDirectory">
<ItemGroup>
<ManagedDependencies Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)' == '.dll'" />
<DependencyDocumentation Include="@(ReferenceCopyLocalPaths)" Condition="'%(Extension)' == '.xml'" />
<WebViewNativeFiles Include="$(TargetDir)runtimes\**\*" />
</ItemGroup>
<MakeDir Directories="$(TargetDir)lib" />
<Copy SourceFiles="@(ManagedDependencies)" DestinationFolder="$(TargetDir)lib" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(WebViewNativeFiles)" DestinationFiles="@(WebViewNativeFiles->'$(TargetDir)lib\runtimes\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" Condition="'@(WebViewNativeFiles)' != ''" />
<Delete Files="@(ManagedDependencies->'$(TargetDir)%(Filename)%(Extension)');@(DependencyDocumentation->'$(TargetDir)%(Filename)%(Extension)')" />
<Delete Files="$(TargetDir)$(TargetName).pdb" Condition="'$(Configuration)' == 'Release' and Exists('$(TargetDir)$(TargetName).pdb')" />
<RemoveDir Directories="$(TargetDir)runtimes" Condition="Exists('$(TargetDir)runtimes')" />
</Target>
<Target Name="OrganizePublishOutput" AfterTargets="PublishOnly">
<ItemGroup>
<PublishRootFiles Include="$(TargetPath)" />
<PublishRootFiles Include="$(TargetPath).config" Condition="Exists('$(TargetPath).config')" />
<PublishLibFiles Include="$(TargetDir)lib\**\*" />
</ItemGroup>
<RemoveDir Directories="$(PublishUrl)" Condition="Exists('$(PublishUrl)')" />
<MakeDir Directories="$(PublishUrl)lib" />
<Copy SourceFiles="@(PublishRootFiles)" DestinationFolder="$(PublishUrl)" SkipUnchangedFiles="true" />
<Copy SourceFiles="@(PublishLibFiles)" DestinationFiles="@(PublishLibFiles->'$(PublishUrl)lib\%(RecursiveDir)%(Filename)%(Extension)')" SkipUnchangedFiles="true" />
</Target> </Target>
<PropertyGroup> <PropertyGroup>
<PreBuildEvent> <PreBuildEvent>
+17 -8
View File
@@ -116,7 +116,7 @@
<!-- Main Content --> <!-- Main Content -->
<Grid Margin="0,35,0,0"> <Grid Margin="0,35,0,0">
<TabControl Background="#1E1E1E" Foreground="White"> <TabControl x:Name="MainTabControl" Background="#1E1E1E" Foreground="White" SelectionChanged="MainTabControl_SelectionChanged">
<!-- Console Tab --> <!-- Console Tab -->
<TabItem Header="Console"> <TabItem Header="Console">
<Grid Background="#252525" Margin="10"> <Grid Background="#252525" Margin="10">
@@ -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 -->
+82 -25
View File
@@ -6,6 +6,7 @@ using System.Net.Http;
using System.Text; using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using Microsoft.Web.WebView2.Core;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
@@ -43,9 +44,7 @@ namespace Lithium
); );
// AA0116 // AA0116
Browser.Source = !string.IsNullOrEmpty(OperatorSets.ConfigExportUrl) InitializeBrowser();
? new Uri(OperatorSets.ConfigExportUrl)
: new Uri("https://jj.giggity.gay/exindex.html");
// AA0117 // AA0117
LoadSettingsToUI(); LoadSettingsToUI();
@@ -77,6 +76,31 @@ namespace Lithium
} }
} }
private async void InitializeBrowser()
{
try
{
CoreWebView2Environment.SetLoaderDllFolderPath(AppPaths.WebViewLoaderDirectory);
Directory.CreateDirectory(AppPaths.WebViewUserDataDirectory);
var environment = await CoreWebView2Environment.CreateAsync(
userDataFolder: AppPaths.WebViewUserDataDirectory);
await Browser.EnsureCoreWebView2Async(environment);
Browser.Source = !string.IsNullOrEmpty(OperatorSets.ConfigExportUrl)
? new Uri(OperatorSets.ConfigExportUrl)
: new Uri("https://jj.scpsmp.site/exindex.html");
}
catch (WebView2RuntimeNotFoundException)
{
AppendConsole("WebView2 Runtime is not installed. The Website tab is unavailable.");
}
catch (Exception ex)
{
AppendConsole($"Website initialization failed: {ex.Message}");
}
}
// AA0118 // AA0118
private Thread StartThread(ThreadStart action) private Thread StartThread(ThreadStart action)
{ {
@@ -122,7 +146,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 +154,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 ?? "";
@@ -184,7 +208,7 @@ namespace Lithium
return; return;
} }
string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "init.config"); string configPath = AppPaths.GetUserFilePath("init.config");
File.WriteAllText(configPath, configContent); File.WriteAllText(configPath, configContent);
// AA0129 // AA0129
@@ -230,13 +254,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 +276,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 +320,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 +328,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}\"");
@@ -451,7 +475,40 @@ namespace Lithium
private void ToggleCustomSet_Click(object sender, RoutedEventArgs e) private void ToggleCustomSet_Click(object sender, RoutedEventArgs e)
{ {
customSetEnabled = !customSetEnabled; customSetEnabled = !customSetEnabled;
UpdateCustomSetConsole(customSetEnabled ? "Set is ON" : "Set is OFF"); UpdateCustomSetState();
}
private void MainTabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
UpdateCustomSetState();
}
private void UpdateCustomSetState()
{
var selectedTab = MainTabControl.SelectedItem as TabItem;
bool onCustomTab = selectedTab != null &&
string.Equals(selectedTab.Header?.ToString(), "Custom Set Builder", StringComparison.OrdinalIgnoreCase);
if (customSetEnabled && onCustomTab)
{
if (double.TryParse(RecoilXTextBox.Text, System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture, out double x) &&
double.TryParse(RecoilYTextBox.Text, System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture, out double y))
{
RecoilEngine.CustomModeActive = true;
RecoilEngine.CustomRecoilX = x;
RecoilEngine.CustomRecoilY = y;
UpdateCustomSetConsole($"Custom Set ACTIVE | X:{x} Y:{y}");
return;
}
UpdateCustomSetConsole("Error: Invalid recoil values");
}
else
{
RecoilEngine.CustomModeActive = false;
UpdateCustomSetConsole(customSetEnabled ? "Set is ON (switch to tab to activate)" : "Set is OFF");
}
} }
// AA0145 // AA0145
@@ -483,7 +540,7 @@ namespace Lithium
string json = JsonSerializer.Serialize(payload); string json = JsonSerializer.Serialize(payload);
var response = await client.PostAsync( var response = await client.PostAsync(
"https://jj.giggity.gay/api/global/add", "https://jj.scpsmp.site/api/global/add",
new StringContent(json, Encoding.UTF8, "application/json") new StringContent(json, Encoding.UTF8, "application/json")
); );
@@ -508,7 +565,7 @@ namespace Lithium
{ {
try try
{ {
string customSetPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "custom_set.txt"); string customSetPath = AppPaths.GetUserFilePath("custom_set.txt");
File.WriteAllText( File.WriteAllText(
customSetPath, customSetPath,
$"{OperatorNameTextBox.Text}|{RecoilXTextBox.Text}|{RecoilYTextBox.Text}|{(AttackerRadioButton.IsChecked == true ? "attacker" : "defender")}" $"{OperatorNameTextBox.Text}|{RecoilXTextBox.Text}|{RecoilYTextBox.Text}|{(AttackerRadioButton.IsChecked == true ? "attacker" : "defender")}"
@@ -535,9 +592,9 @@ namespace Lithium
{ {
try try
{ {
string customSetPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "custom_set.txt"); string customSetPath = AppPaths.GetReadableFilePath("custom_set.txt");
if (!File.Exists(customSetPath)) if (customSetPath == null)
{ {
UpdateCustomSetConsole("No saved set found"); UpdateCustomSetConsole("No saved set found");
return; return;
+10 -10
View File
@@ -41,14 +41,9 @@ namespace Lua
Timeout = System.TimeSpan.FromSeconds(10) Timeout = System.TimeSpan.FromSeconds(10)
}; };
private static string CacheDirectory => private static string CacheDirectory => AppPaths.UserDataDirectory;
System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
"coax"
);
private static string CacheFile => private static string CacheFile => System.IO.Path.Combine(CacheDirectory, "config_cache.txt");
System.IO.Path.Combine(CacheDirectory, "config_cache.txt");
// AA0059 // AA0059
@@ -118,7 +113,7 @@ namespace Lua
var allLines = new List<string>(); var allLines = new List<string>();
bool loadedOnline = false; bool loadedOnline = false;
// Ensure coax folder exists (with proper error handling) // Ensure the per-user cache folder exists (with proper error handling)
try try
{ {
if (!System.IO.Directory.Exists(CacheDirectory)) if (!System.IO.Directory.Exists(CacheDirectory))
@@ -184,7 +179,10 @@ namespace Lua
} }
// Also load config.txt (local overrides) // Also load config.txt (local overrides)
var local = Helper.ReadLinesSafe("config.txt"); string localConfigPath = AppPaths.GetReadableFilePath("config.txt");
var local = localConfigPath == null
? Array.Empty<string>()
: Helper.ReadLinesSafe(localConfigPath);
if (local.Length > 0) if (local.Length > 0)
allLines.AddRange(local); allLines.AddRange(local);
@@ -405,6 +403,8 @@ namespace Lua
isQuickSwapping = true; isQuickSwapping = true;
try try
{ {
string preSwitchSet = CurrentSet;
if (!ConfigLoader.betaTest) if (!ConfigLoader.betaTest)
{ {
if (inAttackers && !onAttackers) if (inAttackers && !onAttackers)
@@ -444,7 +444,7 @@ namespace Lua
{ {
if (string.IsNullOrEmpty(originalSetBeforeQuickSwap)) if (string.IsNullOrEmpty(originalSetBeforeQuickSwap))
{ {
originalSetBeforeQuickSwap = CurrentSet; originalSetBeforeQuickSwap = preSwitchSet;
} }
SetCurrentSet(targetOp); SetCurrentSet(targetOp);
} }
+36 -37
View File
@@ -14,11 +14,14 @@ 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 double CustomRecoilX = 0;
public static double CustomRecoilY = 0;
private static bool IsDown(int key) private static bool IsDown(int key)
{ {
@@ -34,21 +37,27 @@ 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(10);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -57,17 +66,31 @@ 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
{ {
if (CustomModeActive)
{
ApplyRecoil((CustomRecoilX, CustomRecoilY));
return;
}
string setName = OperatorSets.CurrentSet; string setName = OperatorSets.CurrentSet;
if (!OperatorSets.mergedSets.TryGetValue(setName, out var recoil)) return; if (!OperatorSets.mergedSets.TryGetValue(setName, out var recoil)) return;
int now = Environment.TickCount;
HandleJitter(now);
ApplyRecoil(recoil); ApplyRecoil(recoil);
} }
catch (Exception ex) catch (Exception ex)
@@ -76,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)
{ {
Binary file not shown.
+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)
{ {
+3197
View File
File diff suppressed because it is too large Load Diff