├── .gitattributes ├── .gitignore ├── AimBot.csproj ├── AimBot.sln ├── Aimers ├── Aimer.cs ├── FeedbackAimer.cs ├── FlickAimer.cs └── HybridAimer.cs ├── App.xaml ├── App.xaml.cs ├── AssemblyInfo.cs ├── Bot.cs ├── Detectors ├── Detector.cs ├── OpenCV.dll ├── OpenComputerVisionDetector.cs └── Resizer.cs ├── FileFilter.cs ├── Grabbers ├── DXGrabber.dll ├── DxGrabber.cs ├── GdiGrabber.cs └── Grabber.cs ├── Helpers ├── ListExtensions.cs ├── PointExtensions.cs ├── RectangleExtensions.cs ├── ScreenHelper.cs └── TypeHelper.cs ├── Injectors ├── MouseInjector.cs └── WindowsMouseInjector.cs ├── Input ├── GlobalKey.cs ├── GlobalMouse.cs └── GlobalWindow.cs ├── LICENSE ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── README.md ├── Renderers ├── Esp.cs └── GameOverlayEsp.cs ├── Selectors ├── NearestSelector.cs └── Selector.cs ├── Trackers ├── HungarianTracker.cs └── Tracker.cs ├── Triggers ├── ProximityTrigger.cs └── Trigger.cs └── gui.PNG /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | [Ll]ogs/ 33 | 34 | # Visual Studio 2015/2017 cache/options directory 35 | .vs/ 36 | # Uncomment if you have tasks that create the project's static files in wwwroot 37 | #wwwroot/ 38 | 39 | # Visual Studio 2017 auto generated files 40 | Generated\ Files/ 41 | 42 | # MSTest test Results 43 | [Tt]est[Rr]esult*/ 44 | [Bb]uild[Ll]og.* 45 | 46 | # NUnit 47 | *.VisualState.xml 48 | TestResult.xml 49 | nunit-*.xml 50 | 51 | # Build Results of an ATL Project 52 | [Dd]ebugPS/ 53 | [Rr]eleasePS/ 54 | dlldata.c 55 | 56 | # Benchmark Results 57 | BenchmarkDotNet.Artifacts/ 58 | 59 | # .NET Core 60 | project.lock.json 61 | project.fragment.lock.json 62 | artifacts/ 63 | 64 | # StyleCop 65 | StyleCopReport.xml 66 | 67 | # Files built by Visual Studio 68 | *_i.c 69 | *_p.c 70 | *_h.h 71 | *.ilk 72 | *.meta 73 | *.obj 74 | *.iobj 75 | *.pch 76 | *.pdb 77 | *.ipdb 78 | *.pgc 79 | *.pgd 80 | *.rsp 81 | *.sbr 82 | *.tlb 83 | *.tli 84 | *.tlh 85 | *.tmp 86 | *.tmp_proj 87 | *_wpftmp.csproj 88 | *.log 89 | *.vspscc 90 | *.vssscc 91 | .builds 92 | *.pidb 93 | *.svclog 94 | *.scc 95 | 96 | # Chutzpah Test files 97 | _Chutzpah* 98 | 99 | # Visual C++ cache files 100 | ipch/ 101 | *.aps 102 | *.ncb 103 | *.opendb 104 | *.opensdf 105 | *.sdf 106 | *.cachefile 107 | *.VC.db 108 | *.VC.VC.opendb 109 | 110 | # Visual Studio profiler 111 | *.psess 112 | *.vsp 113 | *.vspx 114 | *.sap 115 | 116 | # Visual Studio Trace Files 117 | *.e2e 118 | 119 | # TFS 2012 Local Workspace 120 | $tf/ 121 | 122 | # Guidance Automation Toolkit 123 | *.gpState 124 | 125 | # ReSharper is a .NET coding add-in 126 | _ReSharper*/ 127 | *.[Rr]e[Ss]harper 128 | *.DotSettings.user 129 | 130 | # JustCode is a .NET coding add-in 131 | .JustCode 132 | 133 | # TeamCity is a build add-in 134 | _TeamCity* 135 | 136 | # DotCover is a Code Coverage Tool 137 | *.dotCover 138 | 139 | # AxoCover is a Code Coverage Tool 140 | .axoCover/* 141 | !.axoCover/settings.json 142 | 143 | # Visual Studio code coverage results 144 | *.coverage 145 | *.coveragexml 146 | 147 | # NCrunch 148 | _NCrunch_* 149 | .*crunch*.local.xml 150 | nCrunchTemp_* 151 | 152 | # MightyMoose 153 | *.mm.* 154 | AutoTest.Net/ 155 | 156 | # Web workbench (sass) 157 | .sass-cache/ 158 | 159 | # Installshield output folder 160 | [Ee]xpress/ 161 | 162 | # DocProject is a documentation generator add-in 163 | DocProject/buildhelp/ 164 | DocProject/Help/*.HxT 165 | DocProject/Help/*.HxC 166 | DocProject/Help/*.hhc 167 | DocProject/Help/*.hhk 168 | DocProject/Help/*.hhp 169 | DocProject/Help/Html2 170 | DocProject/Help/html 171 | 172 | # Click-Once directory 173 | publish/ 174 | 175 | # Publish Web Output 176 | *.[Pp]ublish.xml 177 | *.azurePubxml 178 | # Note: Comment the next line if you want to checkin your web deploy settings, 179 | # but database connection strings (with potential passwords) will be unencrypted 180 | *.pubxml 181 | *.publishproj 182 | 183 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 184 | # checkin your Azure Web App publish settings, but sensitive information contained 185 | # in these scripts will be unencrypted 186 | PublishScripts/ 187 | 188 | # NuGet Packages 189 | *.nupkg 190 | # NuGet Symbol Packages 191 | *.snupkg 192 | # The packages folder can be ignored because of Package Restore 193 | **/[Pp]ackages/* 194 | # except build/, which is used as an MSBuild target. 195 | !**/[Pp]ackages/build/ 196 | # Uncomment if necessary however generally it will be regenerated when needed 197 | #!**/[Pp]ackages/repositories.config 198 | # NuGet v3's project.json files produces more ignorable files 199 | *.nuget.props 200 | *.nuget.targets 201 | 202 | # Microsoft Azure Build Output 203 | csx/ 204 | *.build.csdef 205 | 206 | # Microsoft Azure Emulator 207 | ecf/ 208 | rcf/ 209 | 210 | # Windows Store app package directories and files 211 | AppPackages/ 212 | BundleArtifacts/ 213 | Package.StoreAssociation.xml 214 | _pkginfo.txt 215 | *.appx 216 | *.appxbundle 217 | *.appxupload 218 | 219 | # Visual Studio cache files 220 | # files ending in .cache can be ignored 221 | *.[Cc]ache 222 | # but keep track of directories ending in .cache 223 | !?*.[Cc]ache/ 224 | 225 | # Others 226 | ClientBin/ 227 | ~$* 228 | *~ 229 | *.dbmdl 230 | *.dbproj.schemaview 231 | *.jfm 232 | *.pfx 233 | *.publishsettings 234 | orleans.codegen.cs 235 | 236 | # Including strong name files can present a security risk 237 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 238 | #*.snk 239 | 240 | # Since there are multiple workflows, uncomment next line to ignore bower_components 241 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 242 | #bower_components/ 243 | 244 | # RIA/Silverlight projects 245 | Generated_Code/ 246 | 247 | # Backup & report files from converting an old project file 248 | # to a newer Visual Studio version. Backup files are not needed, 249 | # because we have git ;-) 250 | _UpgradeReport_Files/ 251 | Backup*/ 252 | UpgradeLog*.XML 253 | UpgradeLog*.htm 254 | ServiceFabricBackup/ 255 | *.rptproj.bak 256 | 257 | # SQL Server files 258 | *.mdf 259 | *.ldf 260 | *.ndf 261 | 262 | # Business Intelligence projects 263 | *.rdl.data 264 | *.bim.layout 265 | *.bim_*.settings 266 | *.rptproj.rsuser 267 | *- [Bb]ackup.rdl 268 | *- [Bb]ackup ([0-9]).rdl 269 | *- [Bb]ackup ([0-9][0-9]).rdl 270 | 271 | # Microsoft Fakes 272 | FakesAssemblies/ 273 | 274 | # GhostDoc plugin setting file 275 | *.GhostDoc.xml 276 | 277 | # Node.js Tools for Visual Studio 278 | .ntvs_analysis.dat 279 | node_modules/ 280 | 281 | # Visual Studio 6 build log 282 | *.plg 283 | 284 | # Visual Studio 6 workspace options file 285 | *.opt 286 | 287 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 288 | *.vbw 289 | 290 | # Visual Studio LightSwitch build output 291 | **/*.HTMLClient/GeneratedArtifacts 292 | **/*.DesktopClient/GeneratedArtifacts 293 | **/*.DesktopClient/ModelManifest.xml 294 | **/*.Server/GeneratedArtifacts 295 | **/*.Server/ModelManifest.xml 296 | _Pvt_Extensions 297 | 298 | # Paket dependency manager 299 | .paket/paket.exe 300 | paket-files/ 301 | 302 | # FAKE - F# Make 303 | .fake/ 304 | 305 | # CodeRush personal settings 306 | .cr/personal 307 | 308 | # Python Tools for Visual Studio (PTVS) 309 | __pycache__/ 310 | *.pyc 311 | 312 | # Cake - Uncomment if you are using it 313 | # tools/** 314 | # !tools/packages.config 315 | 316 | # Tabs Studio 317 | *.tss 318 | 319 | # Telerik's JustMock configuration file 320 | *.jmconfig 321 | 322 | # BizTalk build output 323 | *.btp.cs 324 | *.btm.cs 325 | *.odx.cs 326 | *.xsd.cs 327 | 328 | # OpenCover UI analysis results 329 | OpenCover/ 330 | 331 | # Azure Stream Analytics local run output 332 | ASALocalRun/ 333 | 334 | # MSBuild Binary and Structured Log 335 | *.binlog 336 | 337 | # NVidia Nsight GPU debugger configuration file 338 | *.nvuser 339 | 340 | # MFractors (Xamarin productivity tool) working folder 341 | .mfractor/ 342 | 343 | # Local History for Visual Studio 344 | .localhistory/ 345 | 346 | # BeatPulse healthcheck temp database 347 | healthchecksdb 348 | 349 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 350 | MigrationBackup/ 351 | 352 | # Ionide (cross platform F# VS Code tools) working folder 353 | .ionide/ 354 | -------------------------------------------------------------------------------- /AimBot.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WinExe 5 | netcoreapp3.1 6 | true 7 | 8 | 9 | 10 | true 11 | 12 | 13 | 14 | true 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Always 26 | 27 | 28 | Always 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /AimBot.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30517.126 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AimBot", "AimBot.csproj", "{464C909F-CADC-472F-A5F3-28462CB44F00}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {464C909F-CADC-472F-A5F3-28462CB44F00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {464C909F-CADC-472F-A5F3-28462CB44F00}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {464C909F-CADC-472F-A5F3-28462CB44F00}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {464C909F-CADC-472F-A5F3-28462CB44F00}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {4E5D822C-B860-414C-84A6-8EB562572CE3} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /Aimers/Aimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Injectors; 5 | 6 | namespace AimBot.Aimers 7 | { 8 | public interface Aimer : IDisposable 9 | { 10 | void Aim(MouseInjector injector, Point target, Point position, double dt); 11 | void Tick(MouseInjector injector, bool aiming, double dt); 12 | void Clear(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aimers/FeedbackAimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Injectors; 5 | 6 | namespace AimBot.Aimers 7 | { 8 | public class FeedbackAimer : Aimer 9 | { 10 | public enum ControllerType 11 | { 12 | P, 13 | PI, 14 | PID 15 | } 16 | 17 | private const double referenceFps = 100.0; // The FPS for which the controller parameters were tuned. 18 | 19 | private ControllerType type; 20 | private double ku; 21 | private double tu; 22 | private double pc; 23 | private double ic; 24 | private double dc; 25 | private double mxs; 26 | private double mys; 27 | private double mxa; 28 | private double mxd; 29 | private double mya; 30 | private double myd; 31 | private double cxd; 32 | private double cyud; 33 | private double cydd; 34 | 35 | private Point target; 36 | private Point position; 37 | 38 | private PID pidx; 39 | private PID pidy; 40 | 41 | private double time; 42 | private double ex; 43 | private double ey; 44 | private double pxs; 45 | private double pys; 46 | 47 | private bool disposed; 48 | 49 | public ControllerType Type 50 | { 51 | get { return type; } 52 | set 53 | { 54 | type = value; 55 | Configure(); 56 | } 57 | } 58 | 59 | public double MaxHorizontalSpeed 60 | { 61 | get { return mxs; } 62 | set { mxs = value; } 63 | } 64 | 65 | public double MaxVerticalSpeed 66 | { 67 | get { return mys; } 68 | set { mys = value; } 69 | } 70 | 71 | public double MaxHorizontalAcceleration 72 | { 73 | get { return mxa; } 74 | set { mxa = value; } 75 | } 76 | 77 | public double MaxHorizontalDeceleration 78 | { 79 | get { return mxd; } 80 | set { mxd = value; } 81 | } 82 | 83 | public double MaxVerticalAcceleration 84 | { 85 | get { return mya; } 86 | set { mya = value; } 87 | } 88 | 89 | public double MaxVerticalDeceleration 90 | { 91 | get { return myd; } 92 | set { myd = value; } 93 | } 94 | 95 | public double CreepHorizontalDistance 96 | { 97 | get { return cxd; } 98 | set { cxd = value; } 99 | } 100 | 101 | public double CreepUpDistance 102 | { 103 | get { return cyud; } 104 | set { cyud = value; } 105 | } 106 | 107 | public double CreepDownDistance 108 | { 109 | get { return cydd; } 110 | set { cydd = value; } 111 | } 112 | 113 | public double CriticalGain 114 | { 115 | get { return ku; } 116 | set 117 | { 118 | ku = value; 119 | Configure(); 120 | } 121 | } 122 | 123 | public double ProportionalConstant 124 | { 125 | get { return pc; } 126 | set 127 | { 128 | pc = value; 129 | Configure(); 130 | } 131 | } 132 | 133 | public double IntegralConstant 134 | { 135 | get { return ic; } 136 | set 137 | { 138 | ic = value; 139 | Configure(); 140 | } 141 | } 142 | 143 | public double DerivativeConstant 144 | { 145 | get { return dc; } 146 | set 147 | { 148 | dc = value; 149 | Configure(); 150 | } 151 | } 152 | 153 | public double OscillationPeriod 154 | { 155 | get { return tu; } 156 | set 157 | { 158 | tu = value; 159 | Configure(); 160 | } 161 | } 162 | 163 | public FeedbackAimer() 164 | { 165 | type = ControllerType.P; 166 | ku = 0.18; 167 | tu = 0.3; 168 | pc = 0.6; 169 | ic = 0.54; 170 | dc = 0.02; 171 | mxs = 600.0; 172 | mys = 600.0; 173 | mxa = 3500.0; 174 | mxd = 10000.0; 175 | mya = 2500.0; 176 | myd = 10000.0; 177 | cxd = 10.0; 178 | cyud = 10.0; 179 | cydd = 50.0; 180 | 181 | target = Point.Empty; 182 | position = Point.Empty; 183 | 184 | Configure(); 185 | Clear(); 186 | } 187 | 188 | public void Configure(double kp, double ki, double kd) 189 | { 190 | pidx = new PID(kp, ki, kd); 191 | pidy = new PID(kp, ki, kd); 192 | } 193 | 194 | public void Configure() 195 | { 196 | double kp = 0, ki = 0, kd = 0; 197 | switch (Type) 198 | { 199 | case ControllerType.P: 200 | kp = 0.6 * CriticalGain; 201 | ki = 0.0; 202 | kd = 0.0; 203 | break; 204 | case ControllerType.PI: 205 | kp = ProportionalConstant * CriticalGain; 206 | ki = IntegralConstant * CriticalGain / OscillationPeriod; 207 | kd = 0.0; 208 | break; 209 | case ControllerType.PID: 210 | kp = ProportionalConstant * CriticalGain; 211 | ki = IntegralConstant * CriticalGain / OscillationPeriod; 212 | kd = DerivativeConstant * CriticalGain * OscillationPeriod; 213 | break; 214 | } 215 | 216 | Configure(kp, ki, kd); 217 | } 218 | 219 | public void Clear() 220 | { 221 | pxs = 0.0; 222 | pys = 0.0; 223 | time = 0.0; 224 | ex = 0.0; 225 | ey = 0.0; 226 | 227 | pidx.Clear(); 228 | pidy.Clear(); 229 | } 230 | 231 | public void Aim(MouseInjector injector, Point target, Point position, double dt) 232 | { 233 | this.target = target; 234 | this.position = position; 235 | 236 | Move(injector, dt); 237 | } 238 | 239 | public void Tick(MouseInjector injector, bool aiming, double dt) 240 | { 241 | if (aiming) 242 | { 243 | Move(injector, dt); 244 | } 245 | else 246 | { 247 | Clear(); 248 | } 249 | } 250 | 251 | private void Move(MouseInjector injector, double dt) 252 | { 253 | time += dt; 254 | 255 | if (target != Point.Empty) 256 | { 257 | var errorx = target.X - position.X; 258 | var errory = target.Y - position.Y; 259 | 260 | var dx = pidx.Tick(errorx, time); 261 | var dy = pidy.Tick(errory, time); 262 | 263 | var xs = dx / dt; 264 | var ys = dy / dt; 265 | 266 | if (errorx * errorx < cxd * cxd) { xs *= (errorx * errorx) / (cxd * cxd); } 267 | if (errory > 0 && errory * errory < cyud * cyud) { ys *= (errory * errory) / (cyud * cyud); } 268 | if (errory < 0 && errory * errory < cydd * cydd) { ys *= (errory * errory) / (cydd * cydd); } 269 | 270 | var xa = (xs - pxs) / dt; 271 | var ya = (ys - pys) / dt; 272 | 273 | if (Math.Sign(xs) * Math.Sign(pxs) >= 0) 274 | { 275 | // Same direction. 276 | if (Math.Abs(xs) >= Math.Abs(pxs)) 277 | { 278 | // Acceleration. 279 | if (mxa > 0.0) 280 | { 281 | if (xa > mxa) { xa = mxa; } 282 | if (xa < -mxa) { xa = -mxa; } 283 | } 284 | } 285 | else 286 | { 287 | // Deceleration 288 | if (mxd > 0.0) 289 | { 290 | if (xa > mxd) { xa = mxd; } 291 | if (xa < -mxd) { xa = -mxd; } 292 | } 293 | } 294 | 295 | if (Math.Abs(ys) >= Math.Abs(pys)) 296 | { 297 | // Acceleration. 298 | if (mxa > 0.0) 299 | { 300 | if (ya > mya) { ya = mya; } 301 | if (ya < -mya) { ya = -mya; } 302 | } 303 | } 304 | else 305 | { 306 | // Deceleration 307 | if (mxd > 0.0) 308 | { 309 | if (ya > myd) { ya = myd; } 310 | if (ya < -myd) { ya = -myd; } 311 | } 312 | } 313 | } 314 | else 315 | { 316 | // Different direction. 317 | // We need to decelerate to a stop. 318 | if (mxa > 0.0) 319 | { 320 | if (xa > mxd) { xa = mxd; } 321 | if (xa < -mxd) { xa = -mxd; } 322 | } 323 | 324 | if (mxd > 0.0) 325 | { 326 | if (ya > myd) { ya = myd; } 327 | if (ya < -myd) { ya = -myd; } 328 | } 329 | } 330 | 331 | xs = pxs + xa * dt; 332 | ys = pys + ya * dt; 333 | 334 | if (xs > mxs) { xs = mxs; } 335 | if (xs < -mxs) { xs = -mxs; } 336 | if (ys > mys) { ys = mys; } 337 | if (ys < -mys) { ys = -mys; } 338 | 339 | dx = xs * dt + ex; 340 | dy = ys * dt + ey; 341 | 342 | var px = (int)Math.Round(dx); 343 | var py = (int)Math.Round(dy); 344 | 345 | ex = dx - px; 346 | ey = dy - py; 347 | 348 | pxs = xs; 349 | pys = ys; 350 | 351 | if (px != 0 || py != 0) 352 | { 353 | injector.Move(px, py); 354 | } 355 | } 356 | else 357 | { 358 | Clear(); 359 | } 360 | 361 | time = 0.0; 362 | } 363 | 364 | private struct PID 365 | { 366 | private double kp; 367 | private double ki; 368 | private double kd; 369 | 370 | private double integral; 371 | private double previousError; 372 | private bool idle; 373 | 374 | public PID(double kp, double ki, double kd) 375 | { 376 | this.kp = kp; 377 | this.ki = ki; 378 | this.kd = kd; 379 | 380 | integral = 0.0; 381 | previousError = 0.0; 382 | idle = true; 383 | } 384 | 385 | public double Tick(double error, double dt) 386 | { 387 | var derivative = (idle) ? 0.0 : error - previousError; 388 | idle = false; 389 | 390 | if (dt > 0) 391 | { 392 | if (previousError != 0.0 && error * previousError < 0.0) 393 | { 394 | integral = 0.0; 395 | } 396 | else 397 | { 398 | integral += error * dt; 399 | } 400 | 401 | derivative /= dt; 402 | } 403 | 404 | previousError = error; 405 | 406 | return (dt * referenceFps) * (kp * error + ki * integral + kd * derivative); 407 | } 408 | 409 | public void Clear() 410 | { 411 | previousError = 0.0; 412 | integral = 0.0; 413 | idle = true; 414 | } 415 | } 416 | 417 | protected virtual void Dispose(bool disposing) 418 | { 419 | if (disposed == false) 420 | { 421 | if (disposing) 422 | { 423 | // TODO: dispose managed state (managed objects). 424 | } 425 | 426 | disposed = true; 427 | } 428 | } 429 | 430 | public void Dispose() 431 | { 432 | Dispose(true); 433 | } 434 | } 435 | } 436 | -------------------------------------------------------------------------------- /Aimers/FlickAimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Threading; 4 | 5 | using AimBot.Injectors; 6 | 7 | namespace AimBot.Aimers 8 | { 9 | public class FlickAimer : Aimer 10 | { 11 | private Thread thread; 12 | private double ms; // Maximum speed (in pixels per second). 13 | private double hs; // Horizontal sensitivity (mouse/screen). 14 | private double vs; // Vertical sensitivity (mouse/screen). 15 | private int ts; // Time-step (milliseconds). 16 | private int td; // Trigger delay (milliseconds). 17 | private int cd; // Cooldown (milliseconds). 18 | private bool trigger; 19 | private bool continueAiming; 20 | private bool flick; 21 | 22 | private bool disposed; 23 | 24 | public double MaxSpeed 25 | { 26 | get { return ms; } 27 | set { ms = value; } 28 | } 29 | 30 | public double HorizontalSensitivity 31 | { 32 | get { return hs; } 33 | set { hs = value; } 34 | } 35 | 36 | public double VerticalSensitivity 37 | { 38 | get { return vs; } 39 | set { vs = value; } 40 | } 41 | 42 | public int TimeStepMs 43 | { 44 | get { return ts; } 45 | set { ts = value; } 46 | } 47 | 48 | public bool Trigger 49 | { 50 | get { return trigger; } 51 | set { trigger = value; } 52 | } 53 | 54 | public bool ContinueAiming 55 | { 56 | get { return continueAiming; } 57 | set { continueAiming = value; } 58 | } 59 | 60 | public int TriggerDelayMs 61 | { 62 | get { return td; } 63 | set { td = value; } 64 | } 65 | 66 | public int CooldownMs 67 | { 68 | get { return cd; } 69 | set { cd = value; } 70 | } 71 | 72 | public FlickAimer() 73 | { 74 | ms = 4000.0; 75 | hs = 1.0; 76 | vs = 1.0; 77 | ts = 10; 78 | td = 50; 79 | cd = 250; 80 | trigger = true; 81 | continueAiming = false; 82 | flick = true; 83 | } 84 | 85 | public void Clear() 86 | { 87 | flick = true; 88 | } 89 | 90 | public void Aim(MouseInjector injector, Point target, Point position, double dt) 91 | { 92 | if (flick && target.IsEmpty == false && (thread == null || thread.IsAlive == false)) 93 | { 94 | flick = continueAiming; // Wait for aim key/button to be pressed again? 95 | thread = new Thread(() => Flick(injector, target, position, ms, hs, vs, ts, td, cd, trigger)); 96 | thread.Start(); 97 | } 98 | } 99 | 100 | public void Tick(MouseInjector injector, bool aiming, double dt) 101 | { 102 | if (aiming == false) 103 | { 104 | Clear(); 105 | } 106 | } 107 | 108 | private static void Flick(MouseInjector injector, Point target, Point position, double speed, double horizontalSensitivity, double verticalSensitivity, int timestepMs, int triggerDelayMs, int cooldownMs, bool trigger) 109 | { 110 | double ex = 0.0; 111 | double ey = 0.0; 112 | 113 | var screenx = target.X - position.X; 114 | var screeny = target.Y - position.Y; 115 | 116 | var mousex = screenx * horizontalSensitivity; 117 | var mousey = screeny * verticalSensitivity; 118 | 119 | var distance = Math.Sqrt(mousex * mousex + mousey * mousey); 120 | var time = distance / speed; 121 | 122 | var frames = (int)Math.Ceiling((time * 1000) / timestepMs); 123 | if (frames > 0) 124 | { 125 | for (int i = 0; i < frames; ++i) 126 | { 127 | var dx = ex + (double)mousex / frames; 128 | var dy = ey + (double)mousey / frames; 129 | 130 | var px = (int)Math.Round(dx); 131 | var py = (int)Math.Round(dy); 132 | 133 | ex = dx - px; 134 | ey = dy - py; 135 | 136 | if (px != 0 || py != 0) 137 | { 138 | injector.Move(px, py); 139 | } 140 | 141 | if (i < frames - 1) 142 | { 143 | Thread.Sleep(timestepMs); 144 | } 145 | else if (trigger) 146 | { 147 | Thread.Sleep(triggerDelayMs); 148 | var rng = new Random(); 149 | injector.Click(0, rng.Next(50, 80)); 150 | } 151 | } 152 | } 153 | else if (trigger) 154 | { 155 | Thread.Sleep(triggerDelayMs); 156 | var rng = new Random(); 157 | injector.Click(0, rng.Next(50, 80)); 158 | } 159 | 160 | if (cooldownMs > 0) 161 | { 162 | Thread.Sleep(cooldownMs); 163 | } 164 | } 165 | 166 | protected virtual void Dispose(bool disposing) 167 | { 168 | if (disposed == false) 169 | { 170 | if (disposing) 171 | { 172 | // TODO: dispose managed state (managed objects). 173 | } 174 | 175 | disposed = true; 176 | } 177 | } 178 | 179 | public void Dispose() 180 | { 181 | Dispose(true); 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /Aimers/HybridAimer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Threading; 4 | 5 | using AimBot.Injectors; 6 | 7 | namespace AimBot.Aimers 8 | { 9 | public class HybridAimer : Aimer 10 | { 11 | private Thread thread; 12 | private double gain; // Proportional gain. 13 | private double hs; // Horizontal sensitivity (mouse/screen). 14 | private double vs; // Vertical sensitivity (mouse/screen). 15 | private double ms; // Maximum speed (in pixels per second). 16 | private double fr; // Flick radius (in pixels). 17 | private int fd; // Flick delay (in milliseconds). 18 | private int ts; // Time-step (in milliseconds). 19 | private int td; // Trigger delay (in milliseconds). 20 | private int cd; // Cooldown (in milliseconds). 21 | private bool trigger; // Trigger after flicking? 22 | private bool continueAiming; // Continue aiming after flicking? 23 | 24 | private Point target; 25 | private Point position; 26 | 27 | private double time; 28 | private double ft; 29 | private double ex; 30 | private double ey; 31 | private bool ready; 32 | 33 | private bool disposed; 34 | 35 | public double MaxSpeed 36 | { 37 | get { return ms; } 38 | set { ms = value; } 39 | } 40 | 41 | public double Gain 42 | { 43 | get { return gain; } 44 | set { gain = value; } 45 | } 46 | 47 | public double FlickRadius 48 | { 49 | get { return fr; } 50 | set { fr = value; } 51 | } 52 | 53 | public int FlickDelayMs 54 | { 55 | get { return fd; } 56 | set { fd = value; } 57 | } 58 | 59 | public double HorizontalSensitivity 60 | { 61 | get { return hs; } 62 | set { hs = value; } 63 | } 64 | 65 | public double VerticalSensitivity 66 | { 67 | get { return vs; } 68 | set { vs = value; } 69 | } 70 | 71 | public int TimeStepMs 72 | { 73 | get { return ts; } 74 | set { ts = value; } 75 | } 76 | 77 | public bool Trigger 78 | { 79 | get { return trigger; } 80 | set { trigger = value; } 81 | } 82 | 83 | public int TriggerDelayMs 84 | { 85 | get { return td; } 86 | set { td = value; } 87 | } 88 | 89 | public int CooldownMs 90 | { 91 | get { return cd; } 92 | set { cd = value; } 93 | } 94 | 95 | public bool ContinueAiming 96 | { 97 | get { return continueAiming; } 98 | set { continueAiming = value; } 99 | } 100 | 101 | public HybridAimer() 102 | { 103 | gain = 0.1; 104 | hs = 0.65; 105 | vs = 0.65; 106 | ms = 4000.0; 107 | fd = 10; 108 | ts = 10; 109 | td = 50; 110 | cd = 250; 111 | trigger = true; 112 | continueAiming = false; 113 | 114 | Clear(); 115 | } 116 | 117 | public void Clear() 118 | { 119 | time = 0.0; 120 | ft = 0.0; 121 | ex = 0.0; 122 | ey = 0.0; 123 | ready = true; 124 | } 125 | 126 | public void Aim(MouseInjector injector, Point target, Point position, double dt) 127 | { 128 | this.target = target; 129 | this.position = position; 130 | Move(injector, true, dt); 131 | } 132 | 133 | public void Tick(MouseInjector injector, bool aiming, double dt) 134 | { 135 | if (aiming) 136 | { 137 | Move(injector, false, dt); 138 | } 139 | else 140 | { 141 | Clear(); 142 | } 143 | } 144 | 145 | private void Move(MouseInjector injector, bool canFlick, double dt) 146 | { 147 | if (ready && (thread == null || thread.IsAlive == false)) 148 | { 149 | time += dt; 150 | 151 | if (target != Point.Empty) 152 | { 153 | var errorx = target.X - position.X; 154 | var errory = target.Y - position.Y; 155 | 156 | // Determine speed using proportional control. 157 | var dx = errorx * gain * time * 100.0 + ex; 158 | var dy = errory * gain * time * 100.0 + ey; 159 | 160 | var xs = dx / dt; 161 | var ys = dy / dt; 162 | 163 | if (xs > ms) { xs = ms; } 164 | if (xs < -ms) { xs = -ms; } 165 | if (ys > ms) { ys = ms; } 166 | if (ys < -ms) { ys = -ms; } 167 | 168 | // Can we flick? 169 | if (canFlick && ft > 0.0 || Math.Sqrt(errorx * errorx + errory * errory) <= fr) 170 | { 171 | if (ft >= fd * 0.001) 172 | { 173 | ft = 0.0; 174 | ready = continueAiming; // Wait for aim key/button to be pressed again? 175 | thread = new Thread(() => Flick(injector, target, position, ms, hs, vs, ts, td, cd, trigger)); 176 | thread.Start(); 177 | } 178 | else 179 | { 180 | ft += dt; 181 | } 182 | } 183 | else // Move using proportional control. 184 | { 185 | dx = xs * dt; 186 | dy = ys * dt; 187 | 188 | var px = (int)Math.Round(dx); 189 | var py = (int)Math.Round(dy); 190 | 191 | ex = dx - px; 192 | ey = dy - py; 193 | 194 | if (px != 0 || py != 0) 195 | { 196 | injector.Move(px, py); 197 | } 198 | } 199 | } 200 | else 201 | { 202 | ex = 0.0; 203 | ey = 0.0; 204 | } 205 | } 206 | 207 | time = 0.0; 208 | } 209 | 210 | private static void Flick(MouseInjector injector, Point target, Point position, double flickSpeed, double horizontalSensitivity, double verticalSensitivity, int timestepMs, int triggerDelayMs, int cooldownMs, bool trigger) 211 | { 212 | double ex = 0.0; 213 | double ey = 0.0; 214 | 215 | var screenx = target.X - position.X; 216 | var screeny = target.Y - position.Y; 217 | 218 | var mousex = screenx * horizontalSensitivity; 219 | var mousey = screeny * verticalSensitivity; 220 | 221 | var distance = Math.Sqrt(mousex * mousex + mousey * mousey); 222 | var time = distance / flickSpeed; 223 | 224 | var frames = (int)Math.Ceiling((time * 1000) / timestepMs); 225 | for (int i = 0; i < frames; ++i) 226 | { 227 | var dx = ex + (double)mousex / frames; 228 | var dy = ey + (double)mousey / frames; 229 | 230 | var px = (int)Math.Round(dx); 231 | var py = (int)Math.Round(dy); 232 | 233 | ex = dx - px; 234 | ey = dy - py; 235 | 236 | if (px != 0 || py != 0) 237 | { 238 | injector.Move(px, py); 239 | } 240 | 241 | if (i < frames - 1) 242 | { 243 | Thread.Sleep(timestepMs); 244 | } 245 | else if (trigger) 246 | { 247 | Thread.Sleep(triggerDelayMs); 248 | var rng = new Random(); 249 | injector.Click(0, rng.Next(50, 80)); // TODO: Allow range to be configured? 250 | } 251 | } 252 | 253 | if (cooldownMs > 0) 254 | { 255 | Thread.Sleep(cooldownMs); 256 | } 257 | } 258 | 259 | protected virtual void Dispose(bool disposing) 260 | { 261 | if (disposed == false) 262 | { 263 | if (disposing) 264 | { 265 | // TODO: dispose managed state (managed objects). 266 | } 267 | 268 | disposed = true; 269 | } 270 | } 271 | 272 | public void Dispose() 273 | { 274 | Dispose(true); 275 | } 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace AimBot 10 | { 11 | /// 12 | /// Interaction logic for App.xaml 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | [assembly: ThemeInfo( 4 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 5 | //(used if a resource is not found in the page, 6 | // or application resource dictionaries) 7 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 8 | //(used if a resource is not found in the page, 9 | // app, or any theme specific resource dictionaries) 10 | )] 11 | -------------------------------------------------------------------------------- /Bot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Drawing; 4 | 5 | using Newtonsoft.Json; 6 | 7 | using AimBot.Input; 8 | using AimBot.Renderers; 9 | using AimBot.Detectors; 10 | using AimBot.Grabbers; 11 | using AimBot.Trackers; 12 | using AimBot.Selectors; 13 | using AimBot.Injectors; 14 | using AimBot.Aimers; 15 | using AimBot.Triggers; 16 | 17 | namespace AimBot 18 | { 19 | public class Bot : IDisposable 20 | { 21 | public enum ActivationKeys 22 | { 23 | None = 0, 24 | Caps = 20, 25 | } 26 | 27 | public enum ActivationButtons 28 | { 29 | None = 0, 30 | Back = GlobalMouse.Button.Back, 31 | Forward = GlobalMouse.Button.Forward, 32 | } 33 | 34 | private Grabber grabber; 35 | private Detector detector; 36 | private Tracker tracker; 37 | private Selector selector; 38 | private MouseInjector injector; 39 | private Aimer aimer; 40 | private Trigger trigger; 41 | 42 | private Stopwatch stopwatch; 43 | 44 | private ActivationKeys activationKey; 45 | private ActivationButtons activationButton; 46 | 47 | private Process process; 48 | private double time; 49 | private bool activated; 50 | private bool disposed; 51 | 52 | [JsonIgnore] 53 | public Process Process 54 | { 55 | get { return process; } 56 | set 57 | { 58 | process = value; 59 | if (injector != null) 60 | { 61 | injector.ProcessId = (process != null) ? (ulong)process.Id : 0; 62 | } 63 | } 64 | } 65 | 66 | public Grabber Grabber 67 | { 68 | get { return grabber; } 69 | set 70 | { 71 | grabber?.Dispose(); 72 | grabber = value; 73 | } 74 | } 75 | 76 | public Detector Detector 77 | { 78 | get { return detector; } 79 | set 80 | { 81 | detector?.Dispose(); 82 | detector = value; 83 | } 84 | } 85 | 86 | public Tracker Tracker 87 | { 88 | get { return tracker; } 89 | set 90 | { 91 | tracker?.Dispose(); 92 | tracker = value; 93 | } 94 | } 95 | 96 | public Selector Selector 97 | { 98 | get { return selector; } 99 | set 100 | { 101 | selector?.Dispose(); 102 | selector = value; 103 | } 104 | } 105 | 106 | public MouseInjector Injector 107 | { 108 | get { return injector; } 109 | set 110 | { 111 | injector?.Dispose(); 112 | injector = value; 113 | } 114 | } 115 | 116 | public Aimer Aimer 117 | { 118 | get { return aimer; } 119 | set 120 | { 121 | aimer?.Dispose(); 122 | aimer = value; 123 | } 124 | } 125 | 126 | public Trigger Trigger 127 | { 128 | get { return trigger; } 129 | set 130 | { 131 | trigger?.Dispose(); 132 | trigger = value; 133 | } 134 | } 135 | 136 | public ActivationKeys ActivationKey 137 | { 138 | get { return activationKey; } 139 | set { activationKey = value; } 140 | } 141 | 142 | public ActivationButtons ActivationButton 143 | { 144 | get { return activationButton; } 145 | set { activationButton = value; } 146 | } 147 | 148 | public Bot() 149 | { 150 | grabber = null; 151 | detector = null; 152 | tracker = null; 153 | selector = null; 154 | injector = null; 155 | aimer = null; 156 | trigger = null; 157 | 158 | stopwatch = new Stopwatch(); 159 | 160 | activationKey = ActivationKeys.None; 161 | activationButton = ActivationButtons.None; 162 | 163 | process = null; 164 | time = 0.0; 165 | activated = false; 166 | disposed = false; 167 | } 168 | 169 | public void OnKey(GlobalKey.KeyEventArgs e) 170 | { 171 | if (e.Data.VirtualCode == (int)activationKey) 172 | { 173 | if (e.State == GlobalKey.State.KeyUp || e.State == GlobalKey.State.SysKeyUp) 174 | { 175 | activated = false; 176 | } 177 | else 178 | { 179 | activated = true; 180 | } 181 | } 182 | } 183 | 184 | public void OnButton(GlobalMouse.ButtonEventArgs e) 185 | { 186 | if ((e.Button & (GlobalMouse.Button)activationButton) != 0) 187 | { 188 | if (e.State == GlobalMouse.State.ButtonUp) 189 | { 190 | activated = false; 191 | } 192 | else 193 | { 194 | activated = true; 195 | } 196 | } 197 | } 198 | 199 | public bool Tick(double dt, Rectangle region, Esp esp) 200 | { 201 | time += dt; 202 | 203 | if (process != null && grabber != null) 204 | { 205 | var image = grabber.Grab(process.MainWindowHandle, region, esp, true, out var changed); 206 | if (image != IntPtr.Zero && changed) 207 | { 208 | if (detector != null) 209 | { 210 | stopwatch.Restart(); 211 | 212 | var position = new Point(region.X + region.Width / 2, region.Y + region.Height / 2); 213 | var detections = detector.Detect(image, region, esp); 214 | 215 | if (tracker != null && selector != null) 216 | { 217 | tracker.Track(detections, esp, time); 218 | var target = selector.Select(tracker, position, esp, activated, time); 219 | 220 | if (aimer != null) 221 | { 222 | if (activated) 223 | { 224 | aimer.Aim(injector, target, position, dt); 225 | } 226 | else 227 | { 228 | aimer.Tick(injector, activated, dt); 229 | } 230 | } 231 | 232 | if (trigger != null) 233 | { 234 | trigger.Trigger(injector, position, target, region, esp, ref activated, time); 235 | } 236 | } 237 | 238 | time = 0.0; 239 | stopwatch.Stop(); 240 | 241 | if (esp != null) 242 | { 243 | var fps = 1000.0 / (double)stopwatch.Elapsed.TotalMilliseconds; 244 | esp.Add(new TextShape(new Point(region.X, region.Y - 20), $"FPS: {Math.Round(fps)}", Color.LimeGreen, 12)); 245 | } 246 | } 247 | else 248 | { 249 | tracker?.Clear(); 250 | selector?.Clear(); 251 | aimer?.Clear(); 252 | trigger?.Clear(); 253 | } 254 | 255 | return activated; 256 | } 257 | else 258 | { 259 | if (aimer != null) 260 | { 261 | aimer.Tick(injector, activated, dt); 262 | } 263 | 264 | stopwatch.Stop(); 265 | } 266 | } 267 | 268 | return false; 269 | } 270 | 271 | protected virtual void Dispose(bool disposing) 272 | { 273 | if (disposed == false) 274 | { 275 | if (disposing) 276 | { 277 | grabber?.Dispose(); 278 | detector?.Dispose(); 279 | tracker?.Dispose(); 280 | selector?.Dispose(); 281 | injector?.Dispose(); 282 | aimer?.Dispose(); 283 | trigger?.Dispose(); 284 | } 285 | 286 | disposed = true; 287 | } 288 | } 289 | 290 | public void Dispose() 291 | { 292 | Dispose(true); 293 | } 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /Detectors/Detector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Text.RegularExpressions; 6 | using AimBot.Helpers; 7 | using AimBot.Renderers; 8 | 9 | namespace AimBot.Detectors 10 | { 11 | [Flags] 12 | public enum Selecting 13 | { 14 | Head = 1 << 0, 15 | Body = 1 << 1, 16 | Both = Head | Body 17 | } 18 | 19 | public enum Anchor 20 | { 21 | Center, 22 | TopCenter, 23 | BottomCenter 24 | } 25 | 26 | public enum Units 27 | { 28 | Pixels, 29 | Percentage 30 | } 31 | 32 | public readonly struct Detection 33 | { 34 | public readonly Rectangle BoundingBox; 35 | public readonly Point HeadPosition; 36 | public readonly Point BodyPosition; 37 | public readonly double Confidence; // In the interval [0.0, 1.0]. 38 | 39 | public Detection(Rectangle boundingBox, Point headPosition, Point bodyPosition, double confidence) 40 | { 41 | BoundingBox = boundingBox; 42 | HeadPosition = headPosition; 43 | BodyPosition = bodyPosition; 44 | Confidence = confidence; 45 | } 46 | } 47 | 48 | public interface Detector : IDisposable 49 | { 50 | List Detect(IntPtr image, Rectangle region, Esp esp); 51 | } 52 | 53 | public abstract class NeuralNetDetector 54 | { 55 | private readonly FileFilter configurationFile; 56 | private readonly List detections; 57 | 58 | public FileFilter ConfigurationFile 59 | { 60 | get { return configurationFile; } 61 | } 62 | 63 | public Anchor AnchorPoint { get; set; } = Anchor.Center; 64 | public Units OffsetUnits { get; set; } = Units.Pixels; 65 | public int HeadHorizontalOffset { get; set; } = 0; 66 | public int HeadVerticalOffset { get; set; } = 0; 67 | public int BodyHorizontalOffset { get; set; } = 0; 68 | public int BodyVerticalOffset { get; set; } = 0; 69 | public double DetectionThreshold { get; set; } = 0.05; 70 | 71 | protected int InputWidth { get; private set; } = 512; 72 | protected int InputHeight { get; private set; } = 512; 73 | 74 | protected NeuralNetDetector() 75 | { 76 | configurationFile = new FileFilter("Detectors", "*.cfg", ""); 77 | configurationFile.OnFileChanged += OnConfigurationFileChanged; 78 | 79 | detections = new List(); 80 | } 81 | 82 | private void OnConfigurationFileChanged(FileFilter obj) 83 | { 84 | var filePath = ConfigurationFile.FilePath; 85 | if (File.Exists(filePath)) 86 | { 87 | using (var reader = File.OpenText(filePath)) 88 | { 89 | var line = reader.ReadLine(); 90 | while (line != null) 91 | { 92 | var parts = line.Split("="); 93 | if (parts != null && parts.Length == 2) 94 | { 95 | switch (parts[0]) 96 | { 97 | case "width": 98 | InputWidth = int.Parse(parts[1]); 99 | break; 100 | case "height": 101 | InputHeight = int.Parse(parts[1]); 102 | break; 103 | } 104 | } 105 | 106 | line = reader.ReadLine(); 107 | } 108 | } 109 | } 110 | 111 | Reload(); 112 | } 113 | 114 | protected abstract bool Reload(); 115 | 116 | protected abstract void AddDetections(IntPtr image, Rectangle region, Esp esp, List detections); 117 | 118 | public List Detect(IntPtr image, Rectangle region, Esp esp) 119 | { 120 | detections.Clear(); 121 | AddDetections(image, region, esp, detections); 122 | return detections; 123 | } 124 | 125 | protected void AddDetection(int classId, Rectangle bounds, double confidence, Esp esp) 126 | { 127 | var center = bounds.Center(); 128 | 129 | if (esp != null) 130 | { 131 | esp.Add(new TextShape(new Point(bounds.Left, bounds.Top - 12) , $"ID: {classId}", Color.Red, 12)); 132 | esp.Add(new RectangleShape(new Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height), Color.Transparent, Color.Red, 2)); 133 | } 134 | 135 | int hho = 0; 136 | int hvo = 0; 137 | int bho = 0; 138 | int bvo = 0; 139 | 140 | switch (OffsetUnits) 141 | { 142 | case Units.Pixels: 143 | hho = HeadHorizontalOffset; 144 | hvo = HeadVerticalOffset; 145 | bho = BodyHorizontalOffset; 146 | bvo = BodyVerticalOffset; 147 | break; 148 | case Units.Percentage: 149 | hho = (int)Math.Round(bounds.Width * HeadHorizontalOffset * 0.01); 150 | hvo = (int)Math.Round(bounds.Height * HeadVerticalOffset * 0.01); 151 | bho = (int)Math.Round(bounds.Width * BodyHorizontalOffset * 0.01); 152 | bvo = (int)Math.Round(bounds.Height * BodyVerticalOffset * 0.01); 153 | break; 154 | } 155 | 156 | var head = Point.Empty; 157 | var body = Point.Empty; 158 | 159 | switch (AnchorPoint) 160 | { 161 | case Anchor.Center: 162 | head = new Point(center.X + hho, center.Y + hvo); 163 | body = new Point(center.X + bho, center.Y + bvo); 164 | break; 165 | case Anchor.TopCenter: 166 | head = new Point(center.X + hho, bounds.Top + hvo); 167 | body = new Point(center.X + bho, bounds.Top + bvo); 168 | break; 169 | case Anchor.BottomCenter: 170 | head = new Point(center.X + hho, bounds.Bottom + hvo); 171 | body = new Point(center.X + bho, bounds.Bottom + bvo); 172 | break; 173 | } 174 | 175 | detections.Add(new Detection(bounds, head, body, confidence)); 176 | 177 | if (esp != null) 178 | { 179 | esp.Add(new CircleShape(new Point(head.X, head.Y), 5, Color.Transparent, Color.Red, 1)); 180 | 181 | if (head != body) 182 | { 183 | esp.Add(new CircleShape(new Point(body.X, body.Y), 5, Color.Transparent, Color.Red, 1)); 184 | } 185 | } 186 | } 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /Detectors/OpenCV.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kermado/NeuralBot/3a5fc6b3cace10dd5224cffb8153bb0866fedc47/Detectors/OpenCV.dll -------------------------------------------------------------------------------- /Detectors/OpenComputerVisionDetector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.IO; 6 | using System.Runtime.InteropServices; 7 | 8 | using AimBot.Renderers; 9 | 10 | namespace AimBot.Detectors 11 | { 12 | public class OpenComputerVisionDetector : NeuralNetDetector, Detector 13 | { 14 | private class OpenCV : IDisposable 15 | { 16 | #region P/Invoke Signatures 17 | private const string LibraryName = "Detectors/OpenCV.dll"; 18 | 19 | [DllImport(LibraryName, EntryPoint = "create")] 20 | private static extern IntPtr Create(string configurationPath, string weightsPath); 21 | 22 | [DllImport(LibraryName, EntryPoint = "detect")] 23 | private static extern int Detect(IntPtr instance, IntPtr data, int width, int height, bool swap, IntPtr boxes); 24 | 25 | [DllImport(LibraryName, EntryPoint = "release")] 26 | private static extern int Release(IntPtr instance); 27 | 28 | [StructLayout(LayoutKind.Sequential)] 29 | public struct BBox 30 | { 31 | public int classId; 32 | public int x; 33 | public int y; 34 | public int width; 35 | public int height; 36 | public float confidence; 37 | }; 38 | #endregion 39 | 40 | private BBox[] boxes; 41 | private IntPtr instance; 42 | private bool disposed; 43 | 44 | public OpenCV(string configurationPath, string weightsPath) 45 | { 46 | boxes = new BBox[1000]; 47 | instance = Create(configurationPath, weightsPath); 48 | } 49 | 50 | public BBox[] Detect(IntPtr bytes, int width, int height, bool swap, out int count) 51 | { 52 | var handle = GCHandle.Alloc(boxes, GCHandleType.Pinned); 53 | 54 | try 55 | { 56 | count = Detect(instance, bytes, width, height, swap, handle.AddrOfPinnedObject()); 57 | 58 | if (count <= 0) 59 | { 60 | return null; 61 | } 62 | 63 | return boxes; 64 | } 65 | finally 66 | { 67 | handle.Free(); 68 | } 69 | } 70 | 71 | protected virtual void Dispose(bool disposing) 72 | { 73 | if (disposed == false) 74 | { 75 | if (disposing) 76 | { 77 | // TODO: dispose managed state (managed objects). 78 | } 79 | 80 | Release(instance); 81 | disposed = true; 82 | } 83 | } 84 | 85 | ~OpenCV() 86 | { 87 | Dispose(false); 88 | } 89 | 90 | public void Dispose() 91 | { 92 | Dispose(true); 93 | GC.SuppressFinalize(this); 94 | } 95 | } 96 | 97 | private bool disposed; 98 | private OpenCV opencv; 99 | private readonly Resizer resizer; 100 | private bool swap; 101 | 102 | public bool SwapRB 103 | { 104 | get { return swap; } 105 | set { swap = value; } 106 | } 107 | 108 | public OpenComputerVisionDetector() 109 | { 110 | disposed = false; 111 | opencv = null; 112 | resizer = new Resizer(); 113 | swap = false; 114 | } 115 | 116 | protected override bool Reload() 117 | { 118 | if (opencv != null) 119 | { 120 | opencv.Dispose(); 121 | } 122 | 123 | if (File.Exists(ConfigurationFile.FilePath)) 124 | { 125 | var weightsPath = Path.ChangeExtension(ConfigurationFile.FilePath, ".weights"); 126 | if (File.Exists(weightsPath)) 127 | { 128 | opencv = new OpenCV(ConfigurationFile.FilePath, weightsPath); 129 | } 130 | } 131 | 132 | return false; 133 | } 134 | 135 | protected override void AddDetections(IntPtr image, Rectangle region, Esp esp, List detections) 136 | { 137 | if (opencv != null && image != IntPtr.Zero) 138 | { 139 | var resized = resizer.Resize(image, region.Width, region.Height, InputWidth, InputHeight); 140 | if (resized != IntPtr.Zero) 141 | { 142 | var ratiox = (double)region.Width / InputWidth; 143 | var ratioy = (double)region.Height / InputHeight; 144 | 145 | var results = opencv.Detect(resized, InputWidth, InputHeight, SwapRB, out var count); 146 | if (results != null && results.Length > 0) 147 | { 148 | for (int i = 0; i < count; ++i) 149 | { 150 | var result = results[i]; 151 | if (result.confidence >= DetectionThreshold) 152 | { 153 | var x = (int)(result.x * ratiox); 154 | var y = (int)(result.y * ratioy); 155 | var w = (int)(result.width * ratiox); 156 | var h = (int)(result.height * ratioy); 157 | 158 | var bounds = new Rectangle(region.X + x, region.Y + y, w, h); 159 | AddDetection(result.classId, bounds, result.confidence, esp); 160 | } 161 | } 162 | } 163 | } 164 | } 165 | } 166 | 167 | protected virtual void Dispose(bool disposing) 168 | { 169 | if (disposed == false) 170 | { 171 | if (disposing) 172 | { 173 | resizer?.Dispose(); 174 | opencv?.Dispose(); 175 | } 176 | 177 | opencv = null; 178 | disposed = true; 179 | } 180 | } 181 | 182 | public void Dispose() 183 | { 184 | Dispose(true); 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /Detectors/Resizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace AimBot.Detectors 5 | { 6 | public class Resizer : IDisposable 7 | { 8 | #region P/Invoke Signatures 9 | [DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] 10 | public static extern IntPtr MemCpy(IntPtr dest, IntPtr src, UIntPtr count); 11 | #endregion 12 | 13 | private int width; 14 | private int height; 15 | private IntPtr resized; 16 | private bool disposed; 17 | 18 | public Resizer() 19 | { 20 | width = 0; 21 | height = 0; 22 | resized = IntPtr.Zero; 23 | disposed = false; 24 | } 25 | 26 | public IntPtr Resize(IntPtr source, int sourceWidth, int sourceHeight, int resizedWidth, int resizedHeight) 27 | { 28 | // Check resizing necessary. 29 | if (sourceWidth == resizedWidth && sourceHeight == resizedHeight) 30 | { 31 | return source; 32 | } 33 | 34 | // Check need to reallocate memory. 35 | if (width != resizedWidth || height != resizedHeight) 36 | { 37 | if (resized != IntPtr.Zero) 38 | { 39 | Marshal.FreeHGlobal(resized); 40 | resized = IntPtr.Zero; 41 | } 42 | 43 | resized = Marshal.AllocHGlobal(resizedWidth * resizedHeight * 3 * sizeof(float)); 44 | width = resizedWidth; 45 | height = resizedHeight; 46 | } 47 | 48 | for (int c = 0; c < 3; ++c) 49 | { 50 | var resizedPage = resized + (width * height * c * sizeof(float)); 51 | var sourcePage = source + (sourceWidth * sourceHeight * c * sizeof(float)); 52 | NearestNeighbour(resizedPage, sourcePage, width, height, sourceWidth, sourceHeight); 53 | } 54 | 55 | return resized; 56 | } 57 | 58 | // See: http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/ 59 | private static void NearestNeighbour(IntPtr resized, IntPtr source, int resizedWidth, int resizedHeight, int sourceWidth, int sourceHeight) 60 | { 61 | double rx = (double)sourceWidth / resizedWidth; 62 | double ry = (double)sourceHeight / resizedHeight; 63 | 64 | unsafe 65 | { 66 | float* rsz = (float*)resized.ToPointer(); 67 | float* src = (float*)source.ToPointer(); 68 | 69 | double px, py; 70 | double srs; 71 | int rrs; 72 | for (int y = 0; y < resizedHeight; ++y) 73 | { 74 | py = Math.Floor(y * ry); 75 | rrs = y * resizedWidth; 76 | srs = py * sourceWidth; 77 | for (int x = 0; x < resizedWidth; ++x) 78 | { 79 | px = Math.Floor(x * rx); 80 | rsz[rrs + x] = src[(int)(srs + px)]; 81 | } 82 | } 83 | } 84 | } 85 | 86 | protected virtual void Dispose(bool disposing) 87 | { 88 | if (disposed == false) 89 | { 90 | if (disposing) 91 | { 92 | // TODO: dispose managed state (managed objects). 93 | } 94 | 95 | if (resized != IntPtr.Zero) 96 | { 97 | Marshal.FreeHGlobal(resized); 98 | resized = IntPtr.Zero; 99 | } 100 | 101 | disposed = true; 102 | } 103 | } 104 | 105 | ~Resizer() 106 | { 107 | Dispose(false); 108 | } 109 | 110 | public void Dispose() 111 | { 112 | Dispose(true); 113 | GC.SuppressFinalize(this); 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /FileFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | using Newtonsoft.Json; 5 | 6 | namespace AimBot 7 | { 8 | public class FileFilter 9 | { 10 | public delegate void FileChanged(FileFilter obj); 11 | 12 | private string directory; 13 | private string pattern; 14 | private string filename; 15 | 16 | public event FileChanged OnFileChanged; 17 | 18 | public FileFilter(string directory, string pattern, string filename) 19 | { 20 | this.directory = directory; 21 | this.pattern = pattern; 22 | this.filename = filename; 23 | } 24 | 25 | public string FileName 26 | { 27 | get { return filename; } 28 | set 29 | { 30 | if (filename != value) 31 | { 32 | filename = value; 33 | OnFileChanged?.Invoke(this); 34 | } 35 | } 36 | } 37 | 38 | public string FilePath 39 | { 40 | get { return Path.Combine(directory, filename); } 41 | } 42 | 43 | [JsonIgnore] 44 | public IEnumerable FileNames 45 | { 46 | get 47 | { 48 | foreach (var path in Directory.GetFiles(directory, pattern)) 49 | { 50 | yield return Path.GetFileName(path); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Grabbers/DXGrabber.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kermado/NeuralBot/3a5fc6b3cace10dd5224cffb8153bb0866fedc47/Grabbers/DXGrabber.dll -------------------------------------------------------------------------------- /Grabbers/DxGrabber.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Runtime.InteropServices; 4 | 5 | using AimBot.Renderers; 6 | 7 | namespace AimBot.Grabbers 8 | { 9 | /// 10 | /// DirectX screen grabber. 11 | /// 12 | /// 13 | /// Uses the desktop duplication API. 14 | /// 15 | public class DXGrabber : Grabber 16 | { 17 | #region P/Invoke Signatures 18 | private const string LibraryName = "Grabbers/DxGrabber.dll"; 19 | 20 | [DllImport(LibraryName, EntryPoint = "create")] 21 | private static extern IntPtr Create(); 22 | 23 | [DllImport(LibraryName, EntryPoint = "release")] 24 | private static extern void Release(IntPtr native); 25 | 26 | [DllImport(LibraryName, EntryPoint = "grab")] 27 | private static extern IntPtr Capture(IntPtr native, int x, int y, int width, int height, int format, int timeout, bool wait, ref int frames); 28 | 29 | [DllImport(LibraryName, EntryPoint = "save")] 30 | private static extern void Save(IntPtr native, int x, int y, int width, int height, int format, int timeout, string filepath); 31 | #endregion 32 | 33 | private IntPtr native; 34 | private bool disposed; 35 | 36 | public DXGrabber() 37 | { 38 | native = Create(); 39 | disposed = false; 40 | } 41 | 42 | public IntPtr Grab(IntPtr windowHandle, Rectangle region, Esp esp, bool wait, out bool changed) 43 | { 44 | esp?.Add(new RectangleShape(region, Color.Transparent, Color.LimeGreen, 2)); 45 | 46 | if (native != IntPtr.Zero) 47 | { 48 | int frames = 0; 49 | var data = Capture(native, region.X, region.Y, region.Width, region.Height, 1, 1000, wait, ref frames); 50 | changed = frames > 0; 51 | 52 | return data; 53 | } 54 | 55 | changed = false; 56 | return IntPtr.Zero; 57 | } 58 | 59 | protected virtual void Dispose(bool disposing) 60 | { 61 | if (disposed == false) 62 | { 63 | if (disposing) 64 | { 65 | // TODO: dispose managed state (managed objects). 66 | } 67 | 68 | if (native != IntPtr.Zero) 69 | { 70 | Release(native); 71 | } 72 | 73 | disposed = true; 74 | } 75 | } 76 | 77 | ~DXGrabber() 78 | { 79 | Dispose(false); 80 | } 81 | 82 | public void Dispose() 83 | { 84 | Dispose(true); 85 | GC.SuppressFinalize(this); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Grabbers/GdiGrabber.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Imaging; 4 | using System.Runtime.InteropServices; 5 | 6 | using AimBot.Renderers; 7 | 8 | namespace AimBot.Grabbers 9 | { 10 | public class GdiGrabber : Grabber 11 | { 12 | #region P/Invoke Signatures 13 | [DllImport("user32.dll")] 14 | private static extern IntPtr GetDC(IntPtr hWnd); 15 | 16 | [DllImport("gdi32.dll")] 17 | private static extern bool DeleteDC(IntPtr hdc); 18 | 19 | [DllImport("user32.dll")] 20 | private static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC); 21 | 22 | [DllImport("gdi32.dll")] 23 | private static extern IntPtr CreateCompatibleDC(IntPtr hdc); 24 | 25 | [DllImport("gdi32.dll")] 26 | private static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int width, int height); 27 | 28 | [DllImport("gdi32.dll")] 29 | private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); 30 | 31 | [DllImport("gdi32.dll")] 32 | private static extern bool DeleteObject(IntPtr hObject); 33 | 34 | [DllImport("gdi32.dll", SetLastError = true)] 35 | private static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop); 36 | 37 | [DllImport("gdi32.dll", SetLastError = true)] 38 | private static extern int GetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan, uint cScanLines, [Out] byte[] lpvBits, ref BITMAPINFOHEADER lpbi, uint uUsage); 39 | 40 | [DllImport("msvcrt.dll", EntryPoint = "memcmp")] 41 | private static extern int CompareMemory(IntPtr b1, IntPtr b2, long count); 42 | 43 | [StructLayout(LayoutKind.Sequential)] 44 | private struct BITMAPINFOHEADER 45 | { 46 | public uint biSize; 47 | public int biWidth; 48 | public int biHeight; 49 | public ushort biPlanes; 50 | public ushort biBitCount; 51 | public uint biCompression; 52 | public uint biSizeImage; 53 | public int biXPelsPerMeter; 54 | public int biYPelsPerMeter; 55 | public uint biClrUsed; 56 | public uint biClrImportant; 57 | } 58 | #endregion 59 | 60 | private IntPtr current; 61 | private IntPtr previous; 62 | private byte[] data; 63 | private int currentNumBytes; 64 | private int previousNumBytes; 65 | private int width; 66 | private int height; 67 | private bool disposed; 68 | 69 | public GdiGrabber() 70 | { 71 | current = IntPtr.Zero; 72 | previous = IntPtr.Zero; 73 | 74 | disposed = false; 75 | } 76 | 77 | public IntPtr Grab(IntPtr windowHandle, Rectangle region, Esp esp, bool wait, out bool changed) 78 | { 79 | changed = false; 80 | 81 | if (esp != null) 82 | { 83 | esp.Add(new RectangleShape(region, Color.Transparent, Color.LimeGreen, 2)); 84 | } 85 | 86 | // Reuse existing bitmap if possible. 87 | // Better not to hammer the GC. 88 | width = region.Width; 89 | height = region.Height; 90 | var numPixels = width * height; 91 | var numBytes = numPixels * 12; 92 | 93 | if (current == IntPtr.Zero || currentNumBytes != numBytes) 94 | { 95 | if (current != IntPtr.Zero) 96 | { 97 | Marshal.FreeHGlobal(current); 98 | current = IntPtr.Zero; 99 | } 100 | 101 | current = Marshal.AllocHGlobal(numBytes); 102 | currentNumBytes = numBytes; 103 | } 104 | 105 | if (previous == IntPtr.Zero || previousNumBytes != numBytes) 106 | { 107 | if (previous != IntPtr.Zero) 108 | { 109 | Marshal.FreeHGlobal(previous); 110 | previous = IntPtr.Zero; 111 | } 112 | 113 | previous = Marshal.AllocHGlobal(numBytes); 114 | previousNumBytes = numBytes; 115 | } 116 | 117 | if (data == null || data.Length != numPixels * 3) 118 | { 119 | data = new byte[numPixels * 3]; 120 | } 121 | 122 | var clientRect = Helpers.ScreenHelper.ClientRectangle(windowHandle); 123 | 124 | var hdc = GetDC(windowHandle); // Handle to display device context. 125 | var hdcMem = CreateCompatibleDC(hdc); // Create memory device context for the device. 126 | var hBitmap = CreateCompatibleBitmap(hdc, width, height); // Create a bitmap. 127 | 128 | do 129 | { 130 | var hOld = SelectObject(hdcMem, hBitmap); // Select the bitmap in the memory device context. 131 | 132 | // Copy from screen to memory device context. 133 | if (BitBlt(hdcMem, 0, 0, width, height, hdc, region.X - clientRect.X, region.Y - clientRect.Y, (int)CopyPixelOperation.SourceCopy) == 0) 134 | { 135 | // Failed! 136 | int error = Marshal.GetLastWin32Error(); // TODO: 137 | } 138 | 139 | SelectObject(hdcMem, hOld); // Restore selection. 140 | 141 | var bitmapInfoHeader = new BITMAPINFOHEADER(); 142 | bitmapInfoHeader.biSize = (uint)Marshal.SizeOf(); 143 | bitmapInfoHeader.biWidth = width; 144 | bitmapInfoHeader.biHeight = -height; // Top down. 145 | bitmapInfoHeader.biPlanes = 1; 146 | bitmapInfoHeader.biBitCount = 24; 147 | bitmapInfoHeader.biCompression = 0; // BI_RGB = Uncompressed RGB 148 | bitmapInfoHeader.biSizeImage = 0; // Size of the image in bytes - set to zero for BI_RGB 149 | bitmapInfoHeader.biXPelsPerMeter = 0; 150 | bitmapInfoHeader.biYPelsPerMeter = 0; 151 | bitmapInfoHeader.biClrUsed = 0; 152 | bitmapInfoHeader.biClrImportant = 0; 153 | 154 | // Copy the bits of the RGB bitmap to the data array. 155 | var linesCopied = GetDIBits(hdc, hBitmap, 0, (uint)height, data, ref bitmapInfoHeader, 0); 156 | if (linesCopied != height || data == null) 157 | { 158 | int error = Marshal.GetLastWin32Error(); 159 | } 160 | 161 | // Copy to "current" buffer. 162 | unsafe 163 | { 164 | fixed (byte* source = data) 165 | { 166 | float* destination = (float*)current; 167 | for (int c = 0; c < 3; ++c) 168 | { 169 | float* page = destination + c * width * height; 170 | for (int y = 0; y < height; ++y) 171 | { 172 | int offset = y * width; 173 | float* scan0 = page + offset; 174 | for (int x = 0; x < width; ++x) 175 | { 176 | scan0[x] = (float)source[3 * (offset + x) + c] / 255.0F; 177 | } 178 | } 179 | } 180 | } 181 | } 182 | 183 | // Compare buffers. 184 | if (previousNumBytes != currentNumBytes) { changed = true; } 185 | else { changed = CompareMemory(previous, current, numBytes) != 0; } 186 | } 187 | while (wait == true && changed == false); 188 | 189 | // Free resources. 190 | DeleteObject(hBitmap); 191 | DeleteDC(hdcMem); 192 | ReleaseDC(IntPtr.Zero, hdc); 193 | 194 | // Swap buffers. 195 | var temp = current; 196 | current = previous; 197 | previous = temp; 198 | var temp2 = currentNumBytes; 199 | currentNumBytes = previousNumBytes; 200 | previousNumBytes = temp2; 201 | 202 | return current; 203 | } 204 | 205 | private void Save(string filepath) 206 | { 207 | if (data != null) 208 | { 209 | var bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb); 210 | var bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat); 211 | 212 | Marshal.Copy(data, 0, bitmapData.Scan0, data.Length); 213 | 214 | bitmap.UnlockBits(bitmapData); 215 | 216 | bitmap.Save(filepath); 217 | } 218 | } 219 | 220 | protected virtual void Dispose(bool disposing) 221 | { 222 | if (disposed == false) 223 | { 224 | if (disposing) 225 | { 226 | // TODO: dispose managed state (managed objects). 227 | } 228 | 229 | if (previous != IntPtr.Zero) 230 | { 231 | Marshal.FreeHGlobal(previous); 232 | } 233 | 234 | if (current != IntPtr.Zero) 235 | { 236 | Marshal.FreeHGlobal(current); 237 | } 238 | 239 | data = null; 240 | disposed = true; 241 | } 242 | } 243 | 244 | ~GdiGrabber() 245 | { 246 | Dispose(false); 247 | } 248 | 249 | public void Dispose() 250 | { 251 | Dispose(true); 252 | GC.SuppressFinalize(this); 253 | } 254 | } 255 | } 256 | -------------------------------------------------------------------------------- /Grabbers/Grabber.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Renderers; 5 | 6 | namespace AimBot.Grabbers 7 | { 8 | public interface Grabber : IDisposable 9 | { 10 | /// 11 | /// Grabs the specified region of the window as an image. 12 | /// 13 | /// The window handle. 14 | /// The region. 15 | /// The esp, which can be rendered to. 16 | /// Whether to block until an image is available. 17 | /// Whether the image may have changed. 18 | /// Pointer to the unmanaged byte array for the image. 19 | IntPtr Grab(IntPtr windowHandle, Rectangle region, Esp esp, bool wait, out bool changed); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Helpers/ListExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace AimBot.Helpers 4 | { 5 | public static class ListExtensions 6 | { 7 | public static T RemoveFast(this List list, int index) 8 | { 9 | var last = list.Count - 1; 10 | var item = list[index]; 11 | list[index] = list[last]; 12 | list.RemoveAt(last); 13 | return item; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Helpers/PointExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace AimBot.Helpers 5 | { 6 | public static class PointExtensions 7 | { 8 | public static int DistanceSq(this Point p1, Point p2) 9 | { 10 | var vx = p2.X - p1.X; 11 | var vy = p2.Y - p1.Y; 12 | return vx * vx + vy * vy; 13 | } 14 | 15 | public static double Distance(this Point p1, Point p2) 16 | { 17 | var vx = p2.X - p1.X; 18 | var vy = p2.Y - p1.Y; 19 | return Math.Sqrt(vx * vx + vy * vy); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Helpers/RectangleExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace AimBot.Helpers 4 | { 5 | public static class RectangleExtensions 6 | { 7 | public static Point Center(this Rectangle rect) 8 | { 9 | return new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2); 10 | } 11 | 12 | public static Point TopLeft(this Rectangle rect) 13 | { 14 | return new Point(rect.X, rect.Y); 15 | } 16 | 17 | public static Point TopRight(this Rectangle rect) 18 | { 19 | return new Point(rect.X + rect.Width, rect.Y); 20 | } 21 | 22 | public static Point BottomRight(this Rectangle rect) 23 | { 24 | return new Point(rect.X + rect.Width, rect.Y + rect.Height); 25 | } 26 | 27 | public static Point CenterRight(this Rectangle rect) 28 | { 29 | return new Point(rect.X + rect.Width, rect.Y + rect.Height / 2); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Helpers/ScreenHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace AimBot.Helpers 6 | { 7 | public static class ScreenHelper 8 | { 9 | #region P/Invoke Signatures 10 | [StructLayout(LayoutKind.Sequential)] 11 | private struct RECT 12 | { 13 | public int Left; 14 | public int Top; 15 | public int Right; 16 | public int Bottom; 17 | } 18 | 19 | [StructLayout(LayoutKind.Sequential)] 20 | public struct POINT 21 | { 22 | public int X; 23 | public int Y; 24 | 25 | public POINT(int x, int y) 26 | { 27 | this.X = x; 28 | this.Y = y; 29 | } 30 | } 31 | 32 | [DllImport("user32.dll")] 33 | private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); 34 | 35 | [DllImport("user32.dll")] 36 | private static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); 37 | 38 | [DllImport("user32.dll")] 39 | private static extern bool ClientToScreen(IntPtr hWnd, ref POINT lpPoint); 40 | #endregion 41 | 42 | /// 43 | /// Determines the rectangle that bounds the specified window, including the title bar, any 44 | /// borders, scroll bars, etc. 45 | /// 46 | /// 47 | /// The rectangle returned is in screen coordinates. 48 | /// 49 | /// The handle to the window. 50 | /// The bounding rectangle (in screen coordinates). 51 | public static Rectangle WindowRectangle(IntPtr windowHandle) 52 | { 53 | GetWindowRect(windowHandle, out var rect); 54 | return new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top); 55 | } 56 | 57 | /// 58 | /// Determines the the width and height of the client area of the specified window. This 59 | /// excludes things like the title bar, any borders, scroll bars, etc. 60 | /// 61 | /// The handle to the window. 62 | /// The client area width. 63 | /// The client area height. 64 | public static void ClientDimensions(IntPtr windowHandle, out int width, out int height) 65 | { 66 | GetClientRect(windowHandle, out var rect); 67 | width = rect.Right - rect.Left; 68 | height = rect.Bottom - rect.Top; 69 | } 70 | 71 | /// 72 | /// Converts the specified screen-space point to window-space. 73 | /// 74 | /// The handle to the window. 75 | /// The screen-space point. 76 | /// The window-space point. 77 | public static Point ScreenToWindowCoordinates(IntPtr windowHandle, Point screenPoint) 78 | { 79 | var rect = WindowRectangle(windowHandle); 80 | return new Point(screenPoint.X - rect.X, screenPoint.Y - rect.Y); 81 | } 82 | 83 | /// 84 | /// Converts the specified client-space point to screen-space. 85 | /// 86 | /// The handle to the window. 87 | /// The client-space point. 88 | /// The screen-space point. 89 | public static Point ClientToScreenCoordinates(IntPtr windowHandle, Point clientPoint) 90 | { 91 | var point = new POINT(clientPoint.X, clientPoint.Y); 92 | ClientToScreen(windowHandle, ref point); 93 | return new Point(point.X, point.Y); 94 | } 95 | 96 | /// 97 | /// Converts the specified client-space point to window-space. 98 | /// 99 | /// The handle to the window. 100 | /// The client-space point. 101 | /// The window-space point. 102 | public static Point ClientToWindowCoordinates(IntPtr windowHandle, Point clientPoint) 103 | { 104 | return ScreenToWindowCoordinates(windowHandle, ClientToScreenCoordinates(windowHandle, clientPoint)); 105 | } 106 | 107 | /// 108 | /// Determines the rectangle that bounds the client area of the specified window. This 109 | /// excludes things like the title bar, any borders, scroll bars, etc. 110 | /// 111 | /// 112 | /// The rectangle returned is in screen coordinates. 113 | /// 114 | /// The handle to the window. 115 | /// The bounding rectangle for the client area (in screen coordinates). 116 | public static Rectangle ClientRectangle(IntPtr windowHandle) 117 | { 118 | GetClientRect(windowHandle, out var rect); 119 | var topLeft = new POINT(rect.Left, rect.Top); 120 | var bottomRight = new POINT(rect.Right, rect.Bottom); 121 | ClientToScreen(windowHandle, ref topLeft); 122 | ClientToScreen(windowHandle, ref bottomRight); 123 | return new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /Helpers/TypeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | 6 | namespace AimBot.Helpers 7 | { 8 | public static class TypeHelper 9 | { 10 | public static IEnumerable ConcreteTypes(Type baseType) 11 | { 12 | foreach (var concreteType in baseType.Assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t) && t.IsAbstract == false && t.IsInterface == false)) 13 | { 14 | yield return concreteType; 15 | } 16 | } 17 | 18 | public static IEnumerable ConcreteTypeNames(Type baseType) 19 | { 20 | foreach (var concreteType in ConcreteTypes(baseType)) 21 | { 22 | yield return concreteType.Name; 23 | } 24 | } 25 | 26 | public static IEnumerable PublicProperties(object obj) 27 | { 28 | if (obj != null) 29 | { 30 | foreach (var prop in obj.GetType().GetProperties()) 31 | { 32 | yield return prop; 33 | } 34 | } 35 | else 36 | { 37 | yield break; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Injectors/MouseInjector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | using Newtonsoft.Json; 4 | 5 | namespace AimBot.Injectors 6 | { 7 | public interface MouseInjector : IDisposable 8 | { 9 | /// 10 | /// The ID for the process into which the mouse events are to be injected. 11 | /// 12 | [JsonIgnore] 13 | public UInt64 ProcessId { get; set; } 14 | 15 | /// 16 | /// Presses and releases the specified button. 17 | /// 18 | /// The button (0 = left, 1 = right). 19 | /// The delay after which the button is released (in milliseconds). 20 | void Click(int button, int releaseMilliseconds); 21 | 22 | /// 23 | /// Moves the mouse cursor. 24 | /// 25 | /// 26 | /// The x-coordinate (in screen-space). 27 | /// The y-coordinate (in screen-space). 28 | void Move(int x, int y); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Injectors/WindowsMouseInjector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Threading; 4 | 5 | namespace AimBot.Injectors 6 | { 7 | public class WindowsMouseInjector : MouseInjector 8 | { 9 | #region P/Invoke Signatures 10 | private enum SendInputEventType : int 11 | { 12 | InputMouse, 13 | InputKeyboard, 14 | InputHardware 15 | } 16 | 17 | [Flags] 18 | private enum MouseEventFlags : uint 19 | { 20 | MOUSEEVENTF_MOVE = 0x0001, 21 | MOUSEEVENTF_LEFTDOWN = 0x0002, 22 | MOUSEEVENTF_LEFTUP = 0x0004, 23 | MOUSEEVENTF_RIGHTDOWN = 0x0008, 24 | MOUSEEVENTF_RIGHTUP = 0x0010, 25 | MOUSEEVENTF_MIDDLEDOWN = 0x0020, 26 | MOUSEEVENTF_MIDDLEUP = 0x0040, 27 | MOUSEEVENTF_XDOWN = 0x0080, 28 | MOUSEEVENTF_XUP = 0x0100, 29 | MOUSEEVENTF_WHEEL = 0x0800, 30 | MOUSEEVENTF_VIRTUALDESK = 0x4000, 31 | MOUSEEVENTF_ABSOLUTE = 0x8000 32 | } 33 | 34 | private struct MouseInputData 35 | { 36 | public int dx; 37 | public int dy; 38 | public uint mouseData; 39 | public MouseEventFlags dwFlags; 40 | public uint time; 41 | public IntPtr dwExtraInfo; 42 | } 43 | 44 | [StructLayout(LayoutKind.Sequential)] 45 | private struct KeyInputData 46 | { 47 | public ushort wVk; 48 | public ushort wScan; 49 | public uint dwFlags; 50 | public uint time; 51 | public IntPtr dwExtraInfo; 52 | } 53 | 54 | [StructLayout(LayoutKind.Sequential)] 55 | private struct HardwareInputData 56 | { 57 | public int uMsg; 58 | public short wParamL; 59 | public short wParamH; 60 | } 61 | 62 | [StructLayout(LayoutKind.Explicit)] 63 | private struct MouseKeybdhardwareInputUnion 64 | { 65 | [FieldOffset(0)] 66 | public MouseInputData mi; 67 | 68 | [FieldOffset(0)] 69 | public KeyInputData ki; 70 | 71 | [FieldOffset(0)] 72 | public HardwareInputData hi; 73 | } 74 | 75 | [StructLayout(LayoutKind.Sequential)] 76 | private struct Input 77 | { 78 | public SendInputEventType type; 79 | public MouseKeybdhardwareInputUnion mkhi; 80 | } 81 | 82 | [DllImport("user32.dll", SetLastError = true)] 83 | private static extern uint SendInput(uint nInputs, ref Input pInputs, int cbSize); 84 | 85 | private void MouseLeftClick(int timeMs) 86 | { 87 | var mouseDownInput = new Input(); 88 | mouseDownInput.type = SendInputEventType.InputMouse; 89 | mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTDOWN; 90 | SendInput(1, ref mouseDownInput, Marshal.SizeOf(mouseDownInput)); 91 | 92 | Thread.Sleep(timeMs); 93 | 94 | var mouseUpInput = new Input(); 95 | mouseUpInput.type = SendInputEventType.InputMouse; 96 | mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_LEFTUP; 97 | SendInput(1, ref mouseUpInput, Marshal.SizeOf(mouseUpInput)); 98 | } 99 | 100 | private void MouseRightClick(int timeMs) 101 | { 102 | var mouseDownInput = new Input(); 103 | mouseDownInput.type = SendInputEventType.InputMouse; 104 | mouseDownInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTDOWN; 105 | SendInput(1, ref mouseDownInput, Marshal.SizeOf(mouseDownInput)); 106 | 107 | Thread.Sleep(timeMs); 108 | 109 | var mouseUpInput = new Input(); 110 | mouseUpInput.type = SendInputEventType.InputMouse; 111 | mouseUpInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_RIGHTUP; 112 | SendInput(1, ref mouseUpInput, Marshal.SizeOf(mouseUpInput)); 113 | } 114 | 115 | private void MouseMove(int dx, int dy) 116 | { 117 | var mouseMoveInput = new Input(); 118 | mouseMoveInput.type = SendInputEventType.InputMouse; 119 | mouseMoveInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE; 120 | mouseMoveInput.mkhi.mi.dx = dx; 121 | mouseMoveInput.mkhi.mi.dy = dy; 122 | SendInput(1, ref mouseMoveInput, Marshal.SizeOf(mouseMoveInput)); 123 | } 124 | #endregion 125 | 126 | private ulong processId; 127 | 128 | public ulong ProcessId 129 | { 130 | get { return processId; } 131 | set { processId = value; } 132 | } 133 | 134 | public WindowsMouseInjector() 135 | { 136 | processId = 0; 137 | } 138 | 139 | public void Move(int dx, int dy) 140 | { 141 | MouseMove(dx, dy); 142 | } 143 | 144 | public void Click(int button, int releaseMilliseconds) 145 | { 146 | new Thread(() => { 147 | switch (button) 148 | { 149 | case 0: MouseLeftClick(releaseMilliseconds); break; 150 | case 1: MouseRightClick(releaseMilliseconds); break; 151 | } 152 | }).Start(); 153 | } 154 | 155 | public void Dispose() 156 | { 157 | // Nothing to do. 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Input/GlobalKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace AimBot.Input 7 | { 8 | public class GlobalKey : IDisposable 9 | { 10 | #region P/Invoke Signatures 11 | private const int WH_KEYBOARD_LL = 13; 12 | 13 | public enum State 14 | { 15 | KeyDown = 0x0100, 16 | KeyUp = 0x0101, 17 | SysKeyDown = 0x0104, 18 | SysKeyUp = 0x0105 19 | } 20 | 21 | [StructLayout(LayoutKind.Sequential)] 22 | public struct Data 23 | { 24 | public int VirtualCode; 25 | public int HardwareScanCode; 26 | public int Flags; 27 | public int TimeStamp; 28 | public IntPtr AdditionalInformation; 29 | } 30 | 31 | [DllImport("kernel32.dll")] 32 | private static extern IntPtr LoadLibrary(string lpFileName); 33 | 34 | [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 35 | private static extern bool FreeLibrary(IntPtr hModule); 36 | 37 | /// 38 | /// The SetWindowsHookEx function installs an application-defined hook procedure into a hook chain. 39 | /// You would install a hook procedure to monitor the system for certain types of events. These events are 40 | /// associated either with a specific thread or with all threads in the same desktop as the calling thread. 41 | /// 42 | /// hook type 43 | /// hook procedure 44 | /// handle to application instance 45 | /// thread identifier 46 | /// If the function succeeds, the return value is the handle to the hook procedure. 47 | [DllImport("USER32", SetLastError = true)] 48 | private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId); 49 | 50 | /// 51 | /// The UnhookWindowsHookEx function removes a hook procedure installed in a hook chain by the SetWindowsHookEx function. 52 | /// 53 | /// handle to hook procedure 54 | /// If the function succeeds, the return value is true. 55 | [DllImport("USER32", SetLastError = true)] 56 | private static extern bool UnhookWindowsHookEx(IntPtr hHook); 57 | 58 | /// 59 | /// The CallNextHookEx function passes the hook information to the next hook procedure in the current hook chain. 60 | /// A hook procedure can call this function either before or after processing the hook information. 61 | /// 62 | /// handle to current hook 63 | /// hook code passed to hook procedure 64 | /// value passed to hook procedure 65 | /// value passed to hook procedure 66 | /// If the function succeeds, the return value is true. 67 | [DllImport("USER32", SetLastError = true)] 68 | private static extern IntPtr CallNextHookEx(IntPtr hHook, int code, IntPtr wParam, IntPtr lParam); 69 | #endregion 70 | 71 | public class KeyEventArgs : HandledEventArgs 72 | { 73 | public Data Data { get; private set; } 74 | public State State { get; private set; } 75 | 76 | public KeyEventArgs(Data data, State state) 77 | { 78 | Data = data; 79 | State = state; 80 | } 81 | } 82 | 83 | private IntPtr windowsHookHandle; 84 | private IntPtr user32LibraryHandle; 85 | private HookProc hookProc; 86 | 87 | private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); 88 | 89 | public event EventHandler KeyEvent; 90 | 91 | public GlobalKey() 92 | { 93 | windowsHookHandle = IntPtr.Zero; 94 | user32LibraryHandle = IntPtr.Zero; 95 | hookProc = LowLevelKeyboardProc; // we must keep alive _hookProc, because GC is not aware about SetWindowsHookEx behaviour. 96 | 97 | user32LibraryHandle = LoadLibrary("User32"); 98 | if (user32LibraryHandle == IntPtr.Zero) 99 | { 100 | int errorCode = Marshal.GetLastWin32Error(); 101 | throw new Win32Exception(errorCode, $"Failed to load library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); 102 | } 103 | 104 | windowsHookHandle = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, user32LibraryHandle, 0); 105 | if (windowsHookHandle == IntPtr.Zero) 106 | { 107 | int errorCode = Marshal.GetLastWin32Error(); 108 | throw new Win32Exception(errorCode, $"Failed to adjust keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); 109 | } 110 | } 111 | 112 | public IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam) 113 | { 114 | bool fEatKeyStroke = false; 115 | 116 | var wparamTyped = wParam.ToInt32(); 117 | if (Enum.IsDefined(typeof(State), wparamTyped)) 118 | { 119 | var o = Marshal.PtrToStructure(lParam, typeof(Data)); 120 | var p = (Data)o; 121 | 122 | var eventArguments = new KeyEventArgs(p, (State)wparamTyped); 123 | 124 | KeyEvent?.Invoke(this, eventArguments); 125 | 126 | fEatKeyStroke = eventArguments.Handled; 127 | } 128 | 129 | return fEatKeyStroke ? (IntPtr)1 : CallNextHookEx(IntPtr.Zero, nCode, wParam, lParam); 130 | } 131 | 132 | protected virtual void Dispose(bool disposing) 133 | { 134 | if (disposing) 135 | { 136 | if (windowsHookHandle != IntPtr.Zero) 137 | { 138 | if (!UnhookWindowsHookEx(windowsHookHandle)) 139 | { 140 | var errorCode = Marshal.GetLastWin32Error(); 141 | throw new Win32Exception(errorCode, $"Failed to remove keyboard hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); 142 | } 143 | 144 | windowsHookHandle = IntPtr.Zero; 145 | hookProc -= LowLevelKeyboardProc; 146 | } 147 | } 148 | 149 | if (user32LibraryHandle != IntPtr.Zero) 150 | { 151 | if (!FreeLibrary(user32LibraryHandle)) 152 | { 153 | int errorCode = Marshal.GetLastWin32Error(); 154 | throw new Win32Exception(errorCode, $"Failed to unload library 'User32.dll'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); 155 | } 156 | 157 | user32LibraryHandle = IntPtr.Zero; 158 | } 159 | } 160 | 161 | ~GlobalKey() 162 | { 163 | Dispose(false); 164 | } 165 | 166 | public void Dispose() 167 | { 168 | Dispose(true); 169 | GC.SuppressFinalize(this); 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /Input/GlobalMouse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Drawing; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace AimBot.Input 8 | { 9 | public class GlobalMouse : IDisposable 10 | { 11 | #region P/Invoke Signatures 12 | private const int WH_MOUSE_LL = 14; 13 | private const int WH_MOUSE = 7; 14 | private const uint LLMHF_INJECTED = 1; 15 | private const uint LLMHF_LOWER_IL_INJECTED = 2; 16 | 17 | private enum MouseMessages 18 | { 19 | WM_LBUTTONDOWN = 0x0201, 20 | WM_LBUTTONUP = 0x0202, 21 | WM_MOUSEMOVE = 0x0200, 22 | WM_MOUSEWHEEL = 0x020A, 23 | WM_RBUTTONDOWN = 0x0204, 24 | WM_RBUTTONUP = 0x0205, 25 | WM_XBUTTONDOWN = 0x020B, 26 | WM_XBUTTONUP = 0x020C 27 | } 28 | 29 | private enum XButtons 30 | { 31 | XBUTTON1 = 0x0001, 32 | XBUTTON2 = 0x0002 33 | } 34 | 35 | [StructLayout(LayoutKind.Sequential)] 36 | private struct POINT 37 | { 38 | public int x; 39 | public int y; 40 | } 41 | 42 | [StructLayout(LayoutKind.Sequential)] 43 | private struct MSLLHOOKSTRUCT 44 | { 45 | public POINT pt; 46 | public uint mouseData; 47 | public uint flags; 48 | public uint time; 49 | public IntPtr dwExtraInfo; 50 | } 51 | 52 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 53 | private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId); 54 | 55 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 56 | [return: MarshalAs(UnmanagedType.Bool)] 57 | private static extern bool UnhookWindowsHookEx(IntPtr hhk); 58 | 59 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 60 | private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam); 61 | 62 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 63 | private static extern IntPtr GetModuleHandle(string lpModuleName); 64 | #endregion 65 | 66 | public enum State 67 | { 68 | ButtonDown, 69 | ButtonUp, 70 | ButtonDoubleClick 71 | } 72 | 73 | [Flags] 74 | public enum Button 75 | { 76 | Left = 1 << 0, 77 | Right = 1 << 1, 78 | Back = 1 << 2, 79 | Forward = 1 << 3 80 | } 81 | 82 | public class ButtonEventArgs : HandledEventArgs 83 | { 84 | public Point Position { get; private set; } 85 | public State State { get; private set; } 86 | public Button Button { get; private set; } 87 | public bool Injected { get; private set; } 88 | 89 | public ButtonEventArgs(Point position, State state, Button button, bool injected) 90 | { 91 | Position = position; 92 | State = state; 93 | Button = button; 94 | Injected = injected; 95 | } 96 | } 97 | 98 | private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); 99 | private HookProc lowLevelMouseProc; 100 | private IntPtr lowLevelMouseHandle; 101 | 102 | public event EventHandler ButtonEvent; 103 | 104 | public GlobalMouse() 105 | { 106 | lowLevelMouseProc = LowLevelMouseHookCallback; 107 | lowLevelMouseHandle = SetLowLevelMouseHook(lowLevelMouseProc); 108 | } 109 | 110 | private static IntPtr SetLowLevelMouseHook(HookProc proc) 111 | { 112 | return SetWindowsHookEx(WH_MOUSE_LL, proc, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); 113 | } 114 | 115 | private IntPtr LowLevelMouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam) 116 | { 117 | if (nCode >= 0) 118 | { 119 | var hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); 120 | var highWord = hookStruct.mouseData >> 16; 121 | var injected = (hookStruct.flags & (LLMHF_INJECTED | LLMHF_LOWER_IL_INJECTED)) != 0; 122 | var position = new Point(hookStruct.pt.x, hookStruct.pt.y); 123 | 124 | switch ((MouseMessages)wParam) 125 | { 126 | case MouseMessages.WM_LBUTTONDOWN: 127 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonDown, Button.Left, injected)); 128 | break; 129 | case MouseMessages.WM_LBUTTONUP: 130 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonUp, Button.Left, injected)); 131 | break; 132 | case MouseMessages.WM_RBUTTONDOWN: 133 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonDown, Button.Right, injected)); 134 | break; 135 | case MouseMessages.WM_RBUTTONUP: 136 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonUp, Button.Right, injected)); 137 | break; 138 | case MouseMessages.WM_XBUTTONDOWN: 139 | switch (highWord) 140 | { 141 | case (uint)XButtons.XBUTTON1: 142 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonDown, Button.Back, injected)); 143 | break; 144 | case (uint)XButtons.XBUTTON2: 145 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonDown, Button.Forward, injected)); 146 | break; 147 | } 148 | break; 149 | case MouseMessages.WM_XBUTTONUP: 150 | switch (highWord) 151 | { 152 | case (uint)XButtons.XBUTTON1: 153 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonUp, Button.Back, injected)); 154 | break; 155 | case (uint)XButtons.XBUTTON2: 156 | ButtonEvent?.Invoke(this, new ButtonEventArgs(position, State.ButtonUp, Button.Forward, injected)); 157 | break; 158 | } 159 | break; 160 | } 161 | } 162 | 163 | return CallNextHookEx(lowLevelMouseHandle, nCode, wParam, lParam); 164 | } 165 | 166 | protected virtual void Dispose(bool disposing) 167 | { 168 | if (disposing) 169 | { 170 | if (lowLevelMouseHandle != IntPtr.Zero) 171 | { 172 | if (UnhookWindowsHookEx(lowLevelMouseHandle) == false) 173 | { 174 | var errorCode = Marshal.GetLastWin32Error(); 175 | throw new Win32Exception(errorCode, $"Failed to remove mouse hooks for '{Process.GetCurrentProcess().ProcessName}'. Error {errorCode}: {new Win32Exception(Marshal.GetLastWin32Error()).Message}."); 176 | } 177 | 178 | lowLevelMouseHandle = IntPtr.Zero; 179 | lowLevelMouseProc -= LowLevelMouseHookCallback; 180 | } 181 | } 182 | } 183 | 184 | public void Dispose() 185 | { 186 | Dispose(true); 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /Input/GlobalWindow.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Diagnostics; 4 | using System.Runtime.InteropServices; 5 | using System.Security.Permissions; 6 | 7 | namespace AimBot.Input 8 | { 9 | public class GlobalWindow : IDisposable 10 | { 11 | #region P/Invoke Signatures 12 | private static long SWEH_CHILDID_SELF = 0; 13 | 14 | public enum SWEH_dwFlags : uint 15 | { 16 | WINEVENT_OUTOFCONTEXT = 0x0000, 17 | WINEVENT_SKIPOWNTHREAD = 0x0001, 18 | WINEVENT_SKIPOWNPROCESS = 0x0002, 19 | WINEVENT_INCONTEXT = 0x0004 20 | } 21 | 22 | private enum SWEH_Events : uint 23 | { 24 | EVENT_MIN = 0x00000001, 25 | EVENT_MAX = 0x7FFFFFFF, 26 | EVENT_SYSTEM_SOUND = 0x0001, 27 | EVENT_SYSTEM_ALERT = 0x0002, 28 | EVENT_SYSTEM_FOREGROUND = 0x0003, 29 | EVENT_SYSTEM_MENUSTART = 0x0004, 30 | EVENT_SYSTEM_MENUEND = 0x0005, 31 | EVENT_SYSTEM_MENUPOPUPSTART = 0x0006, 32 | EVENT_SYSTEM_MENUPOPUPEND = 0x0007, 33 | EVENT_SYSTEM_CAPTURESTART = 0x0008, 34 | EVENT_SYSTEM_CAPTUREEND = 0x0009, 35 | EVENT_SYSTEM_MOVESIZESTART = 0x000A, 36 | EVENT_SYSTEM_MOVESIZEEND = 0x000B, 37 | EVENT_SYSTEM_CONTEXTHELPSTART = 0x000C, 38 | EVENT_SYSTEM_CONTEXTHELPEND = 0x000D, 39 | EVENT_SYSTEM_DRAGDROPSTART = 0x000E, 40 | EVENT_SYSTEM_DRAGDROPEND = 0x000F, 41 | EVENT_SYSTEM_DIALOGSTART = 0x0010, 42 | EVENT_SYSTEM_DIALOGEND = 0x0011, 43 | EVENT_SYSTEM_SCROLLINGSTART = 0x0012, 44 | EVENT_SYSTEM_SCROLLINGEND = 0x0013, 45 | EVENT_SYSTEM_SWITCHSTART = 0x0014, 46 | EVENT_SYSTEM_SWITCHEND = 0x0015, 47 | EVENT_SYSTEM_MINIMIZESTART = 0x0016, 48 | EVENT_SYSTEM_MINIMIZEEND = 0x0017, 49 | EVENT_SYSTEM_DESKTOPSWITCH = 0x0020, 50 | EVENT_SYSTEM_END = 0x00FF, 51 | EVENT_OEM_DEFINED_START = 0x0101, 52 | EVENT_OEM_DEFINED_END = 0x01FF, 53 | EVENT_UIA_EVENTID_START = 0x4E00, 54 | EVENT_UIA_EVENTID_END = 0x4EFF, 55 | EVENT_UIA_PROPID_START = 0x7500, 56 | EVENT_UIA_PROPID_END = 0x75FF, 57 | EVENT_CONSOLE_CARET = 0x4001, 58 | EVENT_CONSOLE_UPDATE_REGION = 0x4002, 59 | EVENT_CONSOLE_UPDATE_SIMPLE = 0x4003, 60 | EVENT_CONSOLE_UPDATE_SCROLL = 0x4004, 61 | EVENT_CONSOLE_LAYOUT = 0x4005, 62 | EVENT_CONSOLE_START_APPLICATION = 0x4006, 63 | EVENT_CONSOLE_END_APPLICATION = 0x4007, 64 | EVENT_CONSOLE_END = 0x40FF, 65 | EVENT_OBJECT_CREATE = 0x8000, 66 | EVENT_OBJECT_DESTROY = 0x8001, 67 | EVENT_OBJECT_SHOW = 0x8002, 68 | EVENT_OBJECT_HIDE = 0x8003, 69 | EVENT_OBJECT_REORDER = 0x8004, 70 | EVENT_OBJECT_FOCUS = 0x8005, 71 | EVENT_OBJECT_SELECTION = 0x8006, 72 | EVENT_OBJECT_SELECTIONADD = 0x8007, 73 | EVENT_OBJECT_SELECTIONREMOVE = 0x8008, 74 | EVENT_OBJECT_SELECTIONWITHIN = 0x8009, 75 | EVENT_OBJECT_STATECHANGE = 0x800A, 76 | EVENT_OBJECT_LOCATIONCHANGE = 0x800B, 77 | EVENT_OBJECT_NAMECHANGE = 0x800C, 78 | EVENT_OBJECT_DESCRIPTIONCHANGE = 0x800D, 79 | EVENT_OBJECT_VALUECHANGE = 0x800E, 80 | EVENT_OBJECT_PARENTCHANGE = 0x800F, 81 | EVENT_OBJECT_HELPCHANGE = 0x8010, 82 | EVENT_OBJECT_DEFACTIONCHANGE = 0x8011, 83 | EVENT_OBJECT_ACCELERATORCHANGE = 0x8012, 84 | EVENT_OBJECT_INVOKED = 0x8013, 85 | EVENT_OBJECT_TEXTSELECTIONCHANGED = 0x8014, 86 | EVENT_OBJECT_CONTENTSCROLLED = 0x8015, 87 | EVENT_SYSTEM_ARRANGMENTPREVIEW = 0x8016, 88 | EVENT_OBJECT_END = 0x80FF, 89 | EVENT_AIA_START = 0xA000, 90 | EVENT_AIA_END = 0xAFFF 91 | } 92 | 93 | private enum SWEH_ObjectId : long 94 | { 95 | OBJID_WINDOW = 0x00000000, 96 | OBJID_SYSMENU = 0xFFFFFFFF, 97 | OBJID_TITLEBAR = 0xFFFFFFFE, 98 | OBJID_MENU = 0xFFFFFFFD, 99 | OBJID_CLIENT = 0xFFFFFFFC, 100 | OBJID_VSCROLL = 0xFFFFFFFB, 101 | OBJID_HSCROLL = 0xFFFFFFFA, 102 | OBJID_SIZEGRIP = 0xFFFFFFF9, 103 | OBJID_CARET = 0xFFFFFFF8, 104 | OBJID_CURSOR = 0xFFFFFFF7, 105 | OBJID_ALERT = 0xFFFFFFF6, 106 | OBJID_SOUND = 0xFFFFFFF5, 107 | OBJID_QUERYCLASSNAMEIDX = 0xFFFFFFF4, 108 | OBJID_NATIVEOM = 0xFFFFFFF0 109 | } 110 | 111 | private static SWEH_dwFlags WinEventHookInternalFlags = SWEH_dwFlags.WINEVENT_OUTOFCONTEXT | SWEH_dwFlags.WINEVENT_SKIPOWNPROCESS | SWEH_dwFlags.WINEVENT_SKIPOWNTHREAD; 112 | 113 | [DllImport("user32.dll")] 114 | private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr voidProcessId); 115 | 116 | [DllImport("user32.dll", SetLastError = false)] 117 | private static extern IntPtr SetWinEventHook(SWEH_Events eventMin, SWEH_Events eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, SWEH_dwFlags dwFlags); 118 | 119 | [DllImport("user32.dll", SetLastError = false)] 120 | private static extern bool UnhookWinEvent(IntPtr hWinEventHook); 121 | 122 | private delegate void WinEventDelegate(IntPtr hWinEventHook, SWEH_Events eventType, IntPtr hwnd, SWEH_ObjectId idObject, long idChild, uint dwEventThread, uint dwmsEventTime); 123 | 124 | private static uint GetWindowThread(IntPtr hWnd) 125 | { 126 | new UIPermission(UIPermissionWindow.AllWindows).Demand(); 127 | return GetWindowThreadProcessId(hWnd, IntPtr.Zero); 128 | } 129 | 130 | private static IntPtr WinEventHookOne(SWEH_Events ev, WinEventDelegate wed, uint idProcess, uint idThread) 131 | { 132 | new UIPermission(UIPermissionWindow.AllWindows).Demand(); 133 | return SetWinEventHook(ev, ev, IntPtr.Zero, wed, idProcess, idThread, WinEventHookInternalFlags); 134 | } 135 | #endregion 136 | 137 | public class MoveEventArgs : HandledEventArgs 138 | { 139 | public MoveEventArgs() { } 140 | } 141 | 142 | private Process process; 143 | private IntPtr windowHandle; 144 | private GCHandle hookHandle; 145 | private IntPtr hookId; 146 | private bool disposed; 147 | 148 | public event EventHandler MoveEvent; 149 | 150 | public GlobalWindow(Process process) 151 | { 152 | this.process = process; 153 | if (process != null) 154 | { 155 | windowHandle = process.MainWindowHandle; 156 | if (windowHandle != IntPtr.Zero) 157 | { 158 | var eventDelegate = new WinEventDelegate(WindowEventCallback); 159 | hookHandle = GCHandle.Alloc(eventDelegate); 160 | 161 | var threadId = GetWindowThread(windowHandle); 162 | hookId = WinEventHookOne(SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE, eventDelegate, (uint)process.Id, threadId); 163 | } 164 | } 165 | } 166 | 167 | private void WindowEventCallback(IntPtr hWinEventHook, SWEH_Events eventType, IntPtr hWnd, SWEH_ObjectId idObject, long idChild, uint dwEventThread, uint dwmsEventTime) 168 | { 169 | if (hWnd == windowHandle) 170 | { 171 | if (eventType == SWEH_Events.EVENT_OBJECT_LOCATIONCHANGE && idObject == (SWEH_ObjectId)SWEH_CHILDID_SELF) 172 | { 173 | MoveEvent?.Invoke(this, new MoveEventArgs()); 174 | } 175 | } 176 | } 177 | 178 | protected virtual void Dispose(bool disposing) 179 | { 180 | if (disposed == false) 181 | { 182 | if (disposing) 183 | { 184 | // Dispose managed state (managed objects) 185 | } 186 | 187 | // Free unmanaged resources (unmanaged objects). 188 | if (hookId != IntPtr.Zero) { 189 | hookHandle.Free(); 190 | UnhookWinEvent(hookId); 191 | hookId = IntPtr.Zero; 192 | } 193 | 194 | // Set large fields to null 195 | disposed = true; 196 | } 197 | } 198 | 199 | ~GlobalWindow() 200 | { 201 | Dispose(disposing: false); 202 | } 203 | 204 | public void Dispose() 205 | { 206 | Dispose(disposing: true); 207 | GC.SuppressFinalize(this); 208 | } 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 63 | 66 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 80 | 83 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 97 | 100 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 114 | 117 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 131 | 134 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 148 | 151 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 165 | 168 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | -------------------------------------------------------------------------------- /MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.IO; 4 | using System.Diagnostics; 5 | using System.Threading; 6 | using System.Drawing; 7 | using System.Collections.Generic; 8 | using System.Windows.Controls; 9 | using System.Reflection; 10 | using System.ComponentModel; 11 | 12 | using Microsoft.Win32; 13 | using Newtonsoft.Json; 14 | 15 | using AimBot.Input; 16 | using AimBot.Renderers; 17 | using AimBot.Helpers; 18 | using AimBot.Grabbers; 19 | using AimBot.Detectors; 20 | using AimBot.Trackers; 21 | using AimBot.Selectors; 22 | using AimBot.Injectors; 23 | using AimBot.Aimers; 24 | 25 | using Trigger = AimBot.Triggers.Trigger; 26 | 27 | namespace AimBot 28 | { 29 | /// 30 | /// Interaction logic for MainWindow.xaml 31 | /// 32 | public partial class MainWindow : Window, INotifyPropertyChanged 33 | { 34 | private string processName; 35 | private Process process; 36 | 37 | private GlobalKey globalKey; 38 | private GlobalMouse globalMouse; 39 | private GlobalWindow globalWindow; 40 | 41 | private Esp esp; 42 | private Bot bot; 43 | 44 | private Thread botThread; 45 | private int botThreadTermination; 46 | 47 | private Stopwatch stopwatch; 48 | 49 | private bool running; 50 | 51 | private Rectangle region; 52 | private Rectangle client; 53 | 54 | private JsonSerializerSettings serializerSettings; 55 | 56 | public event PropertyChangedEventHandler PropertyChanged; 57 | 58 | public bool Started 59 | { 60 | get { return running; } 61 | private set 62 | { 63 | if (running != value) 64 | { 65 | running = value; 66 | NotifyPropertyChanged(nameof(Started)); 67 | NotifyPropertyChanged(nameof(Stopped)); 68 | } 69 | } 70 | } 71 | 72 | public bool Stopped 73 | { 74 | get { return Started == false; } 75 | private set { Started = !value; } 76 | } 77 | 78 | public IEnumerable ProcessNames 79 | { 80 | get 81 | { 82 | foreach (var process in Process.GetProcesses()) 83 | { 84 | yield return process.ProcessName; 85 | } 86 | } 87 | } 88 | 89 | public string ProcessName 90 | { 91 | get { return processName; } 92 | set { UpdateProcess(value); } 93 | } 94 | 95 | public int RegionWidth 96 | { 97 | get { return region.Width; } 98 | set 99 | { 100 | region.Width = value; 101 | RecenterRegion(); 102 | } 103 | } 104 | 105 | public int RegionHeight 106 | { 107 | get { return region.Height; } 108 | set 109 | { 110 | region.Height = value; 111 | RecenterRegion(); 112 | } 113 | } 114 | 115 | public bool Esp 116 | { 117 | get { return esp != null; } 118 | set 119 | { 120 | if (value && esp == null) 121 | { 122 | esp = new GameOverlayEsp(); 123 | StartEsp(); 124 | } 125 | else if (value == false && esp != null) 126 | { 127 | StopEsp(); 128 | esp = null; 129 | } 130 | } 131 | } 132 | 133 | public IEnumerable ActivationKeys 134 | { 135 | get { return Enum.GetNames(typeof(Bot.ActivationKeys)); } 136 | } 137 | 138 | public IEnumerable ActivationButtons 139 | { 140 | get { return Enum.GetNames(typeof(Bot.ActivationButtons)); } 141 | } 142 | 143 | public string ActivationKey 144 | { 145 | get { return bot.ActivationKey.ToString(); } 146 | set 147 | { 148 | if (Enum.TryParse(typeof(Bot.ActivationKeys), value, out var key)) 149 | { 150 | bot.ActivationKey = (Bot.ActivationKeys)key; 151 | } 152 | 153 | NotifyPropertyChanged(nameof(ActivationKey)); 154 | } 155 | } 156 | 157 | public string ActivationButton 158 | { 159 | get { return bot.ActivationButton.ToString(); } 160 | set 161 | { 162 | if (Enum.TryParse(typeof(Bot.ActivationButtons), value, out var btn)) 163 | { 164 | bot.ActivationButton = (Bot.ActivationButtons)btn; 165 | } 166 | 167 | NotifyPropertyChanged(nameof(ActivationButton)); 168 | } 169 | } 170 | 171 | public IEnumerable GrabberNames 172 | { 173 | get { return TypeHelper.ConcreteTypeNames(typeof(Grabber)); } 174 | } 175 | 176 | public string GrabberName 177 | { 178 | get { return bot.Grabber?.GetType().Name ?? ""; } 179 | set 180 | { 181 | foreach (var option in TypeHelper.ConcreteTypes(typeof(Grabber))) 182 | { 183 | if (option.Name == value) 184 | { 185 | bot.Grabber = (Grabber)Activator.CreateInstance(option); 186 | UpdateSettings(bot.Grabber, GrabberSettings); 187 | break; 188 | } 189 | } 190 | 191 | NotifyPropertyChanged(nameof(GrabberName)); 192 | } 193 | } 194 | 195 | public IEnumerable DetectorNames 196 | { 197 | get { return TypeHelper.ConcreteTypeNames(typeof(Detector)); } 198 | } 199 | 200 | public string DetectorName 201 | { 202 | get { return bot.Detector?.GetType().Name ?? ""; } 203 | set 204 | { 205 | foreach (var option in TypeHelper.ConcreteTypes(typeof(Detector))) 206 | { 207 | if (option.Name == value) 208 | { 209 | bot.Detector = (Detector)Activator.CreateInstance(option); 210 | UpdateSettings(bot.Detector, DetectorSettings); 211 | break; 212 | } 213 | } 214 | 215 | NotifyPropertyChanged(nameof(DetectorName)); 216 | } 217 | } 218 | 219 | public IEnumerable TrackerNames 220 | { 221 | get { return TypeHelper.ConcreteTypeNames(typeof(Tracker)); } 222 | } 223 | 224 | public string TrackerName 225 | { 226 | get { return bot.Tracker?.GetType().Name ?? ""; } 227 | set 228 | { 229 | foreach (var option in TypeHelper.ConcreteTypes(typeof(Tracker))) 230 | { 231 | if (option.Name == value) 232 | { 233 | bot.Tracker = (Tracker)Activator.CreateInstance(option); 234 | UpdateSettings(bot.Tracker, TrackerSettings); 235 | break; 236 | } 237 | } 238 | 239 | NotifyPropertyChanged(nameof(TrackerName)); 240 | } 241 | } 242 | 243 | public IEnumerable SelectorNames 244 | { 245 | get { return TypeHelper.ConcreteTypeNames(typeof(Selector)); } 246 | } 247 | 248 | public string SelectorName 249 | { 250 | get { return bot.Selector?.GetType().Name ?? ""; } 251 | set 252 | { 253 | foreach (var option in TypeHelper.ConcreteTypes(typeof(Selector))) 254 | { 255 | if (option.Name == value) 256 | { 257 | bot.Selector = (Selector)Activator.CreateInstance(option); 258 | UpdateSettings(bot.Selector, SelectorSettings); 259 | break; 260 | } 261 | } 262 | 263 | NotifyPropertyChanged(nameof(SelectorName)); 264 | } 265 | } 266 | 267 | public IEnumerable AimerNames 268 | { 269 | get { return TypeHelper.ConcreteTypeNames(typeof(Aimer)); } 270 | } 271 | 272 | public string AimerName 273 | { 274 | get { return bot.Aimer?.GetType().Name ?? ""; } 275 | set 276 | { 277 | foreach (var option in TypeHelper.ConcreteTypes(typeof(Aimer))) 278 | { 279 | if (option.Name == value) 280 | { 281 | bot.Aimer = (Aimer)Activator.CreateInstance(option); 282 | UpdateSettings(bot.Aimer, AimerSettings); 283 | break; 284 | } 285 | } 286 | 287 | NotifyPropertyChanged(nameof(AimerName)); 288 | } 289 | } 290 | 291 | public IEnumerable InjectorNames 292 | { 293 | get { return TypeHelper.ConcreteTypeNames(typeof(MouseInjector)); } 294 | } 295 | 296 | public string InjectorName 297 | { 298 | get { return bot.Injector?.GetType().Name ?? ""; } 299 | set 300 | { 301 | foreach (var option in TypeHelper.ConcreteTypes(typeof(MouseInjector))) 302 | { 303 | if (option.Name == value) 304 | { 305 | bot.Injector = (MouseInjector)Activator.CreateInstance(option); 306 | UpdateSettings(bot.Injector, InjectorSettings); 307 | break; 308 | } 309 | } 310 | 311 | NotifyPropertyChanged(nameof(InjectorName)); 312 | } 313 | } 314 | 315 | public IEnumerable TriggerNames 316 | { 317 | get { return TypeHelper.ConcreteTypeNames(typeof(Trigger)); } 318 | } 319 | 320 | public string TriggerName 321 | { 322 | get { return bot.Trigger?.GetType().Name ?? ""; } 323 | set 324 | { 325 | foreach (var option in TypeHelper.ConcreteTypes(typeof(Trigger))) 326 | { 327 | if (option.Name == value) 328 | { 329 | bot.Trigger = (Trigger)Activator.CreateInstance(option); 330 | UpdateSettings(bot.Trigger, TriggerSettings); 331 | break; 332 | } 333 | } 334 | 335 | NotifyPropertyChanged(nameof(TriggerName)); 336 | } 337 | } 338 | 339 | public string ConfigurationDirectory 340 | { 341 | get 342 | { 343 | var directory = Path.Combine(Directory.GetCurrentDirectory(), "Configurations"); 344 | if (Directory.Exists(directory) == false) 345 | { 346 | Directory.CreateDirectory(directory); 347 | } 348 | 349 | return directory; 350 | } 351 | } 352 | 353 | public IEnumerable ConfigurationFiles 354 | { 355 | get 356 | { 357 | var paths = Directory.GetFiles(ConfigurationDirectory, "*.json"); 358 | foreach (var path in paths) 359 | { 360 | yield return path; 361 | } 362 | } 363 | } 364 | 365 | public MainWindow() 366 | { 367 | InitializeComponent(); 368 | 369 | DataContext = this; 370 | 371 | serializerSettings = new JsonSerializerSettings() 372 | { 373 | TypeNameHandling = TypeNameHandling.Objects 374 | }; 375 | 376 | stopwatch = new Stopwatch(); 377 | esp = null; 378 | bot = new Bot(); 379 | } 380 | 381 | private void StopEsp() 382 | { 383 | esp?.Stop(); 384 | } 385 | 386 | private void StartEsp() 387 | { 388 | if (process != null) 389 | { 390 | esp?.Start(process.MainWindowHandle); 391 | } 392 | } 393 | 394 | private bool UpdateProcess(string processName) 395 | { 396 | StopBot(); 397 | StopEsp(); 398 | Unhook(); 399 | 400 | var processes = Process.GetProcessesByName(processName); 401 | if (processes != null && processes.Length > 0) 402 | { 403 | process = processes[0]; 404 | 405 | UpdateWindow(); 406 | Hook(); 407 | StartEsp(); 408 | 409 | this.processName = processName; 410 | return true; 411 | } 412 | 413 | process = null; 414 | return false; 415 | } 416 | 417 | private void UpdateWindow() 418 | { 419 | if (process != null) 420 | { 421 | client = ScreenHelper.ClientRectangle(process.MainWindowHandle); 422 | esp?.Refit(); 423 | RecenterRegion(); 424 | } 425 | } 426 | 427 | private void RecenterRegion() 428 | { 429 | var cx = client.X + client.Width / 2; 430 | var cy = client.Y + client.Height / 2; 431 | var rx = cx - region.Width / 2; 432 | var ry = cy - region.Height / 2; 433 | region = new Rectangle(rx, ry, region.Width, region.Height); 434 | } 435 | 436 | private void StopBot() 437 | { 438 | if (botThread != null) 439 | { 440 | Interlocked.Increment(ref botThreadTermination); 441 | botThread.Join(); 442 | botThread = null; 443 | } 444 | 445 | if (bot != null) 446 | { 447 | bot.Process = null; 448 | } 449 | 450 | Stopped = true; 451 | } 452 | 453 | private void StartBot() 454 | { 455 | if (process != null && bot != null) 456 | { 457 | bot.Process = process; 458 | 459 | botThreadTermination = 0; 460 | Started = true; 461 | botThread = new Thread(UpdateBot); 462 | botThread.Start(); 463 | } 464 | } 465 | 466 | private void UpdateBot() 467 | { 468 | while (botThreadTermination <= 0) 469 | { 470 | var dt = (double)stopwatch.Elapsed.TotalMilliseconds / 1000.0; 471 | stopwatch.Restart(); 472 | 473 | esp?.Clear(); 474 | 475 | if (process != null && region.Width > 0 && region.Height > 0 && bot != null) 476 | { 477 | bot.Tick(dt, region, esp); 478 | } 479 | 480 | esp?.SwapBuffers(); 481 | } 482 | } 483 | 484 | private void Unhook() 485 | { 486 | if (globalKey != null) 487 | { 488 | globalKey.KeyEvent -= GlobalKey_KeyEvent; 489 | globalKey.Dispose(); 490 | globalKey = null; 491 | } 492 | 493 | if (globalMouse != null) 494 | { 495 | globalMouse.ButtonEvent -= GlobalMouse_ButtonEvent; 496 | globalMouse.Dispose(); 497 | globalMouse = null; 498 | } 499 | 500 | if (globalWindow != null) 501 | { 502 | globalWindow.MoveEvent -= GlobalWindow_MoveEvent; 503 | globalWindow.Dispose(); 504 | globalWindow = null; 505 | } 506 | } 507 | 508 | private void Hook() 509 | { 510 | Unhook(); 511 | 512 | if (process != null) 513 | { 514 | globalKey = new GlobalKey(); 515 | globalKey.KeyEvent += GlobalKey_KeyEvent; 516 | 517 | globalMouse = new GlobalMouse(); 518 | globalMouse.ButtonEvent += GlobalMouse_ButtonEvent; 519 | 520 | globalWindow = new GlobalWindow(process); 521 | globalWindow.MoveEvent += GlobalWindow_MoveEvent; 522 | } 523 | } 524 | 525 | private void UpdateSettings(object instance, StackPanel panel) 526 | { 527 | panel.Children.Clear(); 528 | foreach (var prop in TypeHelper.PublicProperties(instance)) 529 | { 530 | if (prop.PropertyType == typeof(string)) 531 | { 532 | var tl = new TextBlock(); 533 | tl.Text = prop.Name; 534 | panel.Children.Add(tl); 535 | 536 | var tb = new TextBox(); 537 | tb.Name = prop.Name; 538 | tb.Text = (string)prop.GetValue(instance) ?? ""; 539 | tb.TextChanged += OnPropertyTextBoxChanged; 540 | tb.DataContext = new PropertyContext(instance, prop); 541 | panel.Children.Add(tb); 542 | } 543 | else if (prop.PropertyType == typeof(FileFilter)) 544 | { 545 | if (prop.GetValue(instance) is FileFilter ff) 546 | { 547 | var tl = new TextBlock(); 548 | tl.Text = prop.Name; 549 | panel.Children.Add(tl); 550 | 551 | var cb = new ComboBox(); 552 | cb.Name = prop.Name; 553 | cb.ItemsSource = ff.FileNames; 554 | cb.SelectedItem = ff.FileName; 555 | cb.SelectionChanged += OnPropertyComboBoxChanged; 556 | cb.DataContext = new PropertyContext(instance, prop); 557 | panel.Children.Add(cb); 558 | } 559 | } 560 | else if (prop.PropertyType == typeof(int) || prop.PropertyType == typeof(float) || prop.PropertyType == typeof(double)) 561 | { 562 | var tl = new TextBlock(); 563 | tl.Text = prop.Name; 564 | panel.Children.Add(tl); 565 | 566 | var tb = new TextBox(); 567 | tb.Name = prop.Name; 568 | tb.Text = prop.GetValue(instance).ToString(); 569 | tb.TextChanged += OnPropertyTextBoxChanged; 570 | tb.DataContext = new PropertyContext(instance, prop); 571 | panel.Children.Add(tb); 572 | } 573 | else if (prop.PropertyType == typeof(bool)) 574 | { 575 | var tl = new TextBlock(); 576 | tl.Text = prop.Name; 577 | panel.Children.Add(tl); 578 | 579 | var cb = new CheckBox(); 580 | cb.Name = prop.Name; 581 | cb.IsChecked = (bool)prop.GetValue(instance); 582 | cb.Checked += OnPropertyCheckBoxChanged; 583 | cb.Unchecked += OnPropertyCheckBoxChanged; 584 | cb.DataContext = new PropertyContext(instance, prop); 585 | panel.Children.Add(cb); 586 | } 587 | else if (prop.PropertyType.IsEnum) 588 | { 589 | var tl = new TextBlock(); 590 | tl.Text = prop.Name; 591 | panel.Children.Add(tl); 592 | 593 | var cb = new ComboBox(); 594 | cb.Name = prop.Name; 595 | cb.ItemsSource = Enum.GetNames(prop.PropertyType); 596 | cb.SelectedItem = prop.GetValue(instance).ToString(); 597 | cb.SelectionChanged += OnPropertyComboBoxChanged; 598 | cb.DataContext = new PropertyContext(instance, prop); 599 | panel.Children.Add(cb); 600 | } 601 | } 602 | } 603 | 604 | private void OnPropertyComboBoxChanged(object sender, SelectionChangedEventArgs e) 605 | { 606 | if (sender is ComboBox cb) 607 | { 608 | if (cb.DataContext is PropertyContext context) 609 | { 610 | if (context.Property.PropertyType == typeof(FileFilter)) 611 | { 612 | var ff = context.GetValue(); 613 | if (ff != null) 614 | { 615 | ff.FileName = (string)cb.SelectedItem; 616 | } 617 | } 618 | else if (context.Property.PropertyType.IsEnum) 619 | { 620 | context.SetValue(Enum.Parse(context.Property.PropertyType, cb.SelectedItem.ToString())); 621 | } 622 | } 623 | } 624 | } 625 | 626 | private void OnPropertyTextBoxChanged(object sender, TextChangedEventArgs e) 627 | { 628 | if (sender is TextBox tb) 629 | { 630 | if (tb.DataContext is PropertyContext context) 631 | { 632 | if (context.Property.PropertyType == typeof(string)) 633 | { 634 | context.SetValue(tb.Text); 635 | } 636 | else if (context.Property.PropertyType == typeof(int)) 637 | { 638 | if (int.TryParse(tb.Text, out int value)) 639 | { 640 | context.SetValue(value); 641 | } 642 | } 643 | else if (context.Property.PropertyType == typeof(float)) 644 | { 645 | if (float.TryParse(tb.Text, out float value)) 646 | { 647 | context.SetValue(value); 648 | } 649 | } 650 | else if (context.Property.PropertyType == typeof(double)) 651 | { 652 | if (double.TryParse(tb.Text, out double value)) 653 | { 654 | context.SetValue(value); 655 | } 656 | } 657 | } 658 | } 659 | } 660 | 661 | private void OnPropertyCheckBoxChanged(object sender, RoutedEventArgs e) 662 | { 663 | if (sender is CheckBox cb) 664 | { 665 | if (cb.DataContext is PropertyContext context) 666 | { 667 | if (context.Property.PropertyType == typeof(bool)) 668 | { 669 | context.SetValue(cb.IsChecked); 670 | } 671 | } 672 | } 673 | } 674 | 675 | private void OnRefresh(object sender, RoutedEventArgs e) 676 | { 677 | NotifyPropertyChanged(nameof(ProcessNames)); 678 | } 679 | 680 | private void OnSave(object sender, RoutedEventArgs e) 681 | { 682 | var dialog = new SaveFileDialog() 683 | { 684 | Filter = "Configuration Files(*.json)|*.json", 685 | InitialDirectory = ConfigurationDirectory 686 | }; 687 | 688 | if (dialog.ShowDialog() == true) 689 | { 690 | var configuration = new Configuration() { Width = RegionWidth, Height = RegionHeight, Esp = Esp, Bot = bot }; 691 | File.WriteAllText(dialog.FileName, JsonConvert.SerializeObject(configuration, Formatting.Indented, serializerSettings)); 692 | NotifyPropertyChanged(nameof(ConfigurationFiles)); 693 | } 694 | } 695 | 696 | private void OnChangedConfiguration(object sender, SelectionChangedEventArgs e) 697 | { 698 | if (sender is ComboBox cb) 699 | { 700 | var configurationPath = (string)cb.SelectedItem; 701 | if (File.Exists(configurationPath)) 702 | { 703 | StopBot(); 704 | bot?.Dispose(); 705 | 706 | var configuration = (Configuration)JsonConvert.DeserializeObject(File.ReadAllText(configurationPath), typeof(Configuration), serializerSettings); 707 | RegionWidth = configuration.Width; 708 | RegionHeight = configuration.Height; 709 | Esp = configuration.Esp; 710 | bot = configuration.Bot; 711 | 712 | UpdateWindow(); 713 | 714 | NotifyPropertyChanged(nameof(RegionWidth)); 715 | NotifyPropertyChanged(nameof(RegionHeight)); 716 | NotifyPropertyChanged(nameof(ActivationKey)); 717 | NotifyPropertyChanged(nameof(ActivationButton)); 718 | NotifyPropertyChanged(nameof(GrabberName)); 719 | NotifyPropertyChanged(nameof(DetectorName)); 720 | NotifyPropertyChanged(nameof(TrackerName)); 721 | NotifyPropertyChanged(nameof(SelectorName)); 722 | NotifyPropertyChanged(nameof(AimerName)); 723 | NotifyPropertyChanged(nameof(InjectorName)); 724 | NotifyPropertyChanged(nameof(TriggerName)); 725 | 726 | UpdateSettings(bot.Grabber, GrabberSettings); 727 | UpdateSettings(bot.Detector, DetectorSettings); 728 | UpdateSettings(bot.Tracker, TrackerSettings); 729 | UpdateSettings(bot.Selector, SelectorSettings); 730 | UpdateSettings(bot.Aimer, AimerSettings); 731 | UpdateSettings(bot.Injector, InjectorSettings); 732 | UpdateSettings(bot.Trigger, TriggerSettings); 733 | } 734 | } 735 | } 736 | 737 | private void OnStart(object sender, RoutedEventArgs e) 738 | { 739 | StartBot(); 740 | } 741 | 742 | private void OnStop(object sender, RoutedEventArgs e) 743 | { 744 | StopBot(); 745 | } 746 | 747 | private void NotifyPropertyChanged(string name) 748 | { 749 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 750 | } 751 | 752 | private void GlobalKey_KeyEvent(object sender, GlobalKey.KeyEventArgs e) 753 | { 754 | bot?.OnKey(e); 755 | } 756 | 757 | private void GlobalMouse_ButtonEvent(object sender, GlobalMouse.ButtonEventArgs e) 758 | { 759 | bot?.OnButton(e); 760 | } 761 | 762 | private void GlobalWindow_MoveEvent(object sender, GlobalWindow.MoveEventArgs e) 763 | { 764 | UpdateWindow(); 765 | } 766 | 767 | private void Window_Closing(object sender, CancelEventArgs e) 768 | { 769 | StopBot(); 770 | } 771 | 772 | private void Window_Loaded(object sender, RoutedEventArgs e) 773 | { 774 | Refresh.Click += OnRefresh; 775 | Save.Click += OnSave; 776 | Start.Click += OnStart; 777 | Stop.Click += OnStop; 778 | Configuration.SelectionChanged += OnChangedConfiguration; 779 | } 780 | } 781 | 782 | public struct PropertyContext 783 | { 784 | public object Instance; 785 | public PropertyInfo Property; 786 | 787 | public PropertyContext(object instance, PropertyInfo property) 788 | { 789 | Instance = instance; 790 | Property = property; 791 | } 792 | 793 | public void SetValue(T value) 794 | { 795 | Property.SetValue(Instance, value); 796 | } 797 | 798 | public T GetValue() where T : class 799 | { 800 | return Property.GetValue(Instance) as T; 801 | } 802 | } 803 | 804 | public class Configuration 805 | { 806 | public int Width { get; set; } 807 | public int Height { get; set; } 808 | public bool Esp { get; set; } 809 | public Bot Bot { get; set; } 810 | } 811 | } 812 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NeuralBot - Neural Network Aimbot 2 | 3 | This is a general purpose aimbot, which uses a neural network for enemy/target detection. The aimbot doesn't read/write memory from/to the target process. It is essentially a "pixel bot", designed primarily for use with first-person shooter games. Please check that the user agreement for your game allows the use of such a programs! 4 | 5 | ![AimBot](gui.PNG?raw=true "AimBot") 6 | 7 | This aimbot achieved the top score in [Aim Lab](https://youtu.be/vtTsFcAslbE), with the three layer yolov4-tiny convolutional neural network trained on less than 300 images. 8 | 9 | ## The Idea 10 | 11 | The idea was to create an aimbot that could be used across a wide variety of games. All you need is a trained neural network in the darknet format. Drop in the files, configure a few settings and away you go! Since the aimbot is not specific to a single game, it should be possible to easily adapt any of the components or create new components. 12 | 13 | ## Features 14 | 15 | Provided below is a list of the main features: 16 | 17 | * Efficient screen capturing 18 | * GPU-accelerated neural network inference for enemy/target detection (NVIDIA GPUs only) 19 | * Object tracking via Hungarian Algoritm 20 | * Multiple aiming methods 21 | * Trigger bot 22 | * ESP overlay 23 | * Save/load configurations 24 | 25 | ## Requirements 26 | 27 | Unless you are downloading a [pre-built release](https://github.com/kermado/NeuralBot/releases/download/v1.0/NeuralBot.zip), you must install the following requirements in order to use the included OpenCV detector: 28 | 29 | * [OpenCV 4.4.0](https://opencv.org/releases/) 30 | * [NVIDIA CUDA Toolkit 10.0](https://developer.nvidia.com/cuda-toolkit-archive) 31 | * [NVIDIA cuDNN 7.0](https://developer.nvidia.com/rdp/cudnn-archive) 32 | 33 | Please see the [cuDNN installation instructions](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html#installwindows). Note that the pre-built releases include all the necessary DLL dependencies. 34 | 35 | ## Components 36 | 37 | The aimbot is designed to be extended/customised. You can implement your own components and they can be selected and configured through the user interface. This section details the major components. The aimbot includes some basic implementations of these components by default. 38 | 39 | ### Screen Grabber 40 | 41 | The screen grabber is responsible for capturing a specific region of the screen. To screen grabbers are included: 42 | 43 | #### GDI Grabber 44 | 45 | The GDI screen grabber uses the Win32 GDI API. This seems to be pretty efficient in practice, capturing the main window for the target process. 46 | 47 | #### DirectX Grabber 48 | 49 | The DirectX screen grabber uses the Windows Desktop Duplication API. This is supposedly the most efficient method, though the GDI method appears to be more efficient in practice. One important difference is that this method captures from the screen rather than the process main window. You may therefore need to disable ESP rendering in order to avoid confusing the neural network. 50 | 51 | A pre-built binary for the DirectX grabber is included, though the complete [source code](https://github.com/kermado/DXGrabber) is available. 52 | 53 | ### Object Detection 54 | 55 | The object detector is responsible for identifying potential targets from an image. The included detector uses the OpenCV library to perform object detection using a neural network. You must provide a configuration (.cfg) file and associated model (.weights) file in the Darknet format. Note that the aimbot requires the object detection to run at a high framerate (> 100fps) for good results. The YOLOv4 architecture is recommended with a input resolution of 512x512. It is possible to use a larger screen capture area, though the accuracy of the trained neural network may be adversely affected. The included pre-built OpenCV detector supports NVIDIA Pascal and Turing cards only, though the complete [source code](https://github.com/kermado/Detector) is available. 56 | 57 | ### Object Tracker 58 | 59 | The object tracker is responsible for assigning a unique ID to each object. The purpose is to allow the aimbot to continue tracking the same target without switching to other nearby targets. The included tracker uses the Hungarian Algorithm with a GIOU metric. It allows objects to lose detection for a configurable period of time without switching to another target. 60 | 61 | ### Target Selector 62 | 63 | The target selector is responsible for selecting which object should be targeted. The included selector uses a simple distance metric for this purpose. 64 | 65 | ### Target Aimer 66 | 67 | The targget aimer is responsible for moving the crosshair towards the target. Three different aimers are included: 68 | 69 | #### Flick Aimer 70 | 71 | The flick aimer smoothly acquires the position of the target and smoothly moves the crosshair towards that position. The position is not updated over time so as to track any movements that the target makes. If calibrated correctly, the flick aimer should always hit a stationary target. It also shouldn't suffer from dropped detections, since the position is acquired once. The obvious disadvantage is that it is likely to miss a quickly moving target unless the speed is set to a very high value. 72 | 73 | #### Feedback Aimer 74 | 75 | The feedback aimer uses feedback control logic to continuously move the crosshair towards the target. You can configure this aimer to use Proportional (P), Proportional Integral (PI) or Proportional Integral Derivative (PID) control. Whilst this method allows tracking moving objects quite well, it usually tracks slightly behind fast moving objects. It may also be difficult to tune the control parameters. 76 | 77 | #### Hybrid Aimer 78 | 79 | The hybrid aimer combines features of the other two aimers. It uses simple proportional feedback control to get close to the target. Once the target is sufficiently close, it performs a final flick in order to increase the probability of hitting the target. This method is most suitable for low rate of fire weapons, such as sniper rifles. 80 | 81 | ### Trigger Bot 82 | 83 | The trigger bot can automate the process of clicking a mouse button. The included trigger bot can be configured to click the mouse button when the target is sufficiently close. It can be used stand-alone, without any aim assistance. 84 | 85 | ### Mouse Injector 86 | 87 | The mouse injector is responsible for injecting mouse events requested by either the aimer or the trigger bot. 88 | 89 | ## Limitations 90 | 91 | ### Image Scaling 92 | 93 | If the screen capture region is not the same size as the neural network input then the image must be scaled. The current scaling method does not preserve aspect ratio. It is recommended that you set the capture region dimensions to be equal to the neural network input dimensions. This generally yields the best results. If you must use different capture region dimensions then it is highly recommended to maintain the aspect ratio to be equal to the neural network input aspect ratio. 94 | 95 | ### Fullscreen 96 | 97 | The screen grabbers are unable to capture from most games that run in fullscreen mode. You will need to run the game in windowed or borderless windowed mode. 98 | 99 | ## Frequently Asked Questions 100 | 101 | **Will this work with game xyz?** 102 | This aimbot will probably work with most first-person shooter games. You will need a trained neural network for the game and you will also most likely need to configure the aimer for your mouse sensitivity in order to get the best results. 103 | 104 | **Where can I find trained neural network configuration and model files?** 105 | The pre-built release includes a model (aimlab.weights) and configuration file (aimlab.cfg) for AimLab. You can always train your own neural network. The [Darknet](https://github.com/AlexeyAB/darknet) project describes how to do this. 106 | 107 | **Will I get banned for using this?** 108 | If the user agreement doesn't allow the use of such programs then probably. Many anti-cheat programs detect injected mouse input events. There is also a good chance that this will become "signature detected" by many anti-cheat programs in the future. 109 | 110 | **Can I play in fullscreen mode?** 111 | It depends on the game, but probably no. You will usually need to play in either windowed or borderless windowed mode. 112 | 113 | **How can I calibrate the aimers?** 114 | The sensitivity settings can be calibrated in-game by using the flick aimer. Adjust the parameters until the flick lands perfectly on the target position. The PID parameters can be tuned using well-known methods, such as the Ziegler-Nichols method. 115 | 116 | **Does this work with AMD GPUs?** 117 | No. The included OpenCV binary has been built for NVIDIA Pascal and Turing GPUs only. An NVIDIA GTX 1080 or better is recommended. 118 | 119 | **How do I run the aimbot?** 120 | You will need to use Visual Studio 2019 or later to build the solution. Alternatively, download the [pre-built release](https://github.com/kermado/NeuralBot/releases/download/v1.0/NeuralBot.zip). 121 | -------------------------------------------------------------------------------- /Renderers/Esp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace AimBot.Renderers 5 | { 6 | public readonly struct TextShape 7 | { 8 | public readonly Point Position; 9 | public readonly string Text; 10 | public readonly Color Color; 11 | public readonly int Size; 12 | 13 | public TextShape(Point position, string text, Color color, int size) 14 | { 15 | Position = position; 16 | Text = text; 17 | Color = color; 18 | Size = size; 19 | } 20 | } 21 | 22 | public readonly struct RectangleShape 23 | { 24 | /// 25 | /// The screen-space rectangle coordinates. 26 | /// 27 | public readonly Rectangle Rectangle; 28 | 29 | /// 30 | /// The fill color. 31 | /// 32 | public readonly Color FillColor; 33 | 34 | /// 35 | /// The stroke color. 36 | /// 37 | public readonly Color StrokeColor; 38 | 39 | /// 40 | /// The stroke thickness (in pixels). 41 | /// 42 | public readonly int StrokeThickness; 43 | 44 | /// 45 | /// Constructor. 46 | /// 47 | /// The screen-space rectangle coordinates. 48 | /// The fill color. 49 | /// The stroke color. 50 | /// The stroke thickness (in pixels). 51 | public RectangleShape(Rectangle rectangle, Color fillColor, Color strokeColor, int strokeThickness) 52 | { 53 | Rectangle = rectangle; 54 | FillColor = fillColor; 55 | StrokeColor = strokeColor; 56 | StrokeThickness = strokeThickness; 57 | } 58 | } 59 | 60 | public readonly struct CircleShape 61 | { 62 | /// 63 | /// The screen-space center position. 64 | /// 65 | public readonly Point Center; 66 | 67 | /// 68 | /// The radius. 69 | /// 70 | public readonly double Radius; 71 | 72 | /// 73 | /// The fill color. 74 | /// 75 | public readonly Color FillColor; 76 | 77 | /// 78 | /// The stroke color. 79 | /// 80 | public readonly Color StrokeColor; 81 | 82 | /// 83 | /// The stroke thickness (in pixels). 84 | /// 85 | public readonly int StrokeThickness; 86 | 87 | /// 88 | /// Constructor. 89 | /// 90 | /// The screen-space center position. 91 | /// The radius. 92 | /// The fill color. 93 | /// The stroke color. 94 | /// The stroke thickness. 95 | public CircleShape(Point center, double radius, Color fillColor, Color strokeColor, int strokeThickness) 96 | { 97 | Center = center; 98 | Radius = radius; 99 | FillColor = fillColor; 100 | StrokeColor = strokeColor; 101 | StrokeThickness = strokeThickness; 102 | } 103 | } 104 | 105 | public interface Esp 106 | { 107 | void Start(IntPtr windowHandle); 108 | void Stop(); 109 | void Refit(); 110 | void Clear(); 111 | void Add(RectangleShape rectangle); 112 | void Add(CircleShape circle); 113 | void Add(TextShape text); 114 | void SwapBuffers(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Renderers/GameOverlayEsp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using GameOverlay.Drawing; 5 | using GameOverlay.Windows; 6 | 7 | namespace AimBot.Renderers 8 | { 9 | public class GameOverlayEsp : Esp 10 | { 11 | private class Buffer 12 | { 13 | public readonly List Rectangles; 14 | public readonly List Circles; 15 | public readonly List Text; 16 | 17 | public Buffer() 18 | { 19 | Rectangles = new List(); 20 | Circles = new List(); 21 | Text = new List(); 22 | } 23 | 24 | public void Clear() 25 | { 26 | Rectangles.Clear(); 27 | Circles.Clear(); 28 | Text.Clear(); 29 | } 30 | } 31 | 32 | private IntPtr handle; 33 | private GraphicsWindow window; 34 | private Font defaultFont; 35 | private readonly Dictionary brushes; 36 | private Buffer read; 37 | private Buffer write; 38 | private readonly object bufferLock; 39 | 40 | public GameOverlayEsp() 41 | { 42 | window = null; 43 | brushes = new Dictionary(); 44 | read = new Buffer(); 45 | write = new Buffer(); 46 | bufferLock = new object(); 47 | } 48 | 49 | public void Start(IntPtr windowHandle) 50 | { 51 | Stop(); 52 | 53 | handle = windowHandle; 54 | var graphics = new Graphics(windowHandle); 55 | window = new GraphicsWindow(graphics) { FPS = 120, IsTopmost = true, IsVisible = true }; 56 | 57 | window.DrawGraphics += OnDrawGraphics; 58 | window.DestroyGraphics += OnDestroyGraphics; 59 | window.SetupGraphics += OnSetupGraphics; 60 | 61 | window.VisibilityChanged += OnVisibilityChanged; 62 | 63 | window.Create(); 64 | Refit(); 65 | } 66 | 67 | private void OnVisibilityChanged(object sender, OverlayVisibilityEventArgs e) 68 | { 69 | throw new NotImplementedException(); // TODO: 70 | } 71 | 72 | public void Stop() 73 | { 74 | if (window != null) 75 | { 76 | window.DrawGraphics -= OnDrawGraphics; 77 | window.DestroyGraphics -= OnDestroyGraphics; 78 | window.SetupGraphics -= OnSetupGraphics; 79 | window.Dispose(); 80 | window = null; 81 | } 82 | 83 | brushes.Clear(); 84 | 85 | lock (bufferLock) 86 | { 87 | read.Clear(); 88 | write.Clear(); 89 | } 90 | } 91 | 92 | public void Refit() 93 | { 94 | if (window != null) 95 | { 96 | window.PlaceAbove(handle); 97 | window.FitTo(handle, true); 98 | } 99 | } 100 | 101 | private void OnSetupGraphics(object sender, SetupGraphicsEventArgs e) 102 | { 103 | if (e.RecreateResources) 104 | { 105 | defaultFont?.Dispose(); 106 | defaultFont = null; 107 | 108 | foreach (var kv in brushes) 109 | { 110 | kv.Value.Dispose(); 111 | } 112 | 113 | brushes.Clear(); 114 | } 115 | 116 | var gfx = e.Graphics; 117 | defaultFont = gfx.CreateFont("Microsoft Sans Serif", 18, true, false, false); 118 | } 119 | 120 | private void OnDestroyGraphics(object sender, DestroyGraphicsEventArgs e) 121 | { 122 | defaultFont?.Dispose(); 123 | defaultFont = null; 124 | 125 | foreach (var kv in brushes) 126 | { 127 | kv.Value.Dispose(); 128 | } 129 | 130 | brushes.Clear(); 131 | 132 | lock (bufferLock) 133 | { 134 | read.Clear(); 135 | write.Clear(); 136 | } 137 | } 138 | 139 | private void OnDrawGraphics(object sender, DrawGraphicsEventArgs e) 140 | { 141 | window.PlaceAbove(handle); // FIXME: Sometimes the overlay goes behind the target window. 142 | 143 | var gfx = e.Graphics; 144 | 145 | gfx.ClearScene(); 146 | 147 | lock (bufferLock) 148 | { 149 | var clientRect = Helpers.ScreenHelper.ClientRectangle(handle); 150 | foreach (var rectangle in read.Rectangles) 151 | { 152 | var geom = new Rectangle(rectangle.Rectangle.Left - clientRect.Left, 153 | rectangle.Rectangle.Top - clientRect.Top, 154 | rectangle.Rectangle.Right - clientRect.Left, 155 | rectangle.Rectangle.Bottom - clientRect.Top); 156 | 157 | if (rectangle.FillColor.A > 0) 158 | { 159 | gfx.DrawRectangle(Brush(rectangle.FillColor), geom, 0); 160 | } 161 | 162 | if (rectangle.StrokeThickness > 0 && rectangle.StrokeColor.A > 0) 163 | { 164 | gfx.DrawRectangleEdges(Brush(rectangle.StrokeColor), geom, rectangle.StrokeThickness); 165 | } 166 | } 167 | 168 | foreach (var circle in read.Circles) 169 | { 170 | var geom = new Circle(new Point(circle.Center.X - clientRect.Left, 171 | circle.Center.Y - clientRect.Top), (float)circle.Radius); 172 | 173 | gfx.DrawCircle(Brush(circle.StrokeColor), geom, circle.StrokeThickness); 174 | } 175 | 176 | foreach (var text in read.Text) 177 | { 178 | gfx.DrawText(defaultFont, text.Size, Brush(text.Color), text.Position.X - clientRect.Left, text.Position.Y - clientRect.Top, text.Text); 179 | } 180 | } 181 | } 182 | 183 | private SolidBrush Brush(System.Drawing.Color color) 184 | { 185 | return Brush(new Color(color.R, color.G, color.B, color.A)); 186 | } 187 | 188 | private SolidBrush Brush(Color color) 189 | { 190 | if (brushes.TryGetValue(color, out var brush) == false) 191 | { 192 | brush = window.Graphics.CreateSolidBrush(color); 193 | brushes.Add(color, brush); 194 | } 195 | 196 | return brush; 197 | } 198 | 199 | public void Add(RectangleShape rectangle) 200 | { 201 | write.Rectangles.Add(rectangle); 202 | } 203 | 204 | public void Add(CircleShape circle) 205 | { 206 | write.Circles.Add(circle); 207 | } 208 | 209 | public void Add(TextShape text) 210 | { 211 | write.Text.Add(text); 212 | } 213 | 214 | public void Clear() 215 | { 216 | lock (bufferLock) 217 | { 218 | write.Rectangles.Clear(); 219 | write.Text.Clear(); 220 | } 221 | } 222 | 223 | public void SwapBuffers() 224 | { 225 | lock (bufferLock) 226 | { 227 | var temp = write; 228 | write = read; 229 | read = temp; 230 | 231 | write.Clear(); 232 | } 233 | } 234 | } 235 | } 236 | -------------------------------------------------------------------------------- /Selectors/NearestSelector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Helpers; 5 | using AimBot.Detectors; 6 | using AimBot.Trackers; 7 | using AimBot.Renderers; 8 | 9 | namespace AimBot.Selectors 10 | { 11 | /// 12 | /// Selects the point nearest to the current mouse position. 13 | /// 14 | public class NearestSelector : Selector 15 | { 16 | /// 17 | /// The ID for the object being targeted. 18 | /// 19 | /// 20 | /// Zero if no object currently being targeted. 21 | /// 22 | private uint targetId; 23 | 24 | /// 25 | /// The time spent tracking the current target. 26 | /// 27 | private double time; 28 | 29 | /// 30 | /// Whether the target was lost. 31 | /// 32 | private bool lost; 33 | 34 | /// 35 | /// Whether we have been disposed. 36 | /// 37 | private bool disposed; 38 | 39 | /// 40 | /// Which part (head/body) should be targeted. 41 | /// 42 | public Selecting Selecting { get; set; } 43 | 44 | /// 45 | /// The maximum length of time that can be spent selecting the same active target. 46 | /// 47 | public double MaximumActiveSelectionTime { get; set; } = 10.0; 48 | 49 | /// 50 | /// The minimum length of time before another target can be selected whilst aiming. 51 | /// 52 | /// 53 | /// Aiming will be cancelled where the aim key/button is pressed continuously for this 54 | /// length of time. 55 | /// 56 | public double MinimumReselectionTime { get; set; } = 20.0; 57 | 58 | /// 59 | /// The minimum detection confidence for target selection. 60 | /// 61 | public double MinimumSelectionConfidence { get; set; } = 0.1; 62 | 63 | public void Clear() 64 | { 65 | targetId = 0; 66 | time = MinimumReselectionTime; 67 | lost = false; 68 | } 69 | 70 | /// 71 | /// Selects and returns a target point. 72 | /// 73 | /// The tracker, which tracks detections. 74 | /// The current mouse position. 75 | /// The esp, which can be rendered to. 76 | /// Whether to select a target. 77 | /// The timestep. 78 | /// The selected point. 79 | public Point Select(Tracker tracker, Point position, Esp esp, bool aim, double dt) 80 | { 81 | // If we don't want to select a target (e.g. the aim key is not depressed), then cancel 82 | // any existing tracking. 83 | if (aim == false) 84 | { 85 | Clear(); 86 | return Point.Empty; 87 | } 88 | 89 | time += dt; 90 | 91 | // Are we currently tracking an object? 92 | if (targetId > 0) 93 | { 94 | // Look in the list of active objects. 95 | foreach (var obj in tracker.Active) 96 | { 97 | if (obj.Id == targetId) 98 | { 99 | if (time <= MaximumActiveSelectionTime) 100 | { 101 | var point = Select(obj, position); 102 | Render(point, esp); 103 | lost = false; 104 | return point; 105 | } 106 | else 107 | { 108 | // Select a new target. 109 | time = 0.0; 110 | targetId = 0; 111 | lost = false; 112 | break; 113 | } 114 | } 115 | } 116 | 117 | // Couldn't find the object. 118 | // Reset the time so that we don't immediately reselect a new target. 119 | if (lost == false) 120 | { 121 | time = 0.0; 122 | lost = true; 123 | } 124 | } 125 | 126 | // Can we select a new target. 127 | if (time >= MinimumReselectionTime) 128 | { 129 | // Select a new target. 130 | // We select the closest active object. 131 | targetId = 0; 132 | lost = false; 133 | var distanceSq = double.MaxValue; 134 | var target = Point.Empty; 135 | foreach (var obj in tracker.Active) 136 | { 137 | if (obj.Detection.Confidence >= MinimumSelectionConfidence) 138 | { 139 | if (Select(obj, position, ref distanceSq, ref target)) 140 | { 141 | targetId = obj.Id; 142 | } 143 | } 144 | } 145 | 146 | // Did we select a new target? 147 | if (targetId > 0) 148 | { 149 | // Reset the timer. 150 | time = 0.0; 151 | 152 | // Render. 153 | Render(target, esp); 154 | 155 | // Return the selected target. 156 | return target; 157 | } 158 | } 159 | 160 | // We must wait before selecting another target. 161 | return Point.Empty; 162 | } 163 | 164 | private void Render(Point target, Esp esp) 165 | { 166 | if (esp != null && targetId > 0) 167 | { 168 | var width = 8; 169 | var height = 8; 170 | var rect = new Rectangle(target.X - width / 2, target.Y - height / 2, width, height); 171 | esp.Add(new RectangleShape(rect, Color.Red, Color.Red, 4)); 172 | } 173 | } 174 | 175 | private bool Select(TrackedObject obj, Point position, ref double minimumDistanceSq, ref Point target) 176 | { 177 | var selected = false; 178 | if ((Selecting & Selecting.Body) != 0) 179 | { 180 | var body = obj.Detection.BodyPosition; 181 | var distanceSq = position.DistanceSq(body); 182 | if (distanceSq < minimumDistanceSq) 183 | { 184 | minimumDistanceSq = distanceSq; 185 | target = body; 186 | selected = true; 187 | } 188 | } 189 | 190 | if ((Selecting & Selecting.Head) != 0) 191 | { 192 | var head = obj.Detection.HeadPosition; 193 | var distanceSq = position.DistanceSq(head); 194 | if (distanceSq <= minimumDistanceSq) 195 | { 196 | minimumDistanceSq = distanceSq; 197 | target = head; 198 | selected = true; 199 | } 200 | } 201 | 202 | return selected; 203 | } 204 | 205 | private Point Select(TrackedObject obj, Point position) 206 | { 207 | var distanceSq = double.MaxValue; 208 | var target = Point.Empty; 209 | Select(obj, position, ref distanceSq, ref target); 210 | return target; 211 | } 212 | 213 | protected virtual void Dispose(bool disposing) 214 | { 215 | if (disposed == false) 216 | { 217 | if (disposing) 218 | { 219 | // TODO: dispose managed state (managed objects). 220 | } 221 | 222 | disposed = true; 223 | } 224 | } 225 | 226 | public void Dispose() 227 | { 228 | Dispose(true); 229 | } 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /Selectors/Selector.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Renderers; 5 | using AimBot.Trackers; 6 | 7 | namespace AimBot.Selectors 8 | { 9 | public interface Selector : IDisposable 10 | { 11 | /// 12 | /// Selects and returns a point at which to aim. 13 | /// 14 | /// The tracker, which tracks detections. 15 | /// The current mouse position. 16 | /// The esp, which can be rendered to. 17 | /// Whther to select a target. 18 | /// The timestep. 19 | /// The selected point. 20 | Point Select(Tracker tracker, Point position, Esp esp, bool aim, double dt); 21 | 22 | void Clear(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Trackers/HungarianTracker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | 5 | using Newtonsoft.Json; 6 | 7 | using AimBot.Helpers; 8 | using AimBot.Detectors; 9 | using AimBot.Renderers; 10 | 11 | namespace AimBot.Trackers 12 | { 13 | public class HungarianTracker : Tracker 14 | { 15 | private readonly List trackedObjects; 16 | private readonly List droppedObjects; 17 | private readonly List dropIds; 18 | private uint nextId; 19 | private bool disposed; 20 | 21 | /// 22 | /// The length of time after which objects are removed from the inactive list. 23 | /// 24 | public double MaximumInactiveTime { get; set; } = 0.25; 25 | 26 | /// 27 | /// The maximum distance that a tracked object can move between frames before it is 28 | /// classified as a new object. 29 | /// 30 | public int MaximumTrackingDistance { get; set; } = 256; 31 | 32 | [JsonIgnore] 33 | public IEnumerable Active 34 | { 35 | get { return trackedObjects; } 36 | } 37 | 38 | [JsonIgnore] 39 | public IEnumerable Inactive 40 | { 41 | get { return droppedObjects; } 42 | } 43 | 44 | public HungarianTracker() 45 | { 46 | trackedObjects = new List(12); 47 | droppedObjects = new List(12); 48 | dropIds = new List(12); 49 | nextId = 1; 50 | } 51 | 52 | public void Clear() 53 | { 54 | trackedObjects.Clear(); 55 | droppedObjects.Clear(); 56 | dropIds.Clear(); 57 | nextId = 1; 58 | } 59 | 60 | public void Track(List detections, Esp esp, double dt) 61 | { 62 | // Purge dropped objects that have exceeded the time limit. 63 | for (int i = droppedObjects.Count - 1; i >= 0; --i) 64 | { 65 | var dropped = droppedObjects[i]; 66 | if (dropped.Time + dt > MaximumInactiveTime) 67 | { 68 | droppedObjects.RemoveFast(i); 69 | } 70 | else 71 | { 72 | droppedObjects[i] = new TrackedObject(dropped.Detection, dropped.Id, dropped.Time + dt); 73 | } 74 | } 75 | 76 | // Build the cost matrix. 77 | var rows = trackedObjects.Count + droppedObjects.Count; 78 | var cols = detections.Count; 79 | var dimensions = Math.Max(rows, cols); 80 | var costs = new double[dimensions, dimensions]; 81 | 82 | // Populate the cost matrix. 83 | // Detections are the rows of the matrix. 84 | // Tracked and droped objects are the columns. 85 | // Entries are the costs for matching each. 86 | // Note that if the number of detections is not equal to the number of tracked/dropped 87 | // objects then we will have a bunch of (dummy) zero entries. These correspond to 88 | // creating new tracked objects or dropping more tracked objects. 89 | for (int r = 0; r < detections.Count; ++r) 90 | { 91 | var detection = detections[r]; 92 | 93 | for (int c = 0; c < trackedObjects.Count; ++c) 94 | { 95 | costs[r, c] = GIOU(detection.BoundingBox, trackedObjects[c].Detection.BoundingBox); 96 | } 97 | 98 | for (int c = 0; c < droppedObjects.Count; ++c) 99 | { 100 | costs[r, trackedObjects.Count + c] = GIOU(detection.BoundingBox, droppedObjects[c].Detection.BoundingBox); 101 | } 102 | } 103 | 104 | // Find matches using the Hungarian Algorithm. 105 | var assignments = HungarianAlgorithm.FindAssignments(costs); 106 | 107 | // Update or create the tracked/dropped objects. 108 | var persistedCount = trackedObjects.Count; 109 | var maximumDistanceSq = MaximumTrackingDistance * MaximumTrackingDistance; 110 | for (int r = 0; r < detections.Count; ++r) 111 | { 112 | var detection = detections[r]; 113 | var detectionCenter = detection.BoundingBox.Center(); 114 | var c = assignments[r]; 115 | if (c < trackedObjects.Count) 116 | { 117 | // We have a match with a tracked object. 118 | // Check that the distance doesn't exceed the maximum allowed. 119 | var tracked = trackedObjects[c]; 120 | var distanceSq = detectionCenter.DistanceSq(tracked.Detection.BoundingBox.Center()); 121 | if (distanceSq <= maximumDistanceSq) 122 | { 123 | // Okay, we can update the tracked object. 124 | trackedObjects[c] = new TrackedObject(detection, trackedObjects[c].Id, trackedObjects[c].Time + dt); 125 | } 126 | else 127 | { 128 | // Distance limit exceeded. 129 | // We need to create a new tracking object and drop the old one. 130 | trackedObjects.RemoveFast(c); 131 | trackedObjects.Add(new TrackedObject(detection, nextId++, 0.0)); 132 | droppedObjects.Add(new TrackedObject(tracked.Detection, tracked.Id, 0.0)); 133 | persistedCount -= 1; 134 | } 135 | } 136 | else if (c < rows) 137 | { 138 | // We have a match with a dropped object. 139 | // Check the distance doesn't exceed the maximum allowed. 140 | var idx = rows - trackedObjects.Count - 1; 141 | var dropped = droppedObjects[idx]; 142 | var distanceSq = detectionCenter.DistanceSq(dropped.Detection.BoundingBox.Center()); 143 | if (distanceSq <= maximumDistanceSq) 144 | { 145 | // Okay, we can bring back the dropped object. 146 | trackedObjects.Add(new TrackedObject(detection, dropped.Id, 0.0)); 147 | droppedObjects.RemoveFast(idx); 148 | } 149 | else 150 | { 151 | // Distance limit exceeded. 152 | // We need to add a new tracking object. 153 | trackedObjects.Add(new TrackedObject(detection, nextId++, 0.0)); 154 | } 155 | } 156 | else 157 | { 158 | // Completely new object. 159 | trackedObjects.Add(new TrackedObject(detection, nextId++, 0.0)); 160 | } 161 | } 162 | 163 | // Collect the list of tracked object IDs to be removed from the tracked object list and 164 | // drop the trapped objects. 165 | dropIds.Clear(); 166 | for (int r = detections.Count; r < assignments.Length; ++r) 167 | { 168 | var c = assignments[r]; 169 | if (c < persistedCount) // We could have added/removed tracked objects above. 170 | { 171 | var tracked = trackedObjects[c]; 172 | dropIds.Add(tracked.Id); 173 | droppedObjects.Add(new TrackedObject(tracked.Detection, tracked.Id, 0.0)); 174 | } 175 | } 176 | 177 | // Now remove the dropped tracked objects. 178 | foreach (var id in dropIds) 179 | { 180 | for (int i = 0; i < persistedCount; ++i) 181 | { 182 | if (trackedObjects[i].Id == id) 183 | { 184 | trackedObjects.RemoveFast(i); 185 | persistedCount -= 1; 186 | break; 187 | } 188 | } 189 | } 190 | 191 | // Render tracked objects. 192 | if (esp != null) 193 | { 194 | foreach (var tracked in trackedObjects) 195 | { 196 | esp.Add(new TextShape(tracked.Detection.BoundingBox.TopLeft(), tracked.Id.ToString(), Color.Red, 12)); 197 | } 198 | } 199 | } 200 | 201 | /// 202 | /// Calculates the Generalised Intersection over Union. 203 | /// 204 | /// 205 | /// This metric is used for determining how closely matched two AABBs are. A low value 206 | /// indicates that the two rectanges are well matched. Note that this is better than the 207 | /// IoU metric, since it works with non-intersecting rectangles. 208 | /// See the following for a detailed description: https://giou.stanford.edu/ 209 | /// 210 | /// The first rectangle. 211 | /// The second rectangle. 212 | /// The Generalised Intersection over Union (GIOU). 213 | private static double GIOU(Rectangle r1, Rectangle r2) 214 | { 215 | // Calculate areas of rectangles. 216 | var a1 = r1.Width * r1.Height; 217 | var a2 = r2.Width * r2.Height; 218 | 219 | // Degenerate? 220 | if (a1 <= 0.0 || a2 <= 0.0) 221 | { 222 | return 1.0; 223 | } 224 | 225 | // Calculate area of intersection. 226 | var xi1 = Math.Max(r1.Left, r2.Left); 227 | var xi2 = Math.Min(r1.Right, r2.Right); 228 | var yi1 = Math.Max(r1.Top, r2.Top); 229 | var yi2 = Math.Min(r1.Bottom, r2.Bottom); 230 | var ai = 0.0; 231 | if (xi2 > xi1 && yi2 > yi1) 232 | { 233 | // Intersecting! 234 | ai = (xi2 - xi1) * (yi2 - yi1); 235 | } 236 | 237 | // Calculate the area of smallest enclosing box. 238 | var xc1 = Math.Min(r1.Left, r2.Left); 239 | var xc2 = Math.Max(r1.Right, r2.Right); 240 | var yc1 = Math.Min(r1.Top, r2.Top); 241 | var yc2 = Math.Max(r1.Bottom, r2.Bottom); 242 | var ac = (xc2 - xc1) * (yc2 - yc1); 243 | 244 | // Calculate the IoU and GIoU. 245 | var au = a1 + a2 - ai; 246 | var iou = ai / au; 247 | var giou = iou - ((ac - au) / ac); 248 | 249 | // Return GIoU loss. 250 | return 1.0 - giou; 251 | } 252 | 253 | protected virtual void Dispose(bool disposing) 254 | { 255 | if (disposed == false) 256 | { 257 | if (disposing) 258 | { 259 | // TODO: dispose managed state (managed objects). 260 | } 261 | 262 | disposed = true; 263 | } 264 | } 265 | 266 | public void Dispose() 267 | { 268 | Dispose(true); 269 | } 270 | 271 | // Copyright (c) 2010 Alex Regueiro 272 | // Licensed under MIT license, available at . 273 | // Published originally at . 274 | // Based on implementation described at . 275 | // Version 1.3, released 22nd May 2010. 276 | // 277 | // Note [Omar Kermad]: This looks to be performing a lot of allocations. We should really 278 | // try to allocate once and reuse where possible. 279 | private static class HungarianAlgorithm 280 | { 281 | public static int[] FindAssignments(double[,] costs) 282 | { 283 | var h = costs.GetLength(0); 284 | var w = costs.GetLength(1); 285 | 286 | for (int i = 0; i < h; i++) 287 | { 288 | var min = double.MaxValue; 289 | 290 | for (int j = 0; j < w; j++) 291 | { 292 | min = Math.Min(min, costs[i, j]); 293 | } 294 | 295 | for (int j = 0; j < w; j++) 296 | { 297 | costs[i, j] -= min; 298 | } 299 | } 300 | 301 | var masks = new byte[h, w]; 302 | var rowsCovered = new bool[h]; 303 | var colsCovered = new bool[w]; 304 | 305 | for (int i = 0; i < h; i++) 306 | { 307 | for (int j = 0; j < w; j++) 308 | { 309 | if (costs[i, j] == 0 && !rowsCovered[i] && !colsCovered[j]) 310 | { 311 | masks[i, j] = 1; 312 | rowsCovered[i] = true; 313 | colsCovered[j] = true; 314 | } 315 | } 316 | } 317 | 318 | ClearCovers(rowsCovered, colsCovered, w, h); 319 | 320 | var path = new Location[w * h]; 321 | var pathStart = default(Location); 322 | var step = 1; 323 | while (step != -1) 324 | { 325 | switch (step) 326 | { 327 | case 1: 328 | step = RunStep1(masks, colsCovered, w, h); 329 | break; 330 | case 2: 331 | step = RunStep2(costs, masks, rowsCovered, colsCovered, w, h, ref pathStart); 332 | break; 333 | case 3: 334 | step = RunStep3(masks, rowsCovered, colsCovered, w, h, path, pathStart); 335 | break; 336 | case 4: 337 | step = RunStep4(costs, masks, rowsCovered, colsCovered, w, h); 338 | break; 339 | } 340 | } 341 | 342 | var agentsTasks = new int[h]; 343 | for (int i = 0; i < h; i++) 344 | { 345 | for (int j = 0; j < w; j++) 346 | { 347 | if (masks[i, j] == 1) 348 | { 349 | agentsTasks[i] = j; 350 | break; 351 | } 352 | } 353 | } 354 | 355 | return agentsTasks; 356 | } 357 | 358 | private static int RunStep1(byte[,] masks, bool[] colsCovered, int w, int h) 359 | { 360 | for (int i = 0; i < h; i++) 361 | { 362 | for (int j = 0; j < w; j++) 363 | { 364 | if (masks[i, j] == 1) 365 | { 366 | colsCovered[j] = true; 367 | } 368 | } 369 | } 370 | 371 | var colsCoveredCount = 0; 372 | for (int j = 0; j < w; j++) 373 | { 374 | if (colsCovered[j]) 375 | { 376 | colsCoveredCount++; 377 | } 378 | } 379 | 380 | if (colsCoveredCount == h) 381 | { 382 | return -1; 383 | } 384 | else 385 | { 386 | return 2; 387 | } 388 | } 389 | 390 | private static int RunStep2(double[,] costs, byte[,] masks, bool[] rowsCovered, bool[] colsCovered, int w, int h, ref Location pathStart) 391 | { 392 | Location loc; 393 | while (true) 394 | { 395 | loc = FindZero(costs, rowsCovered, colsCovered, w, h); 396 | if (loc.Row == -1) 397 | { 398 | return 4; 399 | } 400 | else 401 | { 402 | masks[loc.Row, loc.Column] = 2; 403 | var starCol = FindStarInRow(masks, w, loc.Row); 404 | 405 | if (starCol != -1) 406 | { 407 | rowsCovered[loc.Row] = true; 408 | colsCovered[starCol] = false; 409 | } 410 | else 411 | { 412 | pathStart = loc; 413 | return 3; 414 | } 415 | } 416 | } 417 | } 418 | 419 | private static int RunStep3(byte[,] masks, bool[] rowsCovered, bool[] colsCovered, int w, int h, Location[] path, Location pathStart) 420 | { 421 | var pathIndex = 0; 422 | path[0] = pathStart; 423 | 424 | while (true) 425 | { 426 | var row = FindStarInColumn(masks, h, path[pathIndex].Column); 427 | if (row == -1) 428 | { 429 | break; 430 | } 431 | 432 | pathIndex++; 433 | path[pathIndex] = new Location(row, path[pathIndex - 1].Column); 434 | var col = FindPrimeInRow(masks, w, path[pathIndex].Row); 435 | pathIndex++; 436 | path[pathIndex] = new Location(path[pathIndex - 1].Row, col); 437 | } 438 | 439 | ConvertPath(masks, path, pathIndex + 1); 440 | ClearCovers(rowsCovered, colsCovered, w, h); 441 | ClearPrimes(masks, w, h); 442 | 443 | return 1; 444 | } 445 | 446 | private static int RunStep4(double[,] costs, byte[,] masks, bool[] rowsCovered, bool[] colsCovered, int w, int h) 447 | { 448 | var minValue = FindMinimum(costs, rowsCovered, colsCovered, w, h); 449 | for (int i = 0; i < h; i++) 450 | { 451 | for (int j = 0; j < w; j++) 452 | { 453 | if (rowsCovered[i]) 454 | { 455 | costs[i, j] += minValue; 456 | } 457 | 458 | if (!colsCovered[j]) 459 | { 460 | costs[i, j] -= minValue; 461 | } 462 | } 463 | } 464 | 465 | return 2; 466 | } 467 | 468 | private static void ConvertPath(byte[,] masks, Location[] path, int pathLength) 469 | { 470 | for (int i = 0; i < pathLength; i++) 471 | { 472 | if (masks[path[i].Row, path[i].Column] == 1) 473 | { 474 | masks[path[i].Row, path[i].Column] = 0; 475 | } 476 | else if (masks[path[i].Row, path[i].Column] == 2) 477 | { 478 | masks[path[i].Row, path[i].Column] = 1; 479 | } 480 | } 481 | } 482 | 483 | private static Location FindZero(double[,] costs, bool[] rowsCovered, bool[] colsCovered, int w, int h) 484 | { 485 | for (int i = 0; i < h; i++) 486 | { 487 | for (int j = 0; j < w; j++) 488 | { 489 | if (costs[i, j] == 0.0 && !rowsCovered[i] && !colsCovered[j]) 490 | { 491 | return new Location(i, j); 492 | } 493 | } 494 | } 495 | 496 | return new Location(-1, -1); 497 | } 498 | 499 | private static double FindMinimum(double[,] costs, bool[] rowsCovered, bool[] colsCovered, int w, int h) 500 | { 501 | var minValue = double.MaxValue; 502 | for (int i = 0; i < h; i++) 503 | { 504 | for (int j = 0; j < w; j++) 505 | { 506 | if (!rowsCovered[i] && !colsCovered[j]) 507 | { 508 | minValue = Math.Min(minValue, costs[i, j]); 509 | } 510 | } 511 | } 512 | 513 | return minValue; 514 | } 515 | 516 | private static int FindStarInRow(byte[,] masks, int w, int row) 517 | { 518 | for (int j = 0; j < w; j++) 519 | { 520 | if (masks[row, j] == 1) 521 | { 522 | return j; 523 | } 524 | } 525 | 526 | return -1; 527 | } 528 | 529 | private static int FindStarInColumn(byte[,] masks, int h, int col) 530 | { 531 | for (int i = 0; i < h; i++) 532 | { 533 | if (masks[i, col] == 1) 534 | { 535 | return i; 536 | } 537 | } 538 | 539 | return -1; 540 | } 541 | 542 | private static int FindPrimeInRow(byte[,] masks, int w, int row) 543 | { 544 | for (int j = 0; j < w; j++) 545 | { 546 | if (masks[row, j] == 2) 547 | { 548 | return j; 549 | } 550 | } 551 | 552 | return -1; 553 | } 554 | 555 | private static void ClearCovers(bool[] rowsCovered, bool[] colsCovered, int w, int h) 556 | { 557 | for (int i = 0; i < h; i++) 558 | { 559 | rowsCovered[i] = false; 560 | } 561 | 562 | for (int j = 0; j < w; j++) 563 | { 564 | colsCovered[j] = false; 565 | } 566 | } 567 | 568 | private static void ClearPrimes(byte[,] masks, int w, int h) 569 | { 570 | for (int i = 0; i < h; i++) 571 | { 572 | for (int j = 0; j < w; j++) 573 | { 574 | if (masks[i, j] == 2) 575 | { 576 | masks[i, j] = 0; 577 | } 578 | } 579 | } 580 | } 581 | 582 | private struct Location 583 | { 584 | public readonly int Row; 585 | public readonly int Column; 586 | 587 | public Location(int row, int col) 588 | { 589 | this.Row = row; 590 | this.Column = col; 591 | } 592 | } 593 | } 594 | } 595 | } 596 | -------------------------------------------------------------------------------- /Trackers/Tracker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using AimBot.Detectors; 5 | using AimBot.Renderers; 6 | 7 | namespace AimBot.Trackers 8 | { 9 | public readonly struct TrackedObject 10 | { 11 | /// 12 | /// The detection. 13 | /// 14 | public readonly Detection Detection; 15 | 16 | /// 17 | /// The unique tracking identifier. 18 | /// 19 | public readonly uint Id; 20 | 21 | /// 22 | /// The time that the object has been in the active or inactive list. 23 | /// 24 | public readonly double Time; 25 | 26 | public TrackedObject(Detection detection, uint id, double time) 27 | { 28 | Detection = detection; 29 | Id = id; 30 | Time = time; 31 | } 32 | } 33 | 34 | public interface Tracker : IDisposable 35 | { 36 | /// 37 | /// The list of active objects. 38 | /// 39 | /// 40 | /// These are objects that are currently detected. 41 | /// 42 | IEnumerable Active { get; } 43 | 44 | /// 45 | /// The list of inactive objects. 46 | /// 47 | /// 48 | /// These are objects that are not currently detected, but were recently detected. 49 | /// 50 | IEnumerable Inactive { get; } 51 | 52 | void Track(List detections, Esp esp, double dt); 53 | 54 | void Clear(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Triggers/ProximityTrigger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Helpers; 5 | using AimBot.Injectors; 6 | using AimBot.Renderers; 7 | 8 | namespace AimBot.Triggers 9 | { 10 | public class ProximityTrigger : Trigger 11 | { 12 | [Flags] 13 | public enum Condition 14 | { 15 | Never = 0, 16 | WhenAiming = 1 << 0, 17 | WhenNotAiming = 1 << 1, 18 | Always = WhenAiming | WhenNotAiming 19 | } 20 | 21 | private double time; 22 | private bool disposed; 23 | 24 | public int Proximity { get; set; } = 20; 25 | public double TriggerRate { get; set; } = 0.8; 26 | public bool ContinueAiming { get; set; } = true; 27 | public Condition Conditions { get; set; } = Condition.Never; 28 | public int TriggerButton { get; set; } = 0; 29 | 30 | public ProximityTrigger() 31 | { 32 | Clear(); 33 | } 34 | 35 | public void Clear() 36 | { 37 | time = 0.0; 38 | } 39 | 40 | public void Trigger(MouseInjector injector, Point current, Point target, Rectangle region, Esp esp, ref bool aim, double dt) 41 | { 42 | time += dt; 43 | 44 | if (Conditions != Condition.Never) 45 | { 46 | if (target != Point.Empty && esp != null) 47 | { 48 | esp.Add(new CircleShape(new Point(target.X, target.Y), Proximity, Color.Transparent, Color.Yellow, 1)); 49 | } 50 | 51 | bool trigger = (aim == true && (Conditions & Condition.WhenAiming) != 0) || 52 | (aim == false && (Conditions & Condition.WhenNotAiming) != 0); 53 | 54 | if (trigger && time >= TriggerRate) 55 | { 56 | var distanceSq = current.DistanceSq(target); 57 | if (distanceSq <= Proximity * Proximity) 58 | { 59 | injector.Click(TriggerButton, 50); 60 | time = 0.0; 61 | if (ContinueAiming == false) 62 | { 63 | aim = false; 64 | } 65 | } 66 | } 67 | } 68 | } 69 | 70 | protected virtual void Dispose(bool disposing) 71 | { 72 | if (disposed == false) 73 | { 74 | if (disposing) 75 | { 76 | // TODO: dispose managed state (managed objects). 77 | } 78 | 79 | disposed = true; 80 | } 81 | } 82 | 83 | public void Dispose() 84 | { 85 | Dispose(true); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Triggers/Trigger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | using AimBot.Injectors; 5 | using AimBot.Renderers; 6 | 7 | namespace AimBot.Triggers 8 | { 9 | public interface Trigger : IDisposable 10 | { 11 | void Trigger(MouseInjector injector, Point current, Point target, Rectangle region, Esp esp, ref bool aim, double dt); 12 | void Clear(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gui.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kermado/NeuralBot/3a5fc6b3cace10dd5224cffb8153bb0866fedc47/gui.PNG --------------------------------------------------------------------------------