├── .DS_Store ├── .gitattributes ├── .idea ├── .gitignore ├── .name ├── FTNAIMZ.iml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── Arduino Sketch ├── FTN-Arduino │ └── FTN-Arduino.ino ├── ImprovedMouse.cpp ├── ImprovedMouse.h └── hidcustom.h ├── README.md ├── __pycache__ ├── capture.cpython-39.pyc ├── fov_window.cpython-39.pyc ├── ftnaimz.cpython-39.pyc └── mouse.cpython-39.pyc ├── capture.py ├── fov_window.py ├── ftnaimz.py ├── main.py └── mouse.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostspaceship/ColorBasedAimbot/79449176df40f7a161147986d869c4ba293c6d85/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.cpp linguist-vendored 2 | *.h linguist-vendored 3 | *.ino linguist-vendored 4 | *.hpp linguist-vendored 5 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | main.py -------------------------------------------------------------------------------- /.idea/FTNAIMZ.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Arduino Sketch/FTN-Arduino/FTN-Arduino.ino: -------------------------------------------------------------------------------- 1 | #ifdef dobogusinclude 2 | #include 3 | #endif 4 | #include 5 | 6 | #include "hidcustom.h" 7 | 8 | signed char delta[3] = {0, 0, 0}; 9 | 10 | void MouseRptParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) 11 | { 12 | MYMOUSEINFO *pmi = (MYMOUSEINFO *)buf; 13 | 14 | if (CHECK_BIT(prevState.mouseInfo.buttons, MOUSE_LEFT) != CHECK_BIT(pmi->buttons, MOUSE_LEFT)) 15 | { 16 | if (CHECK_BIT(pmi->buttons, MOUSE_LEFT)) 17 | Mouse.press(MOUSE_LEFT); 18 | else 19 | Mouse.release(MOUSE_LEFT); 20 | } 21 | 22 | if (CHECK_BIT(prevState.mouseInfo.buttons, MOUSE_RIGHT) != CHECK_BIT(pmi->buttons, MOUSE_RIGHT)) 23 | { 24 | if (CHECK_BIT(pmi->buttons, MOUSE_RIGHT)) 25 | Mouse.press(MOUSE_RIGHT); 26 | else 27 | Mouse.release(MOUSE_RIGHT); 28 | } 29 | 30 | if (CHECK_BIT(prevState.mouseInfo.buttons, MOUSE_MIDDLE) != CHECK_BIT(pmi->buttons, MOUSE_MIDDLE)) 31 | { 32 | if (CHECK_BIT(pmi->buttons, MOUSE_MIDDLE)) 33 | Mouse.press(MOUSE_MIDDLE); 34 | else 35 | Mouse.release(MOUSE_MIDDLE); 36 | } 37 | 38 | if (CHECK_BIT(prevState.mouseInfo.buttons, MOUSE_PREV) != CHECK_BIT(pmi->buttons, MOUSE_PREV)) 39 | { 40 | if (CHECK_BIT(pmi->buttons, MOUSE_PREV)) 41 | Mouse.press(MOUSE_PREV); 42 | else 43 | Mouse.release(MOUSE_PREV); 44 | } 45 | 46 | if (CHECK_BIT(prevState.mouseInfo.buttons, MOUSE_NEXT) != CHECK_BIT(pmi->buttons, MOUSE_NEXT)) 47 | { 48 | if (CHECK_BIT(pmi->buttons, MOUSE_NEXT)) 49 | Mouse.press(MOUSE_NEXT); 50 | else 51 | Mouse.release(MOUSE_NEXT); 52 | } 53 | 54 | if (pmi->dX || pmi->dY) 55 | OnMouseMove(pmi); 56 | 57 | prevState.bInfo[0] = buf[0]; 58 | } 59 | 60 | void MouseRptParser::OnMouseMove(MYMOUSEINFO *mi) 61 | { 62 | delta[0] = mi->dX; 63 | delta[1] = mi->dY; 64 | } 65 | 66 | 67 | #include 68 | 69 | USB Usb; 70 | USBHub Hub(&Usb); 71 | HIDBoot HidMouse(&Usb); 72 | 73 | MouseRptParser Prs; 74 | 75 | void setup() 76 | { 77 | Serial.begin(115200); 78 | Serial.setTimeout(1); 79 | Usb.Init(); 80 | HidMouse.SetReportParser(0, &Prs); 81 | Mouse.begin(); 82 | } 83 | 84 | void loop() 85 | { 86 | delta[0] = 0; 87 | delta[1] = 0; 88 | delta[2] = 0; 89 | Usb.Task(); 90 | 91 | if (Serial.available() > 0) 92 | { 93 | char inChar = Serial.read(); 94 | if (inChar == 'M') 95 | Serial.readBytes((char *)&delta, 2); 96 | else if (inChar == 'C') 97 | Mouse.click(); 98 | } 99 | Mouse.move(delta[0], delta[1], delta[2]); 100 | } -------------------------------------------------------------------------------- /Arduino Sketch/ImprovedMouse.cpp: -------------------------------------------------------------------------------- 1 | #include "ImprovedMouse.h" 2 | 3 | static const uint8_t _hidMultiReportDescriptorMouse[] PROGMEM = { 4 | /* Mouse relative */ 5 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) 54 */ 6 | 0x09, 0x02, /* USAGE (Mouse) */ 7 | 0xa1, 0x01, /* COLLECTION (Application) */ 8 | 0x85, HID_REPORTID_MOUSE, /* REPORT_ID */ 9 | 10 | /* 8 Buttons */ 11 | 0x05, 0x09, /* USAGE_PAGE (Button) */ 12 | 0x19, 0x01, /* USAGE_MINIMUM (Button 1) */ 13 | 0x29, 0x08, /* USAGE_MAXIMUM (Button 8) */ 14 | 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ 15 | 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ 16 | 0x95, 0x08, /* REPORT_COUNT (8) */ 17 | 0x75, 0x01, /* REPORT_SIZE (1) */ 18 | 0x81, 0x02, /* INPUT (Data,Var,Abs) */ 19 | 20 | /* X, Y, Wheel */ 21 | 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ 22 | 0x09, 0x30, /* USAGE (X) */ 23 | 0x09, 0x31, /* USAGE (Y) */ 24 | 0x09, 0x38, /* USAGE (Wheel) */ 25 | 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ 26 | 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ 27 | 0x75, 0x08, /* REPORT_SIZE (8) */ 28 | 0x95, 0x03, /* REPORT_COUNT (3) */ 29 | 0x81, 0x06, /* INPUT (Data,Var,Rel) */ 30 | 31 | /* End */ 32 | 0xc0 /* END_COLLECTION */ 33 | }; 34 | 35 | Mouse_::Mouse_(void) 36 | { 37 | static HIDSubDescriptor node(_hidMultiReportDescriptorMouse, sizeof(_hidMultiReportDescriptorMouse)); 38 | HID().AppendDescriptor(&node); 39 | } 40 | 41 | void Mouse_::begin(void) 42 | { 43 | end(); 44 | } 45 | 46 | void Mouse_::end(void) 47 | { 48 | _buttons = 0; 49 | move(0, 0, 0); 50 | } 51 | 52 | void Mouse_::click(uint8_t b) 53 | { 54 | _buttons = b; 55 | move(0, 0, 0); 56 | _buttons = 0; 57 | move(0, 0, 0); 58 | } 59 | 60 | void Mouse_::move(signed char x, signed char y, signed char wheel) 61 | { 62 | HID_MouseReport_Data_t report; 63 | report.buttons = _buttons; 64 | report.xAxis = x; 65 | report.yAxis = y; 66 | report.wheel = wheel; 67 | SendReport(&report, sizeof(report)); 68 | } 69 | 70 | void Mouse_::buttons(uint8_t b) 71 | { 72 | if (b != _buttons) 73 | { 74 | _buttons = b; 75 | move(0, 0, 0); 76 | } 77 | } 78 | 79 | void Mouse_::press(uint8_t b) 80 | { 81 | buttons(_buttons | b); 82 | } 83 | 84 | void Mouse_::release(uint8_t b) 85 | { 86 | buttons(_buttons & ~b); 87 | } 88 | 89 | void Mouse_::releaseAll(void) 90 | { 91 | _buttons = 0; 92 | move(0, 0, 0); 93 | } 94 | 95 | bool Mouse_::isPressed(uint8_t b) 96 | { 97 | if ((b & _buttons) > 0) 98 | return true; 99 | return false; 100 | } 101 | 102 | void Mouse_::SendReport(void *data, int length) 103 | { 104 | HID().SendReport(HID_REPORTID_MOUSE, data, length); 105 | } 106 | 107 | Mouse_ Mouse; 108 | -------------------------------------------------------------------------------- /Arduino Sketch/ImprovedMouse.h: -------------------------------------------------------------------------------- 1 | 2 | // Include guard 3 | #pragma once 4 | 5 | //================================================================================ 6 | // Settings 7 | //================================================================================ 8 | 9 | #define HID_REPORTID_NONE 0 10 | 11 | #ifndef HID_REPORTID_MOUSE 12 | #define HID_REPORTID_MOUSE 1 13 | #endif 14 | 15 | #ifndef HID_REPORTID_KEYBOARD 16 | #define HID_REPORTID_KEYBOARD 2 17 | #endif 18 | 19 | #ifndef HID_REPORTID_RAWHID 20 | // This will not work properly in most cases. 21 | // The number is just kept from the old number counting. 22 | //#define HID_REPORTID_RAWHID 3 23 | #endif 24 | 25 | #ifndef HID_REPORTID_CONSUMERCONTROL 26 | #define HID_REPORTID_CONSUMERCONTROL 4 27 | #endif 28 | 29 | #ifndef HID_REPORTID_SYSTEMCONTROL 30 | #define HID_REPORTID_SYSTEMCONTROL 5 31 | #endif 32 | 33 | #ifndef HID_REPORTID_GAMEPAD 34 | #define HID_REPORTID_GAMEPAD 6 35 | #endif 36 | 37 | #ifndef HID_REPORTID_MOUSE_ABSOLUTE 38 | #define HID_REPORTID_MOUSE_ABSOLUTE 7 39 | #endif 40 | 41 | #ifndef HID_REPORTID_NKRO_KEYBOARD 42 | #define HID_REPORTID_NKRO_KEYBOARD 8 43 | #endif 44 | 45 | #ifndef HID_REPORTID_TEENSY_KEYBOARD 46 | #define HID_REPORTID_TEENSY_KEYBOARD 9 47 | #endif 48 | 49 | #ifndef HID_REPORTID_SURFACEDIAL 50 | #define HID_REPORTID_SURFACEDIAL 10 51 | #endif 52 | 53 | #if defined(ARDUINO_ARCH_AVR) 54 | 55 | // Use default alignment for AVR 56 | #define ATTRIBUTE_PACKED 57 | 58 | #include "PluggableUSB.h" 59 | 60 | #define EPTYPE_DESCRIPTOR_SIZE uint8_t 61 | 62 | #elif defined(ARDUINO_ARCH_SAM) 63 | 64 | #define ATTRIBUTE_PACKED __attribute__((packed, aligned(1))) 65 | 66 | #include "USB/PluggableUSB.h" 67 | 68 | #define EPTYPE_DESCRIPTOR_SIZE uint32_t 69 | #define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ 70 | UOTGHS_DEVEPTCFG_EPDIR_IN | \ 71 | UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ 72 | UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ 73 | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ 74 | UOTGHS_DEVEPTCFG_ALLOC) 75 | #define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \ 76 | UOTGHS_DEVEPTCFG_EPTYPE_BLK | \ 77 | UOTGHS_DEVEPTCFG_EPBK_1_BANK | \ 78 | UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \ 79 | UOTGHS_DEVEPTCFG_ALLOC) 80 | #define USB_EP_SIZE EPX_SIZE 81 | #define USB_SendControl USBD_SendControl 82 | #define USB_Available USBD_Available 83 | #define USB_Recv USBD_Recv 84 | #define USB_Send USBD_Send 85 | #define USB_Flush USBD_Flush 86 | 87 | #elif defined(ARDUINO_ARCH_SAMD) 88 | 89 | #define ATTRIBUTE_PACKED __attribute__((packed, aligned(1))) 90 | 91 | #define USB_EP_SIZE EPX_SIZE 92 | #define EP_TYPE_INTERRUPT_IN USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0); 93 | #define EP_TYPE_INTERRUPT_OUT USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0); 94 | 95 | #if defined(ARDUINO_API_VERSION) 96 | #include "api/PluggableUSB.h" 97 | #define EPTYPE_DESCRIPTOR_SIZE unsigned int 98 | #else 99 | #include "USB/PluggableUSB.h" 100 | 101 | #define EPTYPE_DESCRIPTOR_SIZE uint32_t 102 | //#define USB_SendControl USBDevice.sendControl -> real C++ functions to take care of PGM overloading 103 | #define USB_Available USBDevice.available 104 | #define USB_Recv USBDevice.recv 105 | #define USB_RecvControl USBDevice.recvControl 106 | #define USB_Send USBDevice.send 107 | #define USB_Flush USBDevice.flush 108 | 109 | int USB_SendControl(void *y, uint8_t z); 110 | int USB_SendControl(uint8_t x, const void *y, uint8_t z); 111 | #endif 112 | 113 | #define TRANSFER_PGM 0 114 | #define TRANSFER_RELEASE 0 115 | 116 | #define HID_REPORT_TYPE_INPUT 1 117 | #define HID_REPORT_TYPE_OUTPUT 2 118 | #define HID_REPORT_TYPE_FEATURE 3 119 | 120 | #else 121 | 122 | #error "Unsupported architecture" 123 | 124 | #endif 125 | 126 | #include 127 | 128 | #define MOUSE_LEFT (1 << 0) 129 | #define MOUSE_RIGHT (1 << 1) 130 | #define MOUSE_MIDDLE (1 << 2) 131 | #define MOUSE_PREV (1 << 3) 132 | #define MOUSE_NEXT (1 << 4) 133 | // actually this mouse report has 8 buttons (for smaller descriptor) 134 | // but the last 3 wont do anything from what I tested 135 | #define MOUSE_ALL (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE | MOUSE_PREV | MOUSE_NEXT) 136 | 137 | typedef union ATTRIBUTE_PACKED 138 | { 139 | // Mouse report: 8 buttons, position, wheel 140 | uint8_t whole8[0]; 141 | uint16_t whole16[0]; 142 | uint32_t whole32[0]; 143 | struct ATTRIBUTE_PACKED 144 | { 145 | uint8_t buttons; 146 | int8_t xAxis; 147 | int8_t yAxis; 148 | int8_t wheel; 149 | }; 150 | } HID_MouseReport_Data_t; 151 | 152 | typedef union ATTRIBUTE_PACKED 153 | { 154 | // BootMouse report: 3 buttons, position 155 | // Wheel is not supported by boot protocol 156 | uint8_t whole8[0]; 157 | uint16_t whole16[0]; 158 | uint32_t whole32[0]; 159 | struct ATTRIBUTE_PACKED 160 | { 161 | uint8_t buttons; 162 | int8_t xAxis; 163 | int8_t yAxis; 164 | }; 165 | } HID_BootMouseReport_Data_t; 166 | 167 | class Mouse_ 168 | { 169 | public: 170 | Mouse_(void); 171 | void begin(void); 172 | void end(void); 173 | void click(uint8_t b = MOUSE_LEFT); 174 | void move(signed char x, signed char y, signed char wheel = 0); 175 | void press(uint8_t b = MOUSE_LEFT); // press LEFT by default 176 | void release(uint8_t b = MOUSE_LEFT); // release LEFT by default 177 | void releaseAll(void); 178 | bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default 179 | 180 | void SendReport(void *data, int length); 181 | 182 | protected: 183 | uint8_t _buttons; 184 | inline void buttons(uint8_t b); 185 | }; 186 | extern Mouse_ Mouse; -------------------------------------------------------------------------------- /Arduino Sketch/hidcustom.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ImprovedMouse.h" 3 | 4 | #define CHECK_BIT(var, pos) ((var)&pos) 5 | 6 | struct MYMOUSEINFO 7 | { 8 | uint8_t buttons; 9 | int8_t dX; 10 | int8_t dY; 11 | int8_t wheel; 12 | }; 13 | 14 | class MouseRptParser : public MouseReportParser 15 | { 16 | union 17 | { 18 | MYMOUSEINFO mouseInfo; 19 | uint8_t bInfo[sizeof(MYMOUSEINFO)]; 20 | } prevState; 21 | 22 | protected: 23 | void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); 24 | 25 | void OnMouseMove(MYMOUSEINFO *mi); 26 | void OnWheelMove(MYMOUSEINFO *mi); 27 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | REQUIRED HARDWARE: 2 | 3 | - ARDUINO LEONARDO 4 | - USB HOST SHIELD 5 | 6 | REQUIRED LIBRARIES: 7 | 8 | - NUMPY 9 | - MSS 10 | - PILLOW 11 | - TERMCOLOR 12 | - PYSERIAL 13 | - KEYBOARD 14 | - OPENCV-PYTHON 15 | - PYWIN32 16 | - PYAUTOGUI 17 | -------------------------------------------------------------------------------- /__pycache__/capture.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostspaceship/ColorBasedAimbot/79449176df40f7a161147986d869c4ba293c6d85/__pycache__/capture.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/fov_window.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostspaceship/ColorBasedAimbot/79449176df40f7a161147986d869c4ba293c6d85/__pycache__/fov_window.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/ftnaimz.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostspaceship/ColorBasedAimbot/79449176df40f7a161147986d869c4ba293c6d85/__pycache__/ftnaimz.cpython-39.pyc -------------------------------------------------------------------------------- /__pycache__/mouse.cpython-39.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lostspaceship/ColorBasedAimbot/79449176df40f7a161147986d869c4ba293c6d85/__pycache__/mouse.cpython-39.pyc -------------------------------------------------------------------------------- /capture.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import time 4 | from mss import mss 5 | import threading 6 | 7 | 8 | class Capture: 9 | def __init__(self, x, y, xfov, yfov): 10 | self.x, self.y, self.xfov, self.yfov = x, y, xfov, yfov 11 | self.screen = np.zeros((xfov, yfov, 3), np.uint8) 12 | self.image = None 13 | self.lock = threading.Lock() 14 | self.capture_thread = threading.Thread(target=self.capture_loop, daemon=True) 15 | self.capture_thread.start() 16 | self.start_time = time.time() 17 | self.frame_count = 0 18 | 19 | def capture_loop(self): 20 | while True: 21 | with self.lock: 22 | self.capture_screen() 23 | self.update_fps() 24 | 25 | def capture_screen(self): 26 | with mss() as sct: 27 | monitor = sct.monitors[0] 28 | top, left = monitor["top"] + self.y, monitor["left"] + self.x 29 | monitor = {"top": self.y, "left": self.x, "width": self.xfov, "height": self.yfov, "monitor": 0} 30 | self.image = sct.grab(monitor) 31 | self.screen = np.array(self.image) 32 | 33 | def update_fps(self): 34 | self.frame_count += 1 35 | elapsed_time = time.time() - self.start_time 36 | if elapsed_time >= 1: 37 | fps = self.frame_count / elapsed_time 38 | print(f" - FPS: {fps:.0f}", end="\r") 39 | self.frame_count = 0 40 | self.start_time = time.time() 41 | 42 | def get_screen(self): 43 | with self.lock: 44 | return self.screen 45 | -------------------------------------------------------------------------------- /fov_window.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import threading 4 | 5 | LOWER_COLOR = np.array([140, 111, 160]) 6 | UPPER_COLOR = np.array([148, 154, 194]) 7 | 8 | 9 | def show_detection_window(grabber, window_toggled): 10 | while window_toggled(): 11 | screen = grabber.get_screen() 12 | hsv = cv2.cvtColor(screen, cv2.COLOR_BGR2HSV) 13 | 14 | mask = cv2.inRange(hsv, LOWER_COLOR, UPPER_COLOR) 15 | highlighted = cv2.bitwise_and(screen, screen, mask=mask) 16 | blurred = cv2.GaussianBlur(highlighted, (0, 0), sigmaX=1, sigmaY=1) 17 | dimmed = cv2.addWeighted(screen, 0.1, np.zeros(screen.shape, dtype=screen.dtype), 0, 0) 18 | result = cv2.add(blurred, dimmed) 19 | 20 | if screen.shape[0] < 500 or screen.shape[1] < 500: 21 | result_resized = cv2.resize(result, (500, 500)) 22 | else: 23 | result_resized = result 24 | 25 | cv2.imshow('DETECTION WINDOW FOR FTNAIMZ', result_resized) 26 | 27 | if cv2.waitKey(1) & 0xFF == ord('q'): 28 | break 29 | cv2.destroyAllWindows() 30 | 31 | 32 | def toggle_window(ftnaim): 33 | ftnaim.window_toggled = not ftnaim.window_toggled 34 | 35 | if ftnaim.window_toggled: 36 | threading.Thread(target=show_detection_window, args=(ftnaim.grabber, lambda: ftnaim.window_toggled), 37 | daemon=True).start() -------------------------------------------------------------------------------- /ftnaimz.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import threading 4 | import time 5 | import win32api 6 | 7 | from capture import Capture 8 | from mouse import ArduinoMouse 9 | from fov_window import toggle_window 10 | 11 | 12 | class Ftnaim: 13 | LOWER_COLOR = np.array([140, 120, 180]) 14 | UPPER_COLOR = np.array([160, 200, 255]) 15 | 16 | def __init__(self, x, y, xfov, yfov, FLICKSPEED, MOVESPEED): 17 | self.arduinomouse = ArduinoMouse() 18 | self.grabber = Capture(x, y, xfov, yfov) 19 | self.flickspeed = FLICKSPEED 20 | self.movespeed = MOVESPEED 21 | threading.Thread(target=self.listen, daemon=True).start() 22 | self.toggled = False 23 | self.window_toggled = False 24 | 25 | def toggle(self): 26 | self.toggled = not self.toggled 27 | time.sleep(0.2) 28 | 29 | def listen(self): 30 | while True: 31 | if win32api.GetAsyncKeyState(0x71) < 0: 32 | toggle_window(self) 33 | time.sleep(0.2) 34 | if win32api.GetAsyncKeyState(0x02) < 0 and self.toggled: 35 | self.process("move") 36 | elif win32api.GetAsyncKeyState(0x12) < 0 and self.toggled: 37 | self.process("click") 38 | 39 | def process(self, action): 40 | screen = self.grabber.get_screen() 41 | hsv = cv2.cvtColor(screen, cv2.COLOR_BGR2HSV) 42 | mask = cv2.inRange(hsv, self.LOWER_COLOR, self.UPPER_COLOR) 43 | dilated = cv2.dilate(mask, None, iterations=5) 44 | contours, _ = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 45 | 46 | if not contours: 47 | return 48 | 49 | contour = max(contours, key=cv2.contourArea) 50 | x, y, w, h = cv2.boundingRect(contour) 51 | center = (x + w // 2, y + h // 2) 52 | y_offset = int(h * 0.3) 53 | 54 | if action == "move": 55 | cX = center[0] 56 | cY = y + y_offset 57 | x_diff = cX - self.grabber.xfov // 2 58 | y_diff = cY - self.grabber.yfov // 2 59 | self.arduinomouse.move(x_diff * self.movespeed, y_diff * self.movespeed) 60 | 61 | elif action == "click" and abs(center[0] - self.grabber.xfov // 2) <= 4 and abs( 62 | center[1] - self.grabber.yfov // 2) <= 10: 63 | self.arduinomouse.click() -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import keyboard 4 | import pyautogui 5 | from termcolor import colored 6 | from ftnaimz import Ftnaim 7 | 8 | # Settings 9 | TOGGLE_KEY = 'F1' # Toggle on/off FTNAIM key 10 | XFOV = 100 # X-Axis FOV 11 | YFOV = 50 # Y-Axis FOV 12 | FLICKSPEED = 1.07437623 # Default flick speed 13 | MOVESPEED = 1 / 5 # Default move speed 14 | 15 | monitor = pyautogui.size() 16 | CENTER_X, CENTER_Y = monitor.width // 2, monitor.height // 2 17 | 18 | senstitle = colored(''' 19 | ░██████╗███████╗███╗░░██╗░██████╗░█████╗░ 20 | ██╔════╝██╔════╝████╗░██║██╔════╝██╔══██╗ 21 | ╚█████╗░█████╗░░██╔██╗██║╚█████╗░╚═╝███╔╝ 22 | ░╚═══██╗██╔══╝░░██║╚████║░╚═══██╗░░░╚══╝░ 23 | ███████╔╝███████╗██║░╚███║██████╔╝░░░██╗░░ 24 | ╚═════╝░╚══════╝╚═╝░░╚══╝╚═════╝░░░░╚═╝░░ 25 | ''', 'magenta') 26 | 27 | ftntitle = colored(''' 28 | ███████╗████████╗███╗░░██╗ ░▄▄▄▄░ ░█████╗░██╗███╗░░░███╗███████╗ 29 | ██╔════╝╚══██╔══╝████╗░██║ ▀▀▄██► ██╔══██╗██║████╗░████║╚════██║ 30 | █████╗░░░░░██║░░░██╔██╗██║ ▀▀███► ███████║██║██╔████╔██║░░███╔═╝ 31 | ██╔══╝░░░░░██║░░░██║╚████║ ░▀███►░█► ██╔══██║██║██║╚██╔╝██║██╔══╝░░ 32 | ██║░░░░░░░░██║░░░██║░╚███║ ▒▄████▀▀ ██║░░██║██║██║░╚═╝░██║███████╗ 33 | ╚═╝░░░░░░░░╚═╝░░░╚═╝░░╚══╝ ╚═╝░░╚═╝╚═╝╚═╝░░░░░╚═╝╚══════╝ 34 | FTN AIMZ - v1.0''', 'magenta') 35 | 36 | 37 | def calculate_settings(sensitivity): 38 | global FLICKSPEED, MOVESPEED 39 | FLICKSPEED = 1.07437623 * (sensitivity ** -0.9936827126) # Calculate flick speed 40 | MOVESPEED = 1 / (5 * sensitivity) # Calculate move speed 41 | 42 | 43 | def main(): 44 | os.system('title ftnaimbot') 45 | 46 | print(senstitle) 47 | sensitivity = float(input(colored("Enter your sensitivity: ", 'magenta'))) 48 | calculate_settings(sensitivity) 49 | 50 | os.system("cls") 51 | 52 | ftnaimbot = Ftnaim(CENTER_X - XFOV // 2, CENTER_Y - YFOV // 2, XFOV, YFOV, FLICKSPEED, MOVESPEED) 53 | 54 | print(ftntitle) 55 | print(colored('Discord:', 'magenta'), colored('lostspaceship', 'magenta')) 56 | print(colored('GitHub:', 'magenta'), end=' ') 57 | print(colored('https://github.com/lostspaceship', 'magenta', attrs=['underline'])) 58 | 59 | print() 60 | print(colored('[Info]', 'magenta'), colored('Set enemies to', 'white'), colored('Purple', 'magenta')) 61 | print(colored('[Info]', 'magenta'), colored(f'Press {TOGGLE_KEY} to toggle FTN AIM', 'white')) 62 | print(colored('[Info]', 'magenta'), colored(f'Press F2 to toggle Detection Window', 'white')) 63 | print(colored('[Info]', 'magenta'), colored('RightMB', 'magenta'), colored('= Aimbot', 'white')) 64 | print(colored('[Info]', 'magenta'), colored('LeftAlt', 'magenta'), colored('= Triggerbot', 'white')) 65 | status = 'Disabled' 66 | 67 | try: 68 | while True: 69 | if keyboard.is_pressed(TOGGLE_KEY): 70 | ftnaimbot.toggle() 71 | status = 'Enabled ' if ftnaimbot.toggled else 'Disabled' 72 | print(f'\r{colored("[Status]", "magenta")} {colored(status, "white")}', end='') 73 | time.sleep(0.01) 74 | except (KeyboardInterrupt, SystemExit): 75 | print(colored('\n[Info]', 'magenta'), colored('Exiting...', 'white') + '\n') 76 | finally: 77 | ftnaimbot.close() 78 | 79 | 80 | if __name__ == '__main__': 81 | main() -------------------------------------------------------------------------------- /mouse.py: -------------------------------------------------------------------------------- 1 | import serial 2 | import serial.tools.list_ports 3 | import random 4 | import time 5 | import sys 6 | from termcolor import colored 7 | 8 | 9 | class ArduinoMouse: 10 | def __init__(self, filter_length=3): 11 | self.serial_port = serial.Serial() 12 | self.serial_port.baudrate = 115200 13 | self.serial_port.timeout = 1 14 | self.serial_port.port = self.find_serial_port() 15 | self.filter_length = filter_length 16 | self.x_history = [0] * filter_length 17 | self.y_history = [0] * filter_length 18 | try: 19 | self.serial_port.open() 20 | except serial.SerialException: 21 | print(colored('[Error]', 'red'), colored( 22 | 'FTNAIMZ is already open or serial port in use by another app. Close FTNAIMZ and other apps before retrying.', 23 | 'white')) 24 | time.sleep(10) 25 | sys.exit() 26 | 27 | def find_serial_port(self): 28 | port = next((port for port in serial.tools.list_ports.comports() if "Arduino" in port.description), None) 29 | if port is not None: 30 | return port.device 31 | else: 32 | print(colored('[Error]', 'red'), colored( 33 | 'Unable to find serial port or the Arduino device is with different name. Please check its connection and try again.', 34 | 'white')) 35 | time.sleep(10) 36 | sys.exit() 37 | 38 | def move(self, x, y): 39 | self.x_history.append(x) 40 | self.y_history.append(y) 41 | 42 | self.x_history.pop(0) 43 | self.y_history.pop(0) 44 | 45 | smooth_x = int(sum(self.x_history) / self.filter_length) 46 | smooth_y = int(sum(self.y_history) / self.filter_length) 47 | 48 | finalx = smooth_x + 256 if smooth_x < 0 else smooth_x 49 | finaly = smooth_y + 256 if smooth_y < 0 else smooth_y 50 | self.serial_port.write(b"M" + bytes([int(finalx), int(finaly)])) 51 | 52 | def flick(self, x, y): 53 | x = x + 256 if x < 0 else x 54 | y = y + 256 if y < 0 else y 55 | self.serial_port.write(b"M" + bytes([int(x), int(y)])) 56 | 57 | def click(self): 58 | delay = random.uniform(0.01, 0.1) 59 | self.serial_port.write(b"C") 60 | time.sleep(delay) 61 | 62 | def close(self): 63 | self.serial_port.close() 64 | 65 | def __del__(self): 66 | self.close() --------------------------------------------------------------------------------