Skip to content

Instantly share code, notes, and snippets.

@mrbid
Last active January 7, 2023 12:16
Show Gist options
  • Select an option

  • Save mrbid/6552c9a6d52d1be452aecefbb8fb8b72 to your computer and use it in GitHub Desktop.

Select an option

Save mrbid/6552c9a6d52d1be452aecefbb8fb8b72 to your computer and use it in GitHub Desktop.
The best trained minimal CNN bot for CS:GO.
/*
--------------------------------------------------
James William Fletcher (github.com/mrbid)
SEPTEMBER 2022
--------------------------------------------------
*** WIP, did I get the 4 dimensional array index right? where is walley leaking memory? ***
I lost interest in this for now, may revisit it next year.
This is a forward pass network I have spent a lot of
time working on from scratch. As of this month and
year I consider this to be the best performing
minimal network.
Weights exported from Keras for inference.
no padding, no bias, grayscale input, 3x3 kernels, channels_last
rows, cols, kernels
y,x,k
kernels:
3,3,2
3,3,4
3,3,8
input: 28x28x1
conv: 3x3x2 > 26x26x2 : relu
maxpool: 13x13
conv: 3x3x4 > 11x11x4 : relu
maxpool: 5x5
conv: 3x3x8 > 3x3x8 : relu
gap: array(8)
dense: sigmoid output
- 28088 FLOPS (floating-point operations per scan)
- This network identifies heads in the Valve Software game CS:GO.
- Maybe I should have transposed these to channels_first?
- If not maybe I should invert the for loop nesting to channels first?
- You may want to install espeak via your package manager.
- clang main.c -Ofast -mfma -lX11 -lm -o aim
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <unistd.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <sys/time.h>
#include <sys/stat.h>
// general
#pragma GCC diagnostic ignored "-Wgnu-folding-constant"
#define forceinline __attribute__((always_inline)) inline
#define uint unsigned int
// scan area vars
#define SCAN_AREA 28
const uint r0 = SCAN_AREA; // dimensions of sample image square
const uint r2 = r0*r0; // total pixels in square
const uint r2i = r2*3; // total inputs to neural net pixels*channels
const uint rd2 = r0/2; // total pixels divided by two
uint x=0, y=0;
float input[r2] = {0};
// x11 vars
Display *d;
int si;
Window twin = 0;
GC gc = 0;
unsigned char pgmbytes[r2] = {0};
char targets_dir[256];
uint sps = 0; // for SPS
// settings
uint enable = 0;
uint sample_capture = 0;
uint crosshair = 1;
uint hotkeys = 1;
// hyperparameters that you can change
#define TRIGGER 1 // how many times to pull the trigger when a target is detected
//#define SCAN_VARIANCE 0.f // how much to randomly wiggle the scan area between scans
#define SCAN_DELAY 1000 // scan frequency delay in microseconds
#define ACTIVATION_SENITIVITY 0.9f // minimum activation sensitivity to fire a shot
#define REPEAT_ACTIVATION 0 // how many positive activations in a row before firing a shot
#define FIRE_RATE_LIMIT_MS 100 // delay between firing shots in milliseconds
#define TRIGGER_RATE_LIMIT_MS 30 // delay between firing shots between TRIGGER iterations in milliseconds
/***************************************************
~~ Neural Network Forward-Pass
*/
// Layers
forceinline uint CL0(uint y, uint x){return y * 28 + x;}
float CL1F[1352];
forceinline uint CL1(uint y, uint x, uint k){return y * (2 * 26) + x * 2 + k;}
float CL1PF[338];
forceinline uint CL1P(uint y, uint x, uint k){return y * (2 * 13) + x * 2 + k;}
float CL2F[484];
forceinline uint CL2(uint y, uint x, uint k){return y * (4 * 11) + x * 4 + k;}
float CL2PF[100];
forceinline uint CL2P(uint y, uint x, uint k){return y * (4 * 5) + x * 4 + k;}
float CL3F[72];
forceinline uint CL3(uint y, uint x, uint k){return y * (8 * 3) + x * 8 + k;}
// Kernels
const float /*18*/ f1[] = {-0.10085268f,-0.5327633f,-0.093879305f,0.9093193f,0.45742872f,-0.54601395f,-0.109133825f,0.27121156f,-0.3521443f,-0.44989288f,0.37559956f,0.28491852f,0.8056581f,0.36666352f,0.5286602f,-0.60915345f,-0.11539043f,0.22436628f};
forceinline uint CF1(uint y, uint x, uint k){return y * (2 * 3) + x * 2 + k;}
const float /*72*/ f2[] = {0.3625854f,-0.2961693f,0.34357676f,-0.09004362f,0.51307756f,-3.5217664f,-0.39044002f,-0.2900187f,0.13758732f,-0.32059073f,-0.10238134f,0.37341678f,1.2980468f,-1.8488529f,-1.5052714f,0.7356388f,-0.078636244f,0.27923414f,0.077999316f,0.4445f,-0.36241f,0.9078533f,-0.38832384f,0.21853346f,-0.46116298f,0.30799797f,0.5373813f,0.37880236f,-0.7928643f,-0.8725977f,0.2778252f,0.097840056f,0.42987445f,0.14128259f,0.36648455f,-0.22519167f,0.15652227f,0.92756784f,0.23862366f,0.6194639f,0.30409643f,-0.51745474f,0.0024263235f,-0.12897015f,1.1616807f,0.7814885f,-0.62208676f,-0.40302494f,-0.16045721f,0.2694907f,-0.21484402f,0.11004151f,0.764975f,0.33624822f,-0.19113706f,1.9655595f,-0.46846592f,0.22514774f,0.43947503f,-1.0024278f,0.36089367f,0.15557878f,-0.2792994f,0.12491965f,-0.22553426f,-0.3300921f,-0.017703544f,-0.7742302f,1.2367371f,0.1950125f,-1.3916389f,-0.2607476f};
forceinline uint CF2(uint y, uint x, uint k, uint d){return y * (2 * 4 * 3) + x * (4 * 3) + d * 2 + k;}
const float /*288*/ f3[] = {-0.6666318f,-0.6499509f,0.017249504f,-0.16326442f,-0.22811371f,0.6105372f,-1.2061936f,0.010394949f,1.9372067f,1.7710887f,1.7254974f,1.7425989f,-1.3244041f,1.048707f,2.1588702f,1.7392019f,-0.42127144f,-0.11061933f,-0.3554936f,-0.019667566f,0.12338132f,-0.06739373f,0.20636322f,-0.05645989f,0.90321827f,1.4634635f,1.3782281f,1.2930415f,-1.1278466f,0.7545569f,0.82316697f,1.4057527f,0.38134363f,-0.64948016f,0.42578185f,-0.23418133f,0.30430847f,-0.31941235f,0.017438103f,-0.33156964f,0.5274514f,1.8053904f,0.786523f,1.5999506f,-1.629409f,1.9005216f,1.5866919f,1.8491492f,0.45213234f,0.15404697f,0.5348579f,-0.03504686f,0.50366986f,-0.38578567f,0.09311065f,0.14972478f,0.06680024f,0.24241066f,-0.5661344f,-0.46240142f,0.6674583f,-0.061471906f,0.7778293f,0.00547942f,0.3505525f,-0.3217814f,0.5647048f,-0.46430093f,0.3413247f,-0.93530357f,0.68285865f,-0.8179386f,-0.9443577f,0.99222124f,-0.74951744f,1.5060915f,-1.8539797f,-1.2733712f,-0.3136488f,1.6198969f,0.3050006f,-0.12353183f,0.2600941f,-0.05577971f,0.7012368f,-0.69120103f,0.08819378f,-0.23662797f,-0.9264782f,0.02257323f,-1.304195f,-0.266403f,0.35280138f,-0.93557376f,-0.2724371f,0.036498073f,-1.0345271f,-0.09567977f,-0.6391683f,-0.14270216f,-0.11629022f,0.13955416f,-0.72821933f,-0.17132543f,0.35356653f,-0.2813003f,-0.60093063f,-0.18304347f,0.14200652f,1.4064893f,0.32346547f,-0.5312404f,-0.23669605f,-0.11699825f,-0.29569745f,-0.25634912f,0.30916855f,0.4422385f,-0.106391065f,-0.16948828f,0.06795499f,0.5405564f,-0.07677913f,0.23410861f,-0.30062374f,1.1781301f,-1.1384887f,-0.017022943f,-0.30742258f,-0.17424811f,-0.011861075f,-0.006211239f,0.07467434f,-0.4911204f,-0.42237592f,0.19911426f,0.94744396f,0.56354165f,0.12879127f,0.69064784f,-0.7407655f,1.937518f,0.3084967f,0.844227f,-0.121149786f,0.2743653f,0.38621083f,0.3470594f,0.056427915f,-0.12770227f,-0.13791257f,0.23218161f,0.7226025f,-0.22627075f,-0.246187f,-0.7509091f,0.97558045f,0.75327444f,0.8887772f,-0.7208585f,0.9673093f,-0.2824686f,0.158171f,-0.63391435f,0.56319493f,0.23208329f,0.48720482f,-0.33179942f,-0.34003234f,0.17145425f,0.107116565f,0.5767645f,0.17950015f,-0.58480746f,-0.886015f,0.3794311f,0.037069265f,-0.03622643f,0.08028794f,0.24633844f,0.10488024f,0.17855826f,-0.113084584f,0.13750535f,-0.23423539f,-0.012242726f,-0.26542222f,-0.1018701f,0.8441302f,0.29523608f,-0.32725728f,0.040206067f,0.0357823f,0.0075954227f,-0.23309204f,0.24467848f,-1.1471972f,-0.1885725f,-0.17840974f,0.31720218f,1.2253202f,-0.33104882f,0.3171273f,-0.25064176f,-0.41660643f,1.2757696f,1.1084087f,-0.033284497f,0.18243246f,-0.09396731f,-0.09534969f,-0.1469201f,0.33480045f,0.6946161f,0.2978034f,-0.36039257f,1.0407037f,0.1910912f,1.3607627f,0.48659712f,-2.0204294f,0.6403378f,-0.08928161f,0.9058087f,-0.24339463f,0.5362985f,-0.0608694f,0.33523193f,-1.1249162f,-1.2907683f,0.14169537f,0.12229522f,0.10730731f,0.5749354f,0.36680436f,0.5716122f,-0.9392891f,1.2686868f,0.9139534f,0.20032431f,-0.58617896f,0.2567366f,-0.50432104f,0.10609374f,0.32372996f,-0.20171365f,-0.33536744f,0.31133586f,0.61647445f,-0.33804142f,0.35246393f,-0.615248f,0.0524327f,0.66400695f,1.0802368f,-0.8643f,0.43973807f,0.5051888f,0.1118751f,0.49338824f,-0.8811681f,-2.5034041f,0.49740288f,0.46392873f,-0.4952641f,-0.123362236f,-0.8946474f,-0.195359f,0.07260272f,-1.8585433f,-1.1545897f,0.36304718f,-0.7406244f,0.07727978f,-0.48872453f,-0.045256052f,0.4778138f,-0.15295202f,-0.7671279f,0.13332541f,-1.1735713f,-0.22989619f,-0.6292691f,-0.5701288f,0.37870747f,-0.35531673f,0.4285855f,-0.5731319f};
forceinline uint CF3(uint y, uint x, uint k, uint d){return y * (4 * 8 * 3) + x * (8 * 3) + d * 8 + k;}
// final dense layer
const float /*8*/ d1[] = {2.3085554f,1.15268f,2.1598685f,1.219241f,-1.2499405f,-3.7682545f,2.529647f,1.0187337f};
// bias: -1.4903662
// processModel
float processModel()
{
printf("a0\n");
// 2 kernels on input, no padding
for(uint y = 1; y < 27; y++)
{
for(uint x = 1; x < 27; x++)
{
for(uint k = 0; k < 2; k++)
{
float ro = 0.f;
// lower row
printf("a0.0.1 - %u %u %u\n", y-1,x-1,CL0(y-1,x-1));
ro += input[CL0(y-1,x-1)]* f1[CF1(0,0,k)];
printf("a0.0.2\n");
ro += input[CL0(y-1,x)] * f1[CF1(0,1,k)];
printf("a0.0.3\n");
ro += input[CL0(y-1,x+1)]* f1[CF1(0,2,k)];
printf("a0.1\n");
// middle row
ro += input[CL0(y,x-1)] * f1[CF1(1,0,k)];
ro += input[CL0(y,x)] * f1[CF1(1,1,k)];
ro += input[CL0(y,x+1)] * f1[CF1(1,2,k)];
printf("a0.2\n");
// top row
ro += input[CL0(y+1,x-1)]* f1[CF1(2,0,k)];
ro += input[CL0(y+1,x)] * f1[CF1(2,1,k)];
ro += input[CL0(y+1,x+1)]* f1[CF1(2,2,k)];
printf("a0.3\n");
// set output
if(ro < 0.f){ro = 0.f;} // relu
CL1F[CL1(x-1, y-1, k)] = ro;
}
}
}
printf("a1\n");
// max pool it
uint oy = 0, ox = 0;
for(uint y = 0; y < 26; y += 2, oy++)
{
for(uint x = 0; x < 26; x += 2, ox++)
{
for(uint k = 0; k < 2; k++)
{
float max = 0.f;
if(CL1F[CL1(y,x,k)] > max)
max = CL1F[CL1(y,x,k)];
if(CL1F[CL1(y,x+1,k)] > max)
max = CL1F[CL1(y,x+1,k)];
if(CL1F[CL1(y+1,x,k)] > max)
max = CL1F[CL1(y+1,x,k)];
if(CL1F[CL1(y+1,x+1,k)] > max)
max = CL1F[CL1(y+1,x+1,k)];
// output max val
CL1PF[CL1P(oy,ox,k)] = max;
}
}
}
printf("a2\n");
// 4 kernels on pooled output, no padding
for(uint y = 1; y < 12; y++)
{
for(uint x = 1; x < 12; x++)
{
for(uint k = 0; k < 4; k++)
{
float ro = 0.f;
for(uint d = 0; d < 2; d++)
{
// lower row
ro += CL1PF[CL1P(y-1,x-1,d)]* f2[CF2(0,0,d,k)];
ro += CL1PF[CL1P(y-1,x,d)] * f2[CF2(0,1,d,k)];
ro += CL1PF[CL1P(y-1,x+1,d)]* f2[CF2(0,2,d,k)];
// middle row
ro += CL1PF[CL1P(y,x-1,d)] * f2[CF2(1,0,d,k)];
ro += CL1PF[CL1P(y,x,d)] * f2[CF2(1,1,d,k)];
ro += CL1PF[CL1P(y,x+1,d)] * f2[CF2(1,2,d,k)];
// top row
ro += CL1PF[CL1P(y+1,x-1,d)]* f2[CF2(2,0,d,k)];
ro += CL1PF[CL1P(y+1,x,d)] * f2[CF2(2,1,d,k)];
ro += CL1PF[CL1P(y+1,x+1,d)]* f2[CF2(2,2,d,k)];
}
if(ro < 0.f){ro = 0.f;} // relu
CL2F[CL2(x-1, y-1, k)] = ro;
}
}
}
printf("a3\n");
// max pool it
oy = 0, ox = 0;
for(uint y = 0; y < 11; y += 2, oy++)
{
for(uint x = 0; x < 11; x += 2, ox++)
{
for(uint k = 0; k < 4; k++)
{
float max = 0.f;
if(CL2F[CL2(y,x,k)] > max)
max = CL2F[CL2(y,x,k)];
if(CL2F[CL2(y,x+1,k)] > max)
max = CL2F[CL2(y,x+1,k)];
if(CL2F[CL2(y+1,x,k)] > max)
max = CL2F[CL2(y+1,x,k)];
if(CL2F[CL2(y+1,x+1,k)] > max)
max = CL2F[CL2(y+1,x+1,k)];
// output max val
CL2PF[CL2P(oy,ox,k)] = max;
}
}
}
printf("a4\n");
// 8 kernels on pooled output, no padding
for(uint y = 1; y < 4; y++)
{
for(uint x = 1; x < 4; x++)
{
for(uint k = 0; k < 8; k++)
{
float ro = 0.f;
for(uint d = 0; d < 4; d++)
{
// lower row
ro += CL2PF[CL2P(y-1,x-1,d)]* f3[CF3(0,0,d,k)];
ro += CL2PF[CL2P(y-1,x,d)] * f3[CF3(0,1,d,k)];
ro += CL2PF[CL2P(y-1,x+1,d)]* f3[CF3(0,2,d,k)];
// middle row
ro += CL2PF[CL2P(y,x-1,d)] * f3[CF3(1,0,d,k)];
ro += CL2PF[CL2P(y,x,d)] * f3[CF3(1,1,d,k)];
ro += CL2PF[CL2P(y,x+1,d)] * f3[CF3(1,2,d,k)];
// top row
ro += CL2PF[CL2P(y+1,x-1,d)]* f3[CF3(2,0,d,k)];
ro += CL2PF[CL2P(y+1,x,d)] * f3[CF3(2,1,d,k)];
ro += CL2PF[CL2P(y+1,x+1,d)]* f3[CF3(2,2,d,k)];
}
if(ro < 0.f){ro = 0.f;} // relu
CL3F[CL3(x-1, y-1, k)] = ro;
}
}
}
printf("a5\n");
// gap
float dense[8] = {0.f};
for(uint y = 0; y < 3; y++)
{
for(uint x = 0; x < 3; x++)
{
for(uint d = 0; d < 8; d++)
{
dense[d] += CL3F[CL3(y, x, d)];
}
}
}
for(uint d = 0; d < 8; d++)
dense[d] /= 9;
printf("a6\n");
// dense
float out = 0.f;
for(uint d = 0; d < 8; d++)
out += dense[d] * d1[d];
out += -1.4903662f;
printf("a7\n");
// sigmoid output
return 1.f / (1.f + expf(-out));
}
/***************************************************
~~ Utils
*/
uint qRand(const float min, const float max)
{
static float rndmax = 1.f/(float)RAND_MAX;
return (((float)rand()) * rndmax) * (max-min) + min;
}
void writePGM(const char* file, const unsigned char* data)
{
FILE* f = fopen(file, "wb");
if(f != NULL)
{
fprintf(f, "P5 28 28 255 ");
fwrite(data, 1, r2i, f);
fclose(f);
}
}
uint64_t microtime()
{
struct timeval tv;
struct timezone tz;
memset(&tz, 0, sizeof(struct timezone));
gettimeofday(&tv, &tz);
return 1000000 * tv.tv_sec + tv.tv_usec;
}
void rainbow_printf(const char* text)
{
static unsigned char base_clr = 0;
if(base_clr == 0)
base_clr = (rand()%125)+55;
base_clr += 3;
unsigned int clr = base_clr;
const unsigned int len = strlen(text);
for(unsigned int i = 0; i < len; i++)
{
clr++;
printf("\e[38;5;%im", clr);
printf("%c", text[i]);
}
printf("\e[38;5;123m");
}
void rainbow_line_printf(const char* text)
{
static unsigned char base_clr = 0;
if(base_clr == 0)
base_clr = (rand()%125)+55;
printf("\e[38;5;%im", base_clr);
base_clr++;
if(base_clr >= 230)
base_clr = (rand()%125)+55;
const unsigned int len = strlen(text);
for(unsigned int i = 0; i < len; i++)
printf("%c", text[i]);
printf("\e[38;5;123m");
}
//https://www.cl.cam.ac.uk/~mgk25/ucs/keysymdef.h
int key_is_pressed(KeySym ks)
{
char keys_return[32];
XQueryKeymap(d, keys_return);
KeyCode kc2 = XKeysymToKeycode(d, ks);
int isPressed = !!(keys_return[kc2 >> 3] & (1 << (kc2 & 7)));
return isPressed;
}
void speakS(const char* text)
{
char s[256];
sprintf(s, "/usr/bin/espeak \"%s\"", text);
if(system(s) <= 0)
sleep(1);
}
Window findWindow(Display *d, Window current, char const *needle)
{
Window ret = 0, root, parent, *children;
unsigned cc;
char *name = NULL;
if(current == 0)
current = XDefaultRootWindow(d);
if(XFetchName(d, current, &name) > 0)
{
if(strstr(name, needle) != NULL)
{
XFree(name);
return current;
}
XFree(name);
}
if(XQueryTree(d, current, &root, &parent, &children, &cc) != 0)
{
for(unsigned int i = 0; i < cc; ++i)
{
Window win = findWindow(d, children[i], needle);
if(win != 0)
{
ret = win;
break;
}
}
XFree(children);
}
return ret;
}
void processScanArea(Window w)
{
// get image block
XImage *img;
#ifdef SCAN_VARIANCE
img = XGetImage(d, w, (x+qRand(-SCAN_VARIANCE, SCAN_VARIANCE))-rd2, (y+qRand(-SCAN_VARIANCE, SCAN_VARIANCE))-rd2, r0, r0, AllPlanes, XYPixmap);
#else
img = XGetImage(d, w, x-rd2, y-rd2, r0, r0, AllPlanes, XYPixmap);
#endif
if(img == NULL)
return;
// extract colour information
int i = 0;
for(int y = 0; y < r0; y++)
{
for(int x = 0; x < r0; x++)
{
const unsigned long pixel = XGetPixel(img, x, y);
const unsigned char sr = (pixel & img->red_mask) >> 16;
const unsigned char sg = (pixel & img->green_mask) >> 8;
const unsigned char sb = pixel & img->blue_mask;
// 0-1 norm
input[i] = ((sr * 0.003921568859f) + (sg * 0.003921568859f) + (sb * 0.003921568859f)) * 0.3333333433f;
pgmbytes[i] = (sr + sg + sb) / 3;
i++;
}
}
// free image block
XDestroyImage(img);
// increment SPS
sps++;
}
void reprint()
{
//system("clear");
rainbow_printf("James William Fletcher (github.com/mrbid)\n");
rainbow_printf("L-CTRL + L-ALT = Toggle BOT ON/OFF\n");
rainbow_printf("R-CTRL + R-ALT = Toggle HOTKEYS ON/OFF\n");
rainbow_printf("P = Toggle crosshair.\n");
rainbow_printf("G = Get activation for reticule area.\n");
rainbow_printf("H = Hold pressed to print scans per second.\n");
rainbow_printf("L = Toggle sample capture.\n");
rainbow_printf("E = Manual sample capture.\n");
printf("\e[38;5;76m");
printf("\nMake the crosshair a single green pixel.\nOR disable the game crosshair and use the crosshair provided by this bot.\nOR if your monitor provides a crosshair use that. (this is best)\n\n");
printf("This bot will only auto trigger when W,A,S,D & L-SHIFT are not being pressed.\n(so when your not moving in game, aka stationary)\n\nL-SHIFT allows you to disable the bot while stationary if desired.\n\n");
printf("\e[38;5;123m");
if(twin != 0)
{
printf("CS:GO Win: 0x%lX\n\n", twin);
if(enable == 1)
rainbow_line_printf("BOT: \033[1m\e[32mON\e[0m\n");
else
rainbow_line_printf("BOT: \033[1m\e[31mOFF\e[0m\n");
if(hotkeys == 1)
rainbow_line_printf("HOTKEYS: \033[1m\e[32mON\e[0m\n");
else
rainbow_line_printf("HOTKEYS: \033[1m\e[31mOFF\e[0m\n");
if(sample_capture == 1)
rainbow_line_printf("SAMPLE CAPTURE: \033[1m\e[32mON\e[0m\n");
else
rainbow_line_printf("SAMPLE CAPTURE: \033[1m\e[31mOFF\e[0m\n");
if(crosshair == 1)
rainbow_line_printf("CROSSHAIR: \033[1m\e[32mON\e[0m\n");
else
rainbow_line_printf("CROSSHAIR: \033[1m\e[31mOFF\e[0m\n");
printf("\n");
}
}
/***************************************************
~~ Program Entry Point
*/
int main(int argc, char *argv[])
{
srand(time(0));
// wipe old data
remove("/dev/shm/pred_r.dat");
remove("/dev/shm/pred_input.dat");
// intro
reprint();
// open display 0
d = XOpenDisplay(":0");
if(d == NULL)
{
printf("Failed to open display\n");
return 0;
}
// get default screen
si = XDefaultScreen(d);
// get graphics context
gc = DefaultGC(d, si);
// find window
twin = findWindow(d, 0, "Counter-Strike");
if(twin != 0)
reprint();
//
XEvent event;
memset(&event, 0x00, sizeof(event));
//
uint tc = 0;
while(1)
{
// loop every SCAN_DELAY ms (1,000 microsecond = 1 millisecond)
usleep(SCAN_DELAY);
// bot toggle
if(key_is_pressed(XK_Control_L) && key_is_pressed(XK_Alt_L))
{
if(enable == 0)
{
// get window
twin = findWindow(d, 0, "Counter-Strike");
if(twin == 0)
{
printf("Failed to detect a CS:GO window.\n");
sleep(1);
continue;
}
// get center window point (x & y)
XWindowAttributes attr;
XGetWindowAttributes(d, twin, &attr);
x = attr.width/2;
y = attr.height/2;
// set mouse event
memset(&event, 0x00, sizeof(event));
event.type = ButtonPress;
event.xbutton.button = Button1;
event.xbutton.same_screen = True;
event.xbutton.subwindow = twin;
event.xbutton.window = twin;
enable = 1;
usleep(100000);
reprint();
speakS("on");
}
else
{
enable = 0;
usleep(100000);
reprint();
speakS("off");
}
}
// toggle bot on/off
if(enable == 1)
{
// always tracks sps
static uint64_t st = 0;
if(microtime() - st >= 1000000)
{
if(key_is_pressed(XK_H))
printf("\e[36mSPS: %u\e[0m\n", sps);
sps = 0;
st = microtime();
}
// input toggle
if(key_is_pressed(XK_Control_R) && key_is_pressed(XK_Alt_R))
{
if(hotkeys == 0)
{
hotkeys = 1;
usleep(100000);
reprint();
speakS("hk on");
}
else
{
hotkeys = 0;
usleep(100000);
reprint();
speakS("hk off");
}
}
if(hotkeys == 1)
{
// crosshair toggle
if(key_is_pressed(XK_P))
{
if(crosshair == 0)
{
crosshair = 1;
usleep(100000);
reprint();
speakS("cx on");
}
else
{
crosshair = 0;
usleep(100000);
reprint();
speakS("cx off");
}
}
// sample capture toggle
if(key_is_pressed(XK_L))
{
if(sample_capture == 0)
{
char* home = getenv("HOME");
sprintf(targets_dir, "%s/Desktop/targets", home);
mkdir(targets_dir, 0777);
sample_capture = 1;
usleep(100000);
reprint();
speakS("sc on");
}
else
{
sample_capture = 0;
usleep(100000);
reprint();
speakS("sc off");
}
}
// sample capture
static uint64_t scd = 0;
if(sample_capture == 1 && key_is_pressed(XK_E) && microtime() > scd)
{
char name[32];
sprintf(name, "%s/%i.pgm", targets_dir, rand());
processScanArea(twin);
writePGM(name, &pgmbytes[0]);
printf("\e[93mMANUAL SAVE:\e[38;5;123m %s\n", name);
scd = microtime() + 350000;
}
}
if(hotkeys == 1 && key_is_pressed(XK_G)) // print activation when pressed
{
const float ret = processModel();
if(ret > 0.f)
{
if(ret > ACTIVATION_SENITIVITY)
{
printf("\e[93mA: %f\e[0m\n", ret);
XSetForeground(d, gc, 65280);
XDrawRectangle(d, event.xbutton.window, gc, x-rd2-1, y-rd2-1, r0+2, r0+2);
XSetForeground(d, gc, 0);
XDrawRectangle(d, event.xbutton.window, gc, x-rd2-2, y-rd2-2, r0+4, r0+4);
XFlush(d);
}
else
{
const uint s = (uint)((1.f-ret)*255.f);
printf("\x1b[38;2;255;%u;%um A: %f\n", s, s, ret);
XSetForeground(d, gc, 16711680);
XDrawRectangle(d, event.xbutton.window, gc, x-rd2-1, y-rd2-1, r0+2, r0+2);
XSetForeground(d, gc, 0);
XDrawRectangle(d, event.xbutton.window, gc, x-rd2-2, y-rd2-2, r0+4, r0+4);
XFlush(d);
}
}
}
else
{
if(crosshair == 1)
{
XSetForeground(d, gc, 65280);
XDrawRectangle(d, event.xbutton.window, gc, x-rd2-1, y-rd2-1, r0+2, r0+2);
XSetForeground(d, gc, 0);
XDrawRectangle(d, event.xbutton.window, gc, x-rd2-2, y-rd2-2, r0+4, r0+4);
XFlush(d);
}
if(key_is_pressed(XK_W) == 0 && key_is_pressed(XK_A) == 0 && key_is_pressed(XK_S) == 0 && key_is_pressed(XK_D) == 0 && key_is_pressed(XK_Shift_L) == 0)
{
const float activation = processModel();
// passed minimum activation?
if(activation > ACTIVATION_SENITIVITY)
{
tc++;
// did we activate enough times in a row to be sure this is a target?
if(tc > REPEAT_ACTIVATION)
{
if(sample_capture == 1)
{
char name[32];
sprintf(name, "%s/%i.pgm", targets_dir, rand());
writePGM(name, &pgmbytes[0]);
printf("\e[38;5;123mSAVED: %s\n", name);
}
// fire off as many shots as we need to
for(int i = 0; i < TRIGGER; i++)
{
// fire mouse down
event.type = ButtonPress;
event.xbutton.state = 0;
XSendEvent(d, PointerWindow, True, 0xfff, &event);
XFlush(d);
// wait 100ms (or ban for suspected cheating)
usleep(100000);
// release mouse down
event.type = ButtonRelease;
event.xbutton.state = 0x100;
XSendEvent(d, PointerWindow, True, 0xfff, &event);
XFlush(d);
// fire limit
usleep(TRIGGER_RATE_LIMIT_MS * 1000);
}
// fire limit
usleep(FIRE_RATE_LIMIT_MS * 1000);
}
}
else
{
tc = 0;
}
}
}
///
}
}
// done, never gets here in regular execution flow
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment