├── .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 | 
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
--------------------------------------------------------------------------------