Josiahiscool73

ai aimbot(xcloud)

Jul 21st, 2025 (edited)
906
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 56.07 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Fortnite xCloud Precision Aimbot (MoveNet) - ud
  3. // @description AI-powered aimbot for Fortnite on xCloud with MoveNet pose detection.
  4. // @author Improved Version / Community
  5. // @version 4.2.18
  6. // @match *://*.xbox.com/play/*
  7. // @grant none
  8. // @run-at document-end
  9. // @require https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf-core.min.js
  10. // @require https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf-converter.min.js
  11. // @require https://cdn.jsdelivr.net/npm/@tensorflow/[email protected]/dist/tf-backend-webgl.min.js
  12. // @require https://cdn.jsdelivr.net/npm/@tensorflow-models/[email protected]/dist/pose-detection.min.js
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. // === Configuration Section ===
  19. // This section contains all customizable settings for the aimbot.
  20. // Each option is documented with its purpose, valid values, and how to adjust it.
  21.  
  22. const config = {
  23. // Detection settings for MoveNet AI model
  24. detection: {
  25. enabled: true, // Set to false to disable AI detection (aimbot visuals only)
  26. modelType: poseDetection.SupportedModels.MoveNet, // Do not change unless using a different model
  27. detectorConfig: {
  28. modelType: poseDetection.movenet.modelType.SINGLEPOSE_LIGHTNING, // Model type: SINGLEPOSE_LIGHTNING (fast) or SINGLEPOSE_THUNDER (accurate)
  29. enableSmoothing: true, // Smooths pose detection for less jitter (true/false)
  30. minPoseScore: 0.25 // Minimum confidence score for a detected pose (0.0 to 1.0, lower = more detections)
  31. },
  32. keypointConfidence: 0.20, // Minimum confidence for individual keypoints (0.0 to 1.0, lower = more points detected)
  33. maxDetections: 5, // Maximum number of players to detect (1 to 10, higher = more CPU usage)
  34. processingInterval: 30, // Minimum time (ms) between detection runs (10 to 100, lower = faster but more CPU)
  35. skipFrames: 1, // Number of frames to skip between detections (0 to 5, 0 = no skip, higher = less CPU usage)
  36. // Example: To reduce CPU usage, increase skipFrames to 2 or 3
  37. useWebGL2: true, // Use WebGL2 for faster processing (true/false, false may improve compatibility)
  38. ignoreSelfRegion: {
  39. enabled: true, // Ignore the player's own character in detection (true/false)
  40. xPercent: 0.00, // X position of ignore region (% of video width, 0.0 to 1.0)
  41. yPercent: 0.27, // Y position of ignore region (% of video height, 0.0 to 1.0)
  42. widthPercent: 0.37, // Width of ignore region (% of video width, 0.0 to 1.0)
  43. heightPercent: 0.74 // Height of ignore region (% of video height, 0.0 to 1.0)
  44. // Adjust these to cover your character's position on screen
  45. }
  46. },
  47. // Game interaction settings
  48. game: {
  49. videoSelector: 'video[aria-label="Game Stream for unknown title"]', // HTML selector for game video (do not change unless xCloud changes)
  50. containerSelector: '#game-stream', // HTML selector for game container (do not change unless xCloud changes)
  51. recoilCompensation: true, // Enable manual recoil compensation (true/false)
  52. recoilLevel: 1, // Recoil strength level (1 to 5, higher = stronger compensation)
  53. // Example: Set recoilLevel to 3 for weapons with moderate recoil
  54. recoilPatterns: {
  55. 1: { vertical: 0.1, horizontal: 0.02, recoverySpeed: 0.25 },
  56. 2: { vertical: 0.2, horizontal: 0.04, recoverySpeed: 0.20 },
  57. 3: { vertical: 0.3, horizontal: 0.06, recoverySpeed: 0.15 },
  58. 4: { vertical: 0.5, horizontal: 0.1, recoverySpeed: 0.12 },
  59. 5: { vertical: 0.7, horizontal: 0.15, recoverySpeed: 0.10 }
  60. // Adjust vertical/horizontal for recoil strength, recoverySpeed for how fast it resets (0.0 to 1.0)
  61. },
  62. autoShoot: true, // Automatically shoot when target is in range (true/false)
  63. triggerOptions: {
  64. delayBeforeShoot: 10, // Delay (ms) before auto-shooting (0 to 100)
  65. burstMode: false, // Enable burst fire mode (true/false)
  66. burstCount: 3, // Number of shots per burst (1 to 10)
  67. burstInterval: 100 // Time (ms) between burst shots (50 to 500)
  68. },
  69. controlOptions: {
  70. crouchOnShoot: false, // Crouch when shooting (true/false)
  71. crouchKey: 'KeyC', // Key for crouching (e.g., 'KeyC' for C key, see https://keycode.info)
  72. reloadKey: 'KeyR', // Key for reloading (e.g., 'KeyR' for R key)
  73. weaponKeys: ['Digit1', 'Digit2', 'Digit3', 'Digit4', 'Digit5'] // Keys for weapon slots (e.g., 'Digit1' for 1 key)
  74. // Example: Change crouchKey to 'KeyX' to use X for crouching
  75. }
  76. },
  77. // Aiming settings
  78. aim: {
  79. activationKey: 'KeyE', // Key to activate aimbot (e.g., 'KeyE' for E key, 'KeyQ' for Q, etc.)
  80. // Example: Change to 'KeyQ' to use Q key for aiming
  81. fovRadius: 250, // Field of view radius (pixels) for target detection (100 to 1000, larger = wider range)
  82. instantLock: true, // Instantly lock onto target (true/false, false = smoother but slower)
  83. aimPoint: "torso_center", // Target body part: "torso_center", "head", "neck", or "center"
  84. headOffset: 0.15, // Vertical offset for head aiming (% of bounding box height, 0.0 to 1.0)
  85. bodyOffset: 0.4, // Vertical offset for torso/center aiming (% of bounding box height, 0.0 to 1.0)
  86. targetPriority: "center", // Target selection priority: "center" (screen center), "crosshair" (mouse), "distance", or "size"
  87. targetSwitchCooldown: 250, // Time (ms) before switching targets (100 to 1000, higher = less frequent switches)
  88. triggerThreshold: 0.7, // Auto-shoot distance threshold (% of fovRadius, 0.0 to 1.0, lower = closer range)
  89. smoothing: {
  90. enabled: false, // Smooth aim movement (true/false)
  91. amount: 0.15, // Smoothing strength (0.0 to 1.0, higher = smoother but slower)
  92. extrapolation: false // Predict target movement (true/false, experimental)
  93. },
  94. snapOptions: {
  95. strength: 1, // Snap strength (0.0 to 1.0, higher = faster snap)
  96. threshold: 0.9, // Snap activation threshold (0.0 to 1.0, lower = easier snap)
  97. diminishingRange: false // Reduce snap strength at edges (true/false)
  98. }
  99. },
  100. // Visual overlay settings
  101. visual: {
  102. showDebugInfo: true, // Show debug info on screen (true/false)
  103. crosshair: {
  104. enabled: true, // Show crosshair (true/false)
  105. style: 'dot', // Crosshair style: 'dot', 'cross', or 'circle'
  106. color: 'lime', // Crosshair color (e.g., 'lime', 'red', '#FF0000')
  107. size: 3, // Crosshair size (pixels, 1 to 10)
  108. centerOnGameScreen: true // Center crosshair on game screen (true) or mouse (false)
  109. },
  110. boundingBoxes: { enabled: false }, // Show bounding boxes around targets (true/false)
  111. keypoints: {
  112. enabled: true, // Show keypoint dots on targets (true/false)
  113. color: 'cyan', // Keypoint color
  114. radius: 3 // Keypoint size (pixels, 1 to 10)
  115. },
  116. skeleton: {
  117. enabled: true, // Show skeleton lines on targets (true/false)
  118. color: 'rgba(255, 0, 255, 0.9)', // Skeleton color
  119. lineWidth: 2 // Skeleton line thickness (pixels, 1 to 5)
  120. },
  121. targetLock: {
  122. enabled: true, // Show lock-on indicator (true/false)
  123. color: 'yellow', // Indicator color
  124. style: 'corners' // Indicator style: 'corners', 'full', or 'crosshair'
  125. },
  126. fovCircle: {
  127. enabled: true, // Show FOV circle (true/false)
  128. color: 'rgba(255,255,255,0.3)', // Circle color
  129. lineWidth: 1, // Circle thickness (pixels, 1 to 5)
  130. centerOnGameScreen: true, // Center on game screen (true) or mouse (false)
  131. showOnlyWhenAiming: true // Show only when aim key is held (true/false)
  132. },
  133. performanceMetrics: {
  134. enabled: true, // Show FPS and detection time (true/false)
  135. position: 'top-left' // Position: 'top-left', 'top-right', 'bottom-left', 'bottom-right'
  136. },
  137. drawIgnoreRegion: {
  138. enabled: true, // Show ignore region rectangle (true/false)
  139. color: 'rgba(50, 50, 50, 0.4)', // Region color
  140. lineWidth: 1, // Border thickness (pixels, 0 to 5, 0 = no border)
  141. showOnlyWhenAiming: true // Show only when aim key is held (true/false)
  142. },
  143. showRecoilTunerGUI: false // Show on-screen recoil tuning GUI (true/false)
  144. }
  145. };
  146. config.version = '4.2.18'; // Script version (do not change)
  147.  
  148. // === ASCII Art Separator ===
  149. // This visually separates configuration from debugging for clarity
  150. /*
  151. _____ _______ _______
  152. | __ \__ __|__ __|
  153. | |__) | | | | |
  154. | _ / | | | |
  155. | | \ \ | | | |
  156. |_| \_\ |_| |_|
  157.  
  158. Configuration above, Debugging below
  159. */
  160.  
  161. // === Debugging and State Management ===
  162. // This section handles internal state and logging. Modify only if you know what you're doing.
  163.  
  164. const tfState = {
  165. backend: 'webgl', // TensorFlow backend (do not change)
  166. flags: { WEBGL_VERSION: 2, WEBGL_RENDER_FLOAT32_ENABLED: true } // WebGL settings
  167. };
  168.  
  169. const state = {
  170. gameVideo: null, // Game video element
  171. detectionModel: null, // MoveNet model
  172. modelLoaded: false, // Model load status
  173. currentTarget: null, // Current aim target
  174. lastTargetSwitch: 0, // Time of last target switch
  175. frameCount: 0, // Frame counter
  176. lastDetectionTime: 0, // Last detection timestamp
  177. performance: {
  178. fps: 0, // Current FPS
  179. framesThisSecond: 0, // Frames in current second
  180. lastFpsUpdate: 0, // Last FPS update time
  181. detectionTime: 0, // Last detection duration
  182. avgDetectionTime: 0, // Average detection duration
  183. detectionTimeHistory: [] // Detection time history
  184. },
  185. ui: {
  186. overlayCanvas: null, // Overlay canvas
  187. overlayCtx: null, // Overlay context
  188. offscreenCanvas: null, // Offscreen canvas for ignore region
  189. offscreenCtx: null // Offscreen context
  190. },
  191. input: {
  192. lastMouseX: window.innerWidth / 2, // Last mouse X position
  193. lastMouseY: window.innerHeight / 2, // Last mouse Y position
  194. leftButtonDown: false, // Left mouse button state
  195. rightButtonDown: false, // Right mouse button state
  196. activeKeys: new Set() // Active keys
  197. },
  198. recoilState: {
  199. active: false, // Recoil compensation active
  200. offsetX: 0, // Recoil X offset
  201. offsetY: 0, // Recoil Y offset
  202. shotsFired: 0, // Shots fired in current burst
  203. lastShotTime: 0, // Last shot timestamp
  204. lastLeftButtonState: false // Last left button state
  205. },
  206. isShooting: false, // Shooting status
  207. currentWeapon: 0 // Current weapon slot
  208. };
  209.  
  210. const debug = {
  211. log: (...args) => console.log(`[AimbotV${config.version}-MoveNet]`, ...args),
  212. warn: (...args) => console.warn(`[AimbotV${config.version}-MoveNet]`, ...args),
  213. error: (...args) => console.error(`[AimbotV${config.version}-MoveNet]`, ...args)
  214. };
  215.  
  216. // === Utility Functions ===
  217. // These functions handle notifications, TensorFlow setup, and model loading.
  218.  
  219. // Displays on-screen notifications
  220. function showNotification(message, type = 'info', duration = 3000) {
  221. const n = document.createElement('div');
  222. n.style.cssText = `position:fixed;top:20px;left:50%;transform:translateX(-50%);padding:10px 20px;border-radius:5px;color:white;z-index:1000000;font-family:sans-serif;font-size:16px;box-shadow:0 2px 10px rgba(0,0,0,0.2);background-color:${type === 'error' ? 'rgba(255,0,0,0.8)' : type === 'warning' ? 'rgba(255,165,0,0.8)' : 'rgba(0,0,0,0.7)'};`;
  223. n.textContent = message;
  224. document.body.appendChild(n);
  225. setTimeout(() => n.remove(), duration);
  226. }
  227.  
  228. // Sets up TensorFlow.js
  229. async function setupTensorFlow() {
  230. try {
  231. debug.log("Configuring TF.js...");
  232. await tf.setBackend(tfState.backend);
  233. await tf.ready();
  234. for (const f in tfState.flags) tf.env().set(f, tfState.flags[f]);
  235. debug.log(`TF.js backend: ${tf.getBackend()}`);
  236. if (tf.getBackend() === 'webgl') debug.log(`WebGL Version: ${tf.env().get('WEBGL_VERSION')}`);
  237. const sT = performance.now();
  238. const tT = tf.zeros([100, 100, 3]);
  239. await tT.data();
  240. tT.dispose();
  241. debug.log(`TF basic op test: ${(performance.now() - sT).toFixed(2)}ms`);
  242. return true;
  243. } catch (e) {
  244. debug.error("TF setup failed:", e);
  245. return false;
  246. }
  247. }
  248.  
  249. // Loads the MoveNet model
  250. async function loadDetectionModel() {
  251. debug.log("Loading MoveNet model...");
  252. try {
  253. if (!await setupTensorFlow()) throw Error("TF setup failed");
  254. if (typeof poseDetection === "undefined") throw Error("Pose Detection API not loaded.");
  255. state.detectionModel = await poseDetection.createDetector(config.detection.modelType, config.detection.detectorConfig);
  256. const tC = document.createElement('canvas');
  257. tC.width = 192;
  258. tC.height = 192;
  259. await state.detectionModel.estimatePoses(tC);
  260. state.modelLoaded = true;
  261. debug.log("MoveNet model loaded!");
  262. showNotification("AI Model (MoveNet) Loaded!", "info");
  263. return true;
  264. } catch (e) {
  265. debug.error("Failed to load MoveNet model:", e);
  266. showNotification("Error loading AI model (MoveNet)! Check console.", "error");
  267. return false;
  268. }
  269. }
  270.  
  271. // === Detection and Targeting Functions ===
  272. // These functions handle player detection and aim target calculation.
  273.  
  274. // Calculates bounding box from keypoints
  275. function calculateBoundingBoxFromKeypoints(kps) {
  276. if (!kps || kps.length === 0) return null;
  277. let mX = Infinity, mY = Infinity, mAX = -Infinity, mAY = -Infinity, vK = 0;
  278. kps.forEach(k => {
  279. if (k.score && k.score >= config.detection.keypointConfidence) {
  280. mX = Math.min(mX, k.x);
  281. mY = Math.min(mY, k.y);
  282. mAX = Math.max(mAX, k.x);
  283. mAY = Math.max(mAY, k.y);
  284. vK++;
  285. }
  286. });
  287. if (vK < 5) return null;
  288. const w = mAX - mX, h = mAY - mY, pX = 0.1 * w, pY = 0.1 * h;
  289. return { x: Math.max(0, mX - pX), y: Math.max(0, mY - pY), width: mAX - mX + 2 * pX, height: mAY - mY + 2 * pY, validKeypoints: vK };
  290. }
  291.  
  292. // Calculates aim target position
  293. function calculateAimTarget(pred, vRect) {
  294. const [vBx, vBy, vBw, vBh] = pred.bbox;
  295. const sBx = vRect.left + vBx / state.gameVideo.videoWidth * vRect.width;
  296. const sBy = vRect.top + vBy / state.gameVideo.videoHeight * vRect.height;
  297. const sBw = vBw / state.gameVideo.videoWidth * vRect.width;
  298. const sBh = vBh / state.gameVideo.videoHeight * vRect.height;
  299. let tX, tY;
  300. const kps = pred.keypoints;
  301. const gK = n => kps.find(k => k.name === n && k.score >= config.detection.keypointConfidence);
  302. switch (config.aim.aimPoint) {
  303. case "head":
  304. const n = gK('nose'), lE = gK('left_eye'), rE = gK('right_eye');
  305. if (n) {
  306. tX = vRect.left + n.x / state.gameVideo.videoWidth * vRect.width;
  307. tY = vRect.top + n.y / state.gameVideo.videoHeight * vRect.height;
  308. } else if (lE && rE) {
  309. tX = vRect.left + ((lE.x + rE.x) / 2) / state.gameVideo.videoWidth * vRect.width;
  310. tY = vRect.top + ((lE.y + rE.y) / 2) / state.gameVideo.videoHeight * vRect.height;
  311. } else {
  312. tX = sBx + sBw / 2;
  313. tY = sBy + sBh * config.aim.headOffset;
  314. }
  315. break;
  316. case "neck":
  317. const lS_n = gK('left_shoulder'), rS_n = gK('right_shoulder');
  318. if (lS_n && rS_n) {
  319. tX = vRect.left + ((lS_n.x + rS_n.x) / 2) / state.gameVideo.videoWidth * vRect.width;
  320. tY = vRect.top + ((lS_n.y + rS_n.y) / 2 - vBh * 0.05) / state.gameVideo.videoHeight * vRect.height;
  321. } else {
  322. tX = sBx + sBw / 2;
  323. tY = sBy + sBh * (config.aim.headOffset + 0.1);
  324. }
  325. break;
  326. case "torso_center":
  327. const lS_t = gK('left_shoulder'), rS_t = gK('right_shoulder'), lH_t = gK('left_hip'), rH_t = gK('right_hip');
  328. if (lS_t && rS_t && lH_t && rH_t) {
  329. tX = vRect.left + (((lS_t.x + rS_t.x) / 2 + (lH_t.x + rH_t.x) / 2) / 2) / state.gameVideo.videoWidth * vRect.width;
  330. tY = vRect.top + (((lS_t.y + rS_t.y) / 2 + (lH_t.y + rH_t.y) / 2) / 2) / state.gameVideo.videoHeight * vRect.height;
  331. } else {
  332. tX = sBx + sBw / 2;
  333. tY = sBy + sBh * config.aim.bodyOffset;
  334. }
  335. break;
  336. case "center":
  337. default:
  338. tX = sBx + sBw / 2;
  339. tY = sBy + sBh / 2;
  340. break;
  341. }
  342. return { x: tX, y: tY, width: sBw, height: sBh, bboxRaw: pred.bbox, keypoints: pred.keypoints };
  343. }
  344.  
  345. // Finds the best target based on priority
  346. function findBestTarget(predictions) {
  347. if (!predictions || predictions.length === 0 || !state.gameVideo) return null;
  348. const videoRect = state.gameVideo.getBoundingClientRect();
  349. if (!videoRect || videoRect.width === 0) return null;
  350. const gameScreenCenterX = videoRect.left + videoRect.width / 2;
  351. const gameScreenCenterY = videoRect.top + videoRect.height / 2;
  352. let bestTarget = null;
  353. let bestScore = Infinity;
  354. predictions.forEach(prediction => {
  355. const targetInfo = calculateAimTarget(prediction, videoRect);
  356. let referenceX, referenceY;
  357. if (config.aim.targetPriority === "center") {
  358. referenceX = gameScreenCenterX;
  359. referenceY = gameScreenCenterY;
  360. } else {
  361. referenceX = state.input.lastMouseX;
  362. referenceY = state.input.lastMouseY;
  363. }
  364. const dx = targetInfo.x - referenceX;
  365. const dy = targetInfo.y - referenceY;
  366. const distanceToPriorityPoint = Math.sqrt(dx * dx + dy * dy);
  367. let fovCenterX = config.visual.fovCircle.centerOnGameScreen && videoRect ? gameScreenCenterX : state.input.lastMouseX;
  368. let fovCenterY = config.visual.fovCircle.centerOnGameScreen && videoRect ? gameScreenCenterY : state.input.lastMouseY;
  369. const dx_fov = targetInfo.x - fovCenterX;
  370. const dy_fov = targetInfo.y - fovCenterY;
  371. if (Math.sqrt(dx_fov * dx_fov + dy_fov * dy_fov) > config.aim.fovRadius) return;
  372. let score;
  373. switch (config.aim.targetPriority) {
  374. case "size":
  375. score = targetInfo.width * targetInfo.height > 0 ? 1 / (targetInfo.width * targetInfo.height) : Infinity;
  376. break;
  377. case "distance":
  378. case "center":
  379. case "crosshair":
  380. default:
  381. score = distanceToPriorityPoint;
  382. break;
  383. }
  384. if (score < bestScore) {
  385. bestScore = score;
  386. bestTarget = { prediction, screenPosition: targetInfo, distance: distanceToPriorityPoint, score: prediction.score };
  387. }
  388. });
  389. return bestTarget;
  390. }
  391.  
  392. // === Input Controller ===
  393. // Handles mouse and keyboard input simulation.
  394.  
  395. const InputController = {
  396. init() {
  397. state.input.lastMouseX = window.innerWidth / 2;
  398. state.input.lastMouseY = window.innerHeight / 2;
  399. document.addEventListener('mousemove', e => {
  400. state.input.lastMouseX = e.clientX;
  401. state.input.lastMouseY = e.clientY;
  402. });
  403. this.setupKeyMonitoring();
  404. debug.log("Input controller initialized");
  405. return true;
  406. },
  407. setupKeyMonitoring() {
  408. document.addEventListener('keydown', e => {
  409. state.input.activeKeys.add(e.code);
  410. if (e.code === config.game.controlOptions.crouchKey) debug.log(`Crouch key pressed (${e.code})`);
  411. if (e.code === config.aim.activationKey) debug.log(`Aim activation key (${e.code}) pressed.`);
  412. config.game.controlOptions.weaponKeys.forEach((k, i) => {
  413. if (e.code === k) {
  414. state.currentWeapon = i;
  415. debug.log(`Switched to weapon slot ${i + 1}`);
  416. }
  417. });
  418. });
  419. document.addEventListener('keyup', e => {
  420. state.input.activeKeys.delete(e.code);
  421. if (e.code === config.aim.activationKey) debug.log(`Aim activation key (${e.code}) released.`);
  422. });
  423. document.addEventListener('mousedown', e => {
  424. if (e.button === 0) state.input.leftButtonDown = true;
  425. if (e.button === 2) state.input.rightButtonDown = true;
  426. });
  427. document.addEventListener('mouseup', e => {
  428. if (e.button === 0) state.input.leftButtonDown = false;
  429. if (e.button === 2) state.input.rightButtonDown = false;
  430. });
  431. },
  432. moveMouseTo(tSX, tSY) {
  433. if (!state.gameVideo) return;
  434. const vR = state.gameVideo.getBoundingClientRect();
  435. if (!vR || vR.width === 0) return;
  436. const gVCX = vR.left + vR.width / 2;
  437. const gVCY = vR.top + vR.height / 2;
  438. let mX = tSX - gVCX;
  439. let mY = tSY - gVCY;
  440. if (Math.abs(mX) < 0.1 && Math.abs(mY) < 0.1 && state.recoilState.offsetX === 0 && state.recoilState.offsetY === 0) return;
  441. const sC = document.querySelector(config.game.containerSelector) || state.gameVideo || document.documentElement;
  442. const evt = new PointerEvent('pointermove', {
  443. bubbles: true, cancelable: true, view: window,
  444. clientX: Math.round(state.input.lastMouseX + mX), clientY: Math.round(state.input.lastMouseY + mY),
  445. screenX: Math.round(state.input.lastMouseX + mX), screenY: Math.round(state.input.lastMouseY + mY),
  446. movementX: Math.round(mX), movementY: Math.round(mY),
  447. buttons: (state.input.leftButtonDown ? 1 : 0) | (state.input.rightButtonDown ? 2 : 0),
  448. pointerType: 'mouse', isPrimary: true
  449. });
  450. sC.dispatchEvent(evt);
  451. },
  452. startShooting() {
  453. if (state.isShooting) return;
  454. const sC = document.querySelector(config.game.containerSelector) || state.gameVideo || document.documentElement;
  455. const evt = new PointerEvent('pointerdown', {
  456. bubbles: true, cancelable: true, view: window,
  457. clientX: Math.round(state.input.lastMouseX), clientY: Math.round(state.input.lastMouseY),
  458. button: 0, buttons: 1, pointerType: 'mouse', isPrimary: true
  459. });
  460. sC.dispatchEvent(evt);
  461. state.isShooting = true;
  462. state.recoilState.shotsFired = 0;
  463. debug.log("Shooting started (simulated by aimbot)");
  464. if (config.game.controlOptions.crouchOnShoot && !state.input.activeKeys.has(config.game.controlOptions.crouchKey)) {
  465. this.pressKey(config.game.controlOptions.crouchKey, 0);
  466. }
  467. },
  468. stopShooting() {
  469. if (!state.isShooting) return;
  470. const sC = document.querySelector(config.game.containerSelector) || state.gameVideo || document.documentElement;
  471. const evt = new PointerEvent('pointerup', {
  472. bubbles: true, cancelable: true, view: window,
  473. clientX: Math.round(state.input.lastMouseX), clientY: Math.round(state.input.lastMouseY),
  474. button: 0, buttons: 0, pointerType: 'mouse', isPrimary: true
  475. });
  476. sC.dispatchEvent(evt);
  477. state.isShooting = false;
  478. debug.log("Shooting stopped (simulated by aimbot)");
  479. if (config.game.controlOptions.crouchOnShoot && state.input.activeKeys.has(config.game.controlOptions.crouchKey)) {
  480. this.releaseKey(config.game.controlOptions.crouchKey);
  481. }
  482. },
  483. pressKey(kC, dur = 50) {
  484. const k = kC.replace(/^(Key|Digit)/, '');
  485. const eT = document.activeElement || document.body;
  486. const dE = new KeyboardEvent('keydown', {
  487. code: kC, key: k, keyCode: kC.startsWith('Digit') ? parseInt(k) : k.length === 1 ? k.charCodeAt(0) : 0,
  488. bubbles: true, cancelable: true, view: window
  489. });
  490. eT.dispatchEvent(dE);
  491. state.input.activeKeys.add(kC);
  492. if (dur > 0) setTimeout(() => this.releaseKey(kC), dur);
  493. },
  494. releaseKey(kC) {
  495. const k = kC.replace(/^(Key|Digit)/, '');
  496. const eT = document.activeElement || document.body;
  497. const uE = new KeyboardEvent('keyup', {
  498. code: kC, key: k, keyCode: kC.startsWith('Digit') ? parseInt(k) : k.length === 1 ? k.charCodeAt(0) : 0,
  499. bubbles: true, cancelable: true, view: window
  500. });
  501. eT.dispatchEvent(uE);
  502. state.input.activeKeys.delete(kC);
  503. },
  504. reload() {
  505. this.pressKey(config.game.controlOptions.reloadKey, 50);
  506. debug.log("Reload key pressed");
  507. },
  508. switchWeapon(sI) {
  509. if (sI >= 0 && sI < config.game.controlOptions.weaponKeys.length) {
  510. this.pressKey(config.game.controlOptions.weaponKeys[sI], 50);
  511. state.currentWeapon = sI;
  512. debug.log(`Switched to weapon slot ${sI + 1}`);
  513. }
  514. }
  515. };
  516.  
  517. // === Visual Rendering Functions ===
  518. // These functions handle the overlay canvas and visual elements.
  519.  
  520. function createOverlayCanvas() {
  521. if (state.ui.overlayCanvas) return;
  522. const c = document.createElement('canvas');
  523. c.id = 'xcloud-aimbot-overlay';
  524. c.width = window.innerWidth;
  525. c.height = window.innerHeight;
  526. c.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:99999;';
  527. state.ui.overlayCanvas = c;
  528. state.ui.overlayCtx = c.getContext('2d');
  529. document.body.appendChild(c);
  530. window.addEventListener('resize', () => {
  531. c.width = window.innerWidth;
  532. c.height = window.innerHeight;
  533. });
  534. debug.log("Overlay canvas created");
  535. }
  536.  
  537. function drawCrosshair(vR) {
  538. if (!state.ui.overlayCtx || !config.visual.crosshair.enabled) return;
  539. const ctx = state.ui.overlayCtx;
  540. let cX, cY;
  541. if (config.visual.crosshair.centerOnGameScreen && vR && vR.width > 0) {
  542. cX = vR.left + vR.width / 2;
  543. cY = vR.top + vR.height / 2;
  544. } else {
  545. cX = state.input.lastMouseX;
  546. cY = state.input.lastMouseY;
  547. }
  548. const s = config.visual.crosshair.size;
  549. ctx.strokeStyle = config.visual.crosshair.color;
  550. ctx.fillStyle = config.visual.crosshair.color;
  551. ctx.lineWidth = 1;
  552. switch (config.visual.crosshair.style) {
  553. case 'cross':
  554. ctx.beginPath();
  555. ctx.moveTo(cX - 2 * s, cY);
  556. ctx.lineTo(cX + 2 * s, cY);
  557. ctx.moveTo(cX, cY - 2 * s);
  558. ctx.lineTo(cX, cY + 2 * s);
  559. ctx.stroke();
  560. break;
  561. case 'dot':
  562. ctx.beginPath();
  563. ctx.arc(cX, cY, s, 0, 2 * Math.PI);
  564. ctx.fill();
  565. break;
  566. case 'circle':
  567. ctx.beginPath();
  568. ctx.arc(cX, cY, 2 * s, 0, 2 * Math.PI);
  569. ctx.stroke();
  570. break;
  571. }
  572. }
  573.  
  574. function drawKeypoints(ps, vR) {
  575. if (!config.visual.keypoints.enabled || !state.ui.overlayCtx || !ps || ps.length === 0 || !vR) return;
  576. const ctx = state.ui.overlayCtx;
  577. ps.forEach(p => {
  578. if (p.keypoints) {
  579. p.keypoints.forEach(kP => {
  580. if (kP.score && kP.score >= config.detection.keypointConfidence) {
  581. const sX = vR.left + kP.x / state.gameVideo.videoWidth * vR.width;
  582. const sY = vR.top + kP.y / state.gameVideo.videoHeight * vR.height;
  583. ctx.beginPath();
  584. ctx.arc(sX, sY, config.visual.keypoints.radius, 0, 2 * Math.PI);
  585. ctx.fillStyle = config.visual.keypoints.color;
  586. ctx.fill();
  587. }
  588. });
  589. }
  590. });
  591. }
  592.  
  593. function drawBoundingBoxes(ps, vR) {
  594. if (!config.visual.boundingBoxes.enabled || !state.ui.overlayCtx || !ps || ps.length === 0 || !vR) return;
  595. const ctx = state.ui.overlayCtx;
  596. ps.forEach(p => {
  597. const [vBx, vBy, vBw, vBh] = p.bbox;
  598. const sX = vR.left + vBx / state.gameVideo.videoWidth * vR.width;
  599. const sY = vR.top + vBy / state.gameVideo.videoHeight * vR.height;
  600. const sW = vBw / state.gameVideo.videoWidth * vR.width;
  601. const sH = vBh / state.gameVideo.videoHeight * vR.height;
  602. ctx.strokeStyle = config.visual.boundingBoxes.color;
  603. ctx.lineWidth = config.visual.boundingBoxes.lineWidth;
  604. ctx.fillStyle = config.visual.boundingBoxes.fillColor;
  605. ctx.fillRect(sX, sY, sW, sH);
  606. ctx.strokeRect(sX, sY, sW, sH);
  607. if (config.visual.boundingBoxes.showInfo) {
  608. ctx.fillStyle = config.visual.boundingBoxes.color;
  609. ctx.font = '12px Arial';
  610. const sT = `${(100 * p.score).toFixed(0)}%`;
  611. ctx.fillText(sT, sX + 5, sY + 15);
  612. if (p.keypoints && config.visual.boundingBoxes.fromKeypoints) {
  613. const kC = p.keypoints.filter(kP => kP.score >= config.detection.keypointConfidence).length;
  614. ctx.fillText(`KPs: ${kC}`, sX + 5, sY + 30);
  615. }
  616. }
  617. });
  618. }
  619.  
  620. const SKELETON_CONNECTIONS = [
  621. ['left_shoulder', 'right_shoulder'], ['left_hip', 'right_hip'], ['left_shoulder', 'left_hip'], ['right_shoulder', 'right_hip'],
  622. ['left_shoulder', 'left_elbow'], ['left_elbow', 'left_wrist'], ['right_shoulder', 'right_elbow'], ['right_elbow', 'right_wrist'],
  623. ['left_hip', 'left_knee'], ['left_knee', 'left_ankle'], ['right_hip', 'right_knee'], ['right_knee', 'right_ankle'],
  624. ];
  625.  
  626. function drawSkeleton(players, videoRect) {
  627. if (!config.visual.skeleton.enabled || !state.ui.overlayCtx || !players || players.length === 0 || !videoRect) return;
  628. const ctx = state.ui.overlayCtx;
  629. ctx.strokeStyle = config.visual.skeleton.color;
  630. ctx.lineWidth = config.visual.skeleton.lineWidth;
  631. players.forEach(player => {
  632. if (player.keypoints) {
  633. const keypointsMap = new Map();
  634. player.keypoints.forEach(kp => {
  635. if (kp.score && kp.score >= config.detection.keypointConfidence) {
  636. keypointsMap.set(kp.name, {
  637. x: videoRect.left + (kp.x / state.gameVideo.videoWidth) * videoRect.width,
  638. y: videoRect.top + (kp.y / state.gameVideo.videoHeight) * videoRect.height
  639. });
  640. }
  641. });
  642. SKELETON_CONNECTIONS.forEach(pair => {
  643. const kp1 = keypointsMap.get(pair[0]);
  644. const kp2 = keypointsMap.get(pair[1]);
  645. if (kp1 && kp2) {
  646. ctx.beginPath();
  647. ctx.moveTo(kp1.x, kp1.y);
  648. ctx.lineTo(kp2.x, kp2.y);
  649. ctx.stroke();
  650. }
  651. });
  652. }
  653. });
  654. }
  655.  
  656. function drawTargetLockIndicator(t, vR) {
  657. if (!config.visual.targetLock.enabled || !state.ui.overlayCtx || !t || !vR) return;
  658. const ctx = state.ui.overlayCtx;
  659. const [vBx, vBy, vBw, vBh] = t.prediction.bbox;
  660. const bSX = vR.left + vBx / state.gameVideo.videoWidth * vR.width;
  661. const bSY = vR.top + vBy / state.gameVideo.videoHeight * vR.height;
  662. const bSW = vBw / state.gameVideo.videoWidth * vR.width;
  663. const bSH = vBh / state.gameVideo.videoHeight * vR.height;
  664. ctx.strokeStyle = config.visual.targetLock.color;
  665. ctx.lineWidth = 2;
  666. const cS = 0.2 * Math.min(bSW, bSH);
  667. switch (config.visual.targetLock.style) {
  668. case 'full':
  669. ctx.strokeRect(bSX, bSY, bSW, bSH);
  670. break;
  671. case 'corners':
  672. ctx.beginPath();
  673. ctx.moveTo(bSX + cS, bSY); ctx.lineTo(bSX, bSY); ctx.lineTo(bSX, bSY + cS);
  674. ctx.moveTo(bSX + bSW - cS, bSY); ctx.lineTo(bSX + bSW, bSY); ctx.lineTo(bSX + bSW, bSY + cS);
  675. ctx.moveTo(bSX + cS, bSY + bSH); ctx.lineTo(bSX, bSY + bSH); ctx.lineTo(bSX, bSY + bSH - cS);
  676. ctx.moveTo(bSX + bSW - cS, bSY + bSH); ctx.lineTo(bSX + bSW, bSY + bSH); ctx.lineTo(bSX + bSW, bSY + bSH - cS);
  677. ctx.stroke();
  678. break;
  679. case 'crosshair':
  680. const cSz = 10;
  681. ctx.beginPath();
  682. ctx.moveTo(t.screenPosition.x - cSz, t.screenPosition.y);
  683. ctx.lineTo(t.screenPosition.x + cSz, t.screenPosition.y);
  684. ctx.moveTo(t.screenPosition.x, t.screenPosition.y - cSz);
  685. ctx.lineTo(t.screenPosition.x, t.screenPosition.y + cSz);
  686. ctx.stroke();
  687. break;
  688. }
  689. }
  690.  
  691. function drawFOVCircle(vR) {
  692. if (!config.visual.fovCircle.enabled || !state.ui.overlayCtx) return;
  693. if (config.visual.fovCircle.showOnlyWhenAiming && !state.input.activeKeys.has(config.aim.activationKey)) return;
  694. const ctx = state.ui.overlayCtx;
  695. let cX, cY;
  696. if (config.visual.fovCircle.centerOnGameScreen && vR && vR.width > 0) {
  697. cX = vR.left + vR.width / 2;
  698. cY = vR.top + vR.height / 2;
  699. } else {
  700. cX = state.input.lastMouseX;
  701. cY = state.input.lastMouseY;
  702. }
  703. ctx.strokeStyle = config.visual.fovCircle.color;
  704. ctx.lineWidth = config.visual.fovCircle.lineWidth;
  705. ctx.beginPath();
  706. ctx.arc(cX, cY, config.aim.fovRadius, 0, 2 * Math.PI);
  707. ctx.stroke();
  708. }
  709.  
  710. function drawPerformanceMetrics() {
  711. if (!config.visual.performanceMetrics.enabled || !state.ui.overlayCtx) return;
  712. const ctx = state.ui.overlayCtx;
  713. const ms = [
  714. `FPS: ${state.performance.fps}`,
  715. `Detect: ${state.performance.detectionTime.toFixed(1)}ms (Avg: ${state.performance.avgDetectionTime.toFixed(1)}ms)`
  716. ];
  717. ctx.font = '14px Arial';
  718. ctx.fillStyle = 'rgba(0,255,0,0.8)';
  719. const lH = 16;
  720. let sX = 10, sY = 20;
  721. switch (config.visual.performanceMetrics.position) {
  722. case 'top-right':
  723. sX = state.ui.overlayCanvas.width - 200;
  724. break;
  725. case 'bottom-left':
  726. sY = state.ui.overlayCanvas.height - ms.length * lH - 10;
  727. break;
  728. case 'bottom-right':
  729. sX = state.ui.overlayCanvas.width - 200;
  730. sY = state.ui.overlayCanvas.height - ms.length * lH - 10;
  731. break;
  732. }
  733. ms.forEach((m, i) => ctx.fillText(m, sX, sY + i * lH));
  734. }
  735.  
  736. function drawDebugInfo() {
  737. if (!config.visual.showDebugInfo || !state.ui.overlayCtx) return;
  738. const ctx = state.ui.overlayCtx;
  739. const aimingActive = state.input.activeKeys.has(config.aim.activationKey);
  740. const dL = [
  741. `Target: ${state.currentTarget ? `Yes (Score: ${state.currentTarget.score.toFixed(2)})` : "No"}`,
  742. `Shooting: ${state.isShooting ? "Yes" : "No"} | Aiming (${config.aim.activationKey.replace('Key', '')})${aimingActive ? " (Active)" : " (Inactive)"}`,
  743. `Recoil X: ${state.recoilState.offsetX.toFixed(2)} Y: ${state.recoilState.offsetY.toFixed(2)}`,
  744. `OS Mouse: X:${state.input.lastMouseX.toFixed(0)} Y:${state.input.lastMouseY.toFixed(0)}`
  745. ];
  746. ctx.font = '12px Arial';
  747. ctx.fillStyle = 'rgba(255,255,0,0.8)';
  748. const lH = 15;
  749. let sY = 80;
  750. if (config.visual.performanceMetrics.enabled && config.visual.performanceMetrics.position === 'top-left') {
  751. sY = 20 + (state.performance.fps > 0 ? 2 : 1) * 16 + 20;
  752. }
  753. let sX = 10;
  754. if (config.visual.performanceMetrics.enabled && config.visual.performanceMetrics.position === 'bottom-left' && config.visual.showDebugInfo) {
  755. sY = state.ui.overlayCanvas.height - (state.performance.fps > 0 ? 2 : 1) * 16 - 10 - dL.length * lH - 10;
  756. }
  757. dL.forEach((l, i) => ctx.fillText(l, sX, sY + i * lH));
  758. }
  759.  
  760. function drawIgnoreSelfRegionVisualization(videoRect) {
  761. if (!config.detection.ignoreSelfRegion.enabled || !config.visual.drawIgnoreRegion.enabled || !state.ui.overlayCtx || !videoRect || videoRect.width === 0) return;
  762. const ctx = state.ui.overlayCtx;
  763. const region = config.detection.ignoreSelfRegion;
  764. const visConfig = config.visual.drawIgnoreRegion;
  765. const rectX = videoRect.left + videoRect.width * region.xPercent;
  766. const rectY = videoRect.top + videoRect.height * region.yPercent;
  767. const rectW = videoRect.width * region.widthPercent;
  768. const rectH = videoRect.height * region.heightPercent;
  769. ctx.fillStyle = visConfig.color;
  770. ctx.fillRect(rectX, rectY, rectW, rectH);
  771. if (visConfig.lineWidth > 0) {
  772. ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)';
  773. ctx.lineWidth = visConfig.lineWidth;
  774. ctx.strokeRect(rectX, rectY, rectW, rectH);
  775. }
  776. }
  777.  
  778. function drawVisuals(players, currentTarget) {
  779. if (!state.ui.overlayCtx) return;
  780. const ctx = state.ui.overlayCtx;
  781. const canvas = state.ui.overlayCanvas;
  782. ctx.clearRect(0, 0, canvas.width, canvas.height);
  783. const videoRect = state.gameVideo ? state.gameVideo.getBoundingClientRect() : null;
  784. const isAimKeyHeld = state.input.activeKeys.has(config.aim.activationKey);
  785. if (config.visual.crosshair.enabled) drawCrosshair(videoRect);
  786. if (config.visual.fovCircle.enabled && (!config.visual.fovCircle.showOnlyWhenAiming || isAimKeyHeld)) {
  787. drawFOVCircle(videoRect);
  788. }
  789. if (config.detection.ignoreSelfRegion.enabled && config.visual.drawIgnoreRegion.enabled &&
  790. (!config.visual.drawIgnoreRegion.showOnlyWhenAiming || isAimKeyHeld) && videoRect) {
  791. drawIgnoreSelfRegionVisualization(videoRect);
  792. }
  793. if (isAimKeyHeld && videoRect && videoRect.width > 0) {
  794. if (config.visual.keypoints.enabled) drawKeypoints(players, videoRect);
  795. if (config.visual.skeleton.enabled) drawSkeleton(players, videoRect);
  796. if (config.visual.targetLock.enabled && currentTarget) drawTargetLockIndicator(currentTarget, videoRect);
  797. }
  798. if (config.visual.performanceMetrics.enabled) drawPerformanceMetrics();
  799. if (config.visual.showDebugInfo) drawDebugInfo();
  800. }
  801.  
  802. // === Recoil and Aiming Logic ===
  803. // Handles recoil compensation and aiming mechanics.
  804.  
  805. function applyRecoilCompensation() {
  806. if (!config.game.recoilCompensation) {
  807. if (state.recoilState.offsetX !== 0 || state.recoilState.offsetY !== 0) {
  808. const rS = config.game.recoilPatterns[config.game.recoilLevel] || config.game.recoilPatterns[1];
  809. state.recoilState.offsetX *= (1 - rS.recoverySpeed);
  810. state.recoilState.offsetY *= (1 - rS.recoverySpeed);
  811. if (Math.abs(state.recoilState.offsetX) < 0.01) state.recoilState.offsetX = 0;
  812. if (Math.abs(state.recoilState.offsetY) < 0.01) state.recoilState.offsetY = 0;
  813. }
  814. return;
  815. }
  816. const rS = config.game.recoilPatterns[config.game.recoilLevel] || config.game.recoilPatterns[1];
  817. const now = performance.now();
  818. if (state.input.leftButtonDown && !state.recoilState.lastLeftButtonState) {
  819. state.recoilState.shotsFired = 0;
  820. state.recoilState.active = true;
  821. }
  822. state.recoilState.lastLeftButtonState = state.input.leftButtonDown;
  823. if (state.input.leftButtonDown && state.recoilState.active) {
  824. if (state.recoilState.shotsFired === 0 || now - state.recoilState.lastShotTime > 200) {
  825. const kM = 1.0;
  826. state.recoilState.offsetY = -(rS.vertical * kM);
  827. state.recoilState.offsetX = (Math.random() - 0.5) * 2 * rS.horizontal * kM;
  828. } else {
  829. state.recoilState.offsetY -= rS.vertical * (0.2 + 0.5 * Math.random());
  830. state.recoilState.offsetX += (Math.random() - 0.5) * rS.horizontal * 1.5;
  831. }
  832. state.recoilState.offsetY = Math.max(state.recoilState.offsetY, -(rS.vertical * 4));
  833. state.recoilState.offsetX = Math.min(Math.abs(state.recoilState.offsetX), rS.horizontal * 2.5) * (state.recoilState.offsetX < 0 ? -1 : 1);
  834. if ((Math.abs(state.recoilState.offsetX) > 0.01 || Math.abs(state.recoilState.offsetY) > 0.01) && state.gameVideo) {
  835. const evt = new PointerEvent('pointermove', {
  836. bubbles: true, cancelable: true, view: window,
  837. movementX: Math.round(state.recoilState.offsetX), movementY: Math.round(state.recoilState.offsetY),
  838. buttons: (state.input.leftButtonDown ? 1 : 0) | (state.input.rightButtonDown ? 2 : 0),
  839. pointerType: 'mouse', isPrimary: true
  840. });
  841. (document.querySelector(config.game.containerSelector) || state.gameVideo || document.documentElement).dispatchEvent(evt);
  842. }
  843. state.recoilState.shotsFired++;
  844. state.recoilState.lastShotTime = now;
  845. state.recoilState.offsetX *= (1 - (rS.recoverySpeed * 1.5));
  846. state.recoilState.offsetY *= (1 - (rS.recoverySpeed * 1.5));
  847. } else {
  848. state.recoilState.active = false;
  849. if (state.recoilState.offsetX !== 0 || state.recoilState.offsetY !== 0) {
  850. state.recoilState.offsetX *= (1 - rS.recoverySpeed);
  851. state.recoilState.offsetY *= (1 - rS.recoverySpeed);
  852. if (Math.abs(state.recoilState.offsetX) < 0.01) state.recoilState.offsetX = 0;
  853. if (Math.abs(state.recoilState.offsetY) < 0.01) state.recoilState.offsetY = 0;
  854. }
  855. }
  856. }
  857.  
  858. async function processAiming(timestamp) {
  859. if (config.game.recoilCompensation) {
  860. applyRecoilCompensation();
  861. }
  862. const isAimKeyHeld = state.input.activeKeys.has(config.aim.activationKey);
  863. if (!isAimKeyHeld || !config.detection.enabled || !state.modelLoaded) {
  864. state.currentTarget = null;
  865. drawVisuals([], null);
  866. if (state.isShooting && !config.game.triggerOptions.burstMode) {
  867. InputController.stopShooting();
  868. }
  869. return;
  870. }
  871. const players = await detectPlayers();
  872. const newTarget = findBestTarget(players);
  873. if (newTarget) {
  874. if (!state.currentTarget || newTarget.prediction !== state.currentTarget.prediction) {
  875. const now = performance.now();
  876. if (!state.currentTarget || now - state.lastTargetSwitch > config.aim.targetSwitchCooldown) {
  877. debug.log(`New target acquired: Score ${newTarget.score.toFixed(2)}, dist: ${newTarget.distance.toFixed(0)}px`);
  878. state.currentTarget = newTarget;
  879. state.lastTargetSwitch = now;
  880. }
  881. } else {
  882. state.currentTarget = newTarget;
  883. }
  884. } else {
  885. state.currentTarget = null;
  886. }
  887. drawVisuals(players, state.currentTarget);
  888. if (state.currentTarget) {
  889. let { x: targetX, y: targetY } = state.currentTarget.screenPosition;
  890. InputController.moveMouseTo(targetX, targetY);
  891. if (config.game.autoShoot && state.currentTarget.distance < config.aim.fovRadius * config.aim.triggerThreshold) {
  892. if (!state.isShooting) {
  893. setTimeout(() => {
  894. if (state.currentTarget && state.input.activeKeys.has(config.aim.activationKey)) {
  895. InputController.startShooting();
  896. }
  897. }, config.game.triggerOptions.delayBeforeShoot);
  898. }
  899. } else if (state.isShooting && !config.game.triggerOptions.burstMode) {
  900. InputController.stopShooting();
  901. }
  902. } else {
  903. if (state.isShooting && !config.game.triggerOptions.burstMode) InputController.stopShooting();
  904. }
  905. }
  906.  
  907. async function detectPlayers() {
  908. if (!state.input.activeKeys.has(config.aim.activationKey)) {
  909. return [];
  910. }
  911. if (!state.gameVideo || !state.modelLoaded || !state.detectionModel ||
  912. state.gameVideo.paused || state.gameVideo.ended ||
  913. state.gameVideo.videoWidth === 0 || state.gameVideo.videoHeight === 0) {
  914. return [];
  915. }
  916. if (state.frameCount % (config.detection.skipFrames + 1) !== 0) {
  917. state.frameCount++;
  918. return [];
  919. }
  920. state.frameCount++;
  921. const now = performance.now();
  922. if (now - state.lastDetectionTime < config.detection.processingInterval) {
  923. return [];
  924. }
  925. let videoSource = state.gameVideo;
  926. if (config.detection.ignoreSelfRegion.enabled) {
  927. if (!state.ui.offscreenCanvas) {
  928. state.ui.offscreenCanvas = document.createElement('canvas');
  929. state.ui.offscreenCtx = state.ui.offscreenCanvas.getContext('2d');
  930. }
  931. if (state.ui.offscreenCanvas.width !== state.gameVideo.videoWidth || state.ui.offscreenCanvas.height !== state.gameVideo.videoHeight) {
  932. state.ui.offscreenCanvas.width = state.gameVideo.videoWidth;
  933. state.ui.offscreenCanvas.height = state.gameVideo.videoHeight;
  934. }
  935. const ctx = state.ui.offscreenCtx;
  936. ctx.drawImage(state.gameVideo, 0, 0, state.gameVideo.videoWidth, state.gameVideo.videoHeight);
  937. const region = config.detection.ignoreSelfRegion;
  938. const rectX = state.gameVideo.videoWidth * region.xPercent;
  939. const rectY = state.gameVideo.videoHeight * region.yPercent;
  940. const rectW = state.gameVideo.videoWidth * region.widthPercent;
  941. const rectH = state.gameVideo.videoHeight * region.heightPercent;
  942. ctx.fillStyle = 'rgba(0, 0, 0, 1)';
  943. ctx.fillRect(rectX, rectY, rectW, rectH);
  944. videoSource = state.ui.offscreenCanvas;
  945. }
  946. try {
  947. const detectionStart = performance.now();
  948. const poses = await state.detectionModel.estimatePoses(videoSource, { flipHorizontal: false });
  949. const detectionEnd = performance.now();
  950. state.performance.detectionTime = detectionEnd - detectionStart;
  951. state.performance.detectionTimeHistory.push(state.performance.detectionTime);
  952. if (state.performance.detectionTimeHistory.length > 30) state.performance.detectionTimeHistory.shift();
  953. state.performance.avgDetectionTime = state.performance.detectionTimeHistory.reduce((a, b) => a + b, 0) / state.performance.detectionTimeHistory.length;
  954. state.lastDetectionTime = now;
  955. const results = [];
  956. if (poses && poses.length > 0) {
  957. for (const pose of poses) {
  958. if (pose.score && pose.score >= config.detection.detectorConfig.minPoseScore) {
  959. const bbox = calculateBoundingBoxFromKeypoints(pose.keypoints);
  960. if (bbox && bbox.width > 0 && bbox.height > 0) {
  961. results.push({ class: 'person', score: pose.score, bbox: [bbox.x, bbox.y, bbox.width, bbox.height], keypoints: pose.keypoints });
  962. }
  963. }
  964. }
  965. }
  966. return results.slice(0, config.detection.maxDetections);
  967. } catch (err) {
  968. debug.error("Error during pose estimation:", err);
  969. return [];
  970. }
  971. }
  972.  
  973. // === GUI and Initialization ===
  974. // Handles the recoil tuning GUI and aimbot startup.
  975.  
  976. function createRecoilTuningGUI() {
  977. if (!config.visual.showRecoilTunerGUI) return;
  978. const guiContainer = document.createElement('div');
  979. guiContainer.id = 'aimbot-recoil-gui';
  980. guiContainer.style.cssText = `position: fixed; top: 280px; right: 10px; background-color: rgba(30, 30, 30, 0.85); border: 1px solid #555; border-radius: 5px; padding: 10px; color: white; font-family: Arial, sans-serif; font-size: 12px; z-index: 1000001; display: flex; flex-direction: column; gap: 8px; width: 230px;`;
  981. guiContainer.innerHTML = '<h4 style="margin:0 0 10px 0; text-align:center; font-size: 14px;">Anti-Recoil Tuner</h4>';
  982. const levelDiv = document.createElement('div');
  983. levelDiv.style.display = 'flex';
  984. levelDiv.style.alignItems = 'center';
  985. levelDiv.style.justifyContent = 'space-between';
  986. const levelLabel = document.createElement('label');
  987. levelLabel.textContent = 'Recoil Level:';
  988. levelLabel.htmlFor = 'recoilLevelSlider';
  989. levelLabel.style.marginRight = '10px';
  990. levelLabel.style.whiteSpace = 'nowrap';
  991. const levelSlider = document.createElement('input');
  992. levelSlider.type = 'range';
  993. levelSlider.id = 'recoilLevelSlider';
  994. levelSlider.min = 1;
  995. levelSlider.max = 5;
  996. levelSlider.step = 1;
  997. levelSlider.value = config.game.recoilLevel;
  998. levelSlider.style.width = '100px';
  999. levelSlider.style.flexGrow = '1';
  1000. const levelValueDisplay = document.createElement('span');
  1001. levelValueDisplay.textContent = levelSlider.value;
  1002. levelValueDisplay.style.marginLeft = '10px';
  1003. levelValueDisplay.style.width = '20px';
  1004. levelValueDisplay.style.textAlign = 'right';
  1005. levelSlider.addEventListener('input', () => {
  1006. config.game.recoilLevel = parseInt(levelSlider.value);
  1007. levelValueDisplay.textContent = levelSlider.value;
  1008. debug.log(`Recoil level set to: ${config.game.recoilLevel}`);
  1009. });
  1010. levelDiv.appendChild(levelLabel);
  1011. levelDiv.appendChild(levelSlider);
  1012. levelDiv.appendChild(levelValueDisplay);
  1013. guiContainer.appendChild(levelDiv);
  1014. document.body.appendChild(guiContainer);
  1015. debug.log("Recoil tuning GUI created.");
  1016. }
  1017.  
  1018. function startAimbotLoop() {
  1019. debug.log("Starting main aimbot loop");
  1020. let loopActive = true;
  1021. async function mainLoop(timestamp) {
  1022. if (!loopActive) return;
  1023. requestAnimationFrame(mainLoop);
  1024. state.performance.framesThisSecond++;
  1025. if (timestamp - state.performance.lastFpsUpdate >= 1000) {
  1026. state.performance.fps = state.performance.framesThisSecond;
  1027. state.performance.framesThisSecond = 0;
  1028. state.performance.lastFpsUpdate = timestamp;
  1029. }
  1030. if (!state.gameVideo || state.gameVideo.paused || state.gameVideo.ended || state.gameVideo.videoWidth === 0) {
  1031. if (state.isShooting) InputController.stopShooting();
  1032. if (state.ui.overlayCtx) state.ui.overlayCtx.clearRect(0, 0, state.ui.overlayCanvas.width, state.ui.overlayCanvas.height);
  1033. state.currentTarget = null;
  1034. return;
  1035. }
  1036. await processAiming(timestamp);
  1037. }
  1038. requestAnimationFrame(mainLoop);
  1039. }
  1040.  
  1041. async function initializeAimbot() {
  1042. debug.log(`Initializing Aimbot V${config.version} (MoveNet)...`);
  1043. state.gameVideo = document.querySelector(config.game.videoSelector);
  1044. if (!state.gameVideo) {
  1045. debug.error("Game video element not found. Retrying...");
  1046. showNotification("Error: Game video not found! Aimbot cannot start.", "error", 5000);
  1047. setTimeout(initializeAimbot, 3000);
  1048. return;
  1049. }
  1050. debug.log("Game video element found:", state.gameVideo);
  1051. if (state.gameVideo.readyState < state.gameVideo.HAVE_METADATA) {
  1052. debug.log("Waiting for video metadata...");
  1053. try {
  1054. await new Promise((rs, rj) => {
  1055. state.gameVideo.onloadedmetadata = rs;
  1056. state.gameVideo.onerror = rj;
  1057. });
  1058. debug.log(`Video metadata loaded: ${state.gameVideo.videoWidth}x${state.gameVideo.videoHeight}`);
  1059. } catch (vE) {
  1060. debug.error("Error loading video metadata:", vE);
  1061. showNotification("Error loading video. Aimbot might not work correctly.", "error");
  1062. setTimeout(initializeAimbot, 5000);
  1063. return;
  1064. }
  1065. } else {
  1066. debug.log(`Video dimensions readily available: ${state.gameVideo.videoWidth}x${state.gameVideo.videoHeight}`);
  1067. }
  1068. createOverlayCanvas();
  1069. if (config.visual.showRecoilTunerGUI) {
  1070. createRecoilTuningGUI();
  1071. }
  1072. if (!InputController.init()) {
  1073. debug.error("Input controller failed to initialize.");
  1074. showNotification("Error: Input controller init failed!", "error");
  1075. return;
  1076. }
  1077. if (config.detection.enabled) {
  1078. if (!await loadDetectionModel()) debug.error("Detection model (MoveNet) failed to load. Detection features disabled.");
  1079. } else {
  1080. debug.log("Detection is disabled in config.");
  1081. showNotification("AI Detection is disabled.", "info");
  1082. }
  1083. startAimbotLoop();
  1084. debug.log("Aimbot (MoveNet) initialized and main loop started.");
  1085. showNotification(`Precision Aimbot V${config.version} (MoveNet) Initialized!`, "info");
  1086. }
  1087.  
  1088. if (document.readyState === 'complete' || document.readyState === 'interactive') {
  1089. setTimeout(initializeAimbot, 2500);
  1090. } else {
  1091. window.addEventListener('load', () => setTimeout(initializeAimbot, 2500));
  1092. }
  1093. })();
Add Comment
Please, Sign In to add comment