Advertisement
Josiahiscool73

AI Aimbot Xbox cloud gaming

May 1st, 2025
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 46.96 KB | None | 0 0
  1. // ==UserScript==
  2. // @name XcloudCheat v2.8.3 (Local Coco SSD - Tidy Fix)
  3. // @description Aimbot using local Coco SSD model with controller emulation, recoil compensation for Xbox Cloud Gaming. Fixes tf.tidy error.
  4. // @author Ph0qu3_111 & AI Enhancement & Integration
  5. // @version 2.8.3
  6. // @match *://*.xbox.com/play/*
  7. // @grant none
  8. // @run-at document-end
  9. // @require https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js
  10. // @require https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd@latest/dist/coco-ssd.min.js
  11. // ==/UserScript==
  12.  
  13. // --- Configuration ---
  14. const config = {
  15. // --- Detection Model (Coco SSD) ---
  16. detection: {
  17. enabled: true, // Master switch for detection/aiming
  18. modelType: 'cocossd', // Identifier for the model being used
  19. confidence: 0.50, // Confidence threshold (0.0 to 1.0) - Adjust as needed
  20. targetClass: 'person', // Coco SSD class for players
  21. maxDetections: 10, // Max number of detections per frame (performance)
  22. },
  23.  
  24. // --- Game settings ---
  25. game: {
  26. videoSelector: 'video[aria-label="Game Stream for unknown title"]',
  27. containerSelector: '#game-stream',
  28. aimInterval: 50, // Min ms between aim processing frames (lower = faster but more CPU)
  29. fovRadius: 250, // Field of View radius from screen center (pixels)
  30. aimSpeed: 0.25, // Smoothing factor for aim movement (0.05=slow, 1=instant)
  31. recoilCompensation: true,
  32. recoilLevel: 3, // 1=None, 2=Barely, 3=Slight, 4=ALot
  33. recoilPatterns: { // Defines vertical/horizontal kick and recovery speed
  34. 1: { vertical: 0, horizontal: 0, recoverySpeed: 0.1 },
  35. 2: { vertical: 0.2, horizontal: 0.05, recoverySpeed: 0.1 },
  36. 3: { vertical: 0.4, horizontal: 0.1, recoverySpeed: 0.15 },
  37. 4: { vertical: 0.6, horizontal: 0.2, recoverySpeed: 0.2 },
  38. },
  39. // jumpPrediction: false, // Currently disabled - complex to implement reliably
  40. autoShoot: true, // Automatically shoot when aiming at a valid target
  41. autoCrouchShoot: true, // Pressing Crouch key also triggers shooting
  42. autoReload: true, // Pressing Reload key triggers simulated reload press
  43. crouchKey: 'KeyQ', // Keyboard key for autoCrouchShoot
  44. reloadKey: 'KeyR', // Keyboard key for autoReload
  45. controller: { // Controller emulation settings
  46. enabled: true, // Use controller emulation for aiming/shooting
  47. xSensitivity: 0.5, // Multiplier for horizontal stick movement
  48. ySensitivity: 0.5, // Multiplier for vertical stick movement
  49. deadzone: 0.15, // Stick values below this are ignored (prevents drift)
  50. }
  51. },
  52.  
  53. // --- Visuals ---
  54. crosshair: {
  55. enabled: true,
  56. size: 15,
  57. color: 'lime',
  58. style: 'cross' // 'circle', 'dot', 'cross'
  59. },
  60. fovCircle: { // Drawn on overlay canvas
  61. enabled: true,
  62. color: 'rgba(255, 0, 0, 0.3)',
  63. lineWidth: 1,
  64. },
  65. boundingBoxes: { // Drawn on overlay canvas
  66. enabled: true,
  67. color: 'yellow',
  68. lineWidth: 2,
  69. },
  70.  
  71. // --- Aiming Logic ---
  72. aim: {
  73. positionSmoothing: true, // Average last few target positions for smoother aim
  74. historySize: 3, // Number of positions to average for smoothing
  75. // targetLockTime: 100, // Future features - Not implemented
  76. // targetLockTimeVariance: 20, // Future features - Not implemented
  77. targetPriority: "closest", // "closest", "center" (target closest to FOV center, or screen center)
  78. aimPoint: "center", // "center" (box center), "top" (box top-center estimate)
  79. },
  80.  
  81. // --- Debugging ---
  82. debug: {
  83. enabled: true,
  84. showFPS: true,
  85. logThrottleMs: 250, // Minimum ms between console logs
  86. }
  87. };
  88.  
  89. // --- Global Variables ---
  90. let gameVideo = null;
  91. let detectionModel = null; // Stores the loaded Coco SSD model instance
  92. let positionHistory = []; // Stores recent target coordinates for smoothing
  93. let currentTarget = null; // Stores the prediction object of the current target
  94. let overlayCanvas = null; // Canvas element for drawing FOV, boxes, etc.
  95. let overlayCtx = null; // 2D context for the overlay canvas
  96.  
  97. // --- Utility functions ---
  98. const utils = {
  99. fps: (function() { // Self-contained FPS counter
  100. let fps = 0;
  101. let lastUpdate = Date.now();
  102. let frames = 0;
  103. return {
  104. get: () => fps,
  105. update: () => {
  106. frames++;
  107. const now = Date.now();
  108. const diff = now - lastUpdate;
  109. if (diff >= 1000) {
  110. fps = Math.round((frames * 1000) / diff);
  111. lastUpdate = now;
  112. frames = 0;
  113. }
  114. }
  115. };
  116. })()
  117. };
  118.  
  119. // --- Debug system ---
  120. const debug = { // Simple console logging wrapper with throttling
  121. enabled: config.debug.enabled,
  122. showFPS: config.debug.showFPS,
  123. lastLogTime: 0,
  124. throttleMs: config.debug.logThrottleMs,
  125. log(...args) {
  126. if (this.enabled) {
  127. const now = Date.now();
  128. if (now - this.lastLogTime >= this.throttleMs) {
  129. let logString = `[XcloudCheat]`;
  130. if (this.showFPS) { logString += ` FPS: ${utils.fps.get()} |`; }
  131. console.log(logString, ...args);
  132. this.lastLogTime = now;
  133. }
  134. }
  135. },
  136. error(...args) { // Always log errors if debugging is enabled
  137. if (this.enabled) { console.error(`[XcloudCheat] ERROR:`, ...args); }
  138. },
  139. warn(...args) { // Log warnings if debugging is enabled
  140. if (this.enabled) { console.warn(`[XcloudCheat] WARN:`, ...args); }
  141. }
  142. };
  143.  
  144.  
  145. // --- Input Simulator (Handles Controller Emulation) ---
  146. const InputSimulator = {
  147. gameContainer: null,
  148. mousePos: { x: 0, y: 0 }, // Used for fallback or potential future mouse mode
  149. isShooting: false, // Tracks if the shoot button (trigger) is currently held
  150. recoilOffset: { x: 0, y: 0 }, // Current recoil adjustment being applied
  151. controller: { // State of the virtual controller
  152. leftStickX: 0, leftStickY: 0, rightStickX: 0, rightStickY: 0,
  153. buttons: { // Standard gamepad button layout
  154. a: false, b: false, x: false, y: false, leftBumper: false, rightBumper: false,
  155. leftTrigger: 0, rightTrigger: 0, // Triggers are analog (0.0 to 1.0)
  156. back: false, start: false, leftStickPress: false, rightStickPress: false, // Added stick presses
  157. dpadUp: false, dpadDown: false, dpadLeft: false, dpadRight: false
  158. }
  159. },
  160.  
  161. init() { // Get the game container element
  162. this.gameContainer = document.querySelector(config.game.containerSelector);
  163. if (!this.gameContainer) {
  164. debug.error('Game container NOT found! Input simulation will likely fail.');
  165. return false;
  166. }
  167. // Store initial center (not strictly needed for controller but useful for reference)
  168. const rect = this.gameContainer.getBoundingClientRect();
  169. this.mousePos = { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };
  170. debug.log('Input simulator initialized targeting:', config.game.containerSelector);
  171. return true;
  172. },
  173.  
  174. applyRecoil(targetX, targetY) { // Adjusts target coordinates based on recoil settings
  175. if (!config.game.recoilCompensation || !config.game.recoilPatterns[config.game.recoilLevel] || !this.isShooting) {
  176. // Don't apply recoil if disabled, level invalid, or not currently shooting
  177. // Ensure recoil decays even if not shooting
  178. if (this.recoilOffset.x !== 0 || this.recoilOffset.y !== 0) {
  179. const recoverySpeed = config.game.recoilPatterns[config.game.recoilLevel]?.recoverySpeed || 0.1;
  180. this.recoilOffset.x *= (1 - recoverySpeed);
  181. this.recoilOffset.y *= (1 - recoverySpeed);
  182. if (Math.abs(this.recoilOffset.x) < 0.01) this.recoilOffset.x = 0;
  183. if (Math.abs(this.recoilOffset.y) < 0.01) this.recoilOffset.y = 0;
  184. }
  185. return { x: targetX, y: targetY };
  186. }
  187.  
  188. const recoil = config.game.recoilPatterns[config.game.recoilLevel];
  189. // Apply initial kick only once when shooting starts (offset is near zero)
  190. if (Math.abs(this.recoilOffset.x) < 0.1 && Math.abs(this.recoilOffset.y) < 0.1) {
  191. const kickMultiplier = 5; // Adjust this to control initial kick intensity
  192. this.recoilOffset.y = recoil.vertical * kickMultiplier;
  193. this.recoilOffset.x = (Math.random() - 0.5) * 2 * recoil.horizontal * kickMultiplier;
  194. debug.log(`Recoil kick: x=${this.recoilOffset.x.toFixed(2)}, y=${this.recoilOffset.y.toFixed(2)}`);
  195. }
  196.  
  197. // Apply the current recoil offset to the target
  198. // Subtract X offset, Add Y offset (recoil pushes aim UP and sideways)
  199. let newTargetX = targetX - this.recoilOffset.x;
  200. let newTargetY = targetY + this.recoilOffset.y;
  201.  
  202. // Gradually reduce recoil offset (recovery towards center)
  203. this.recoilOffset.x *= (1 - recoil.recoverySpeed);
  204. this.recoilOffset.y *= (1 - recoil.recoverySpeed);
  205.  
  206. // Prevent drift when offset is very small
  207. if (Math.abs(this.recoilOffset.x) < 0.01) this.recoilOffset.x = 0;
  208. if (Math.abs(this.recoilOffset.y) < 0.01) this.recoilOffset.y = 0;
  209.  
  210. return { x: newTargetX, y: newTargetY };
  211. },
  212.  
  213. sendControllerInput() { // Creates and dispatches simulated gamepad data
  214. if (!config.game.controller.enabled || !this.gameContainer) return;
  215. try {
  216. // Construct the Gamepad object state based on current values
  217. const gamepad = {
  218. id: "Simulated Xbox Controller (XcloudCheat)", // Add an ID
  219. index: 0, // Typically the first controller
  220. connected: true,
  221. timestamp: performance.now(), // Use high-resolution timer
  222. mapping: 'standard',
  223. axes: [ // Standard mapping: LS horizontal, LS vertical, RS horizontal, RS vertical
  224. this.controller.leftStickX,
  225. this.controller.leftStickY,
  226. this.controller.rightStickX,
  227. this.controller.rightStickY
  228. ],
  229. buttons: [ // Standard mapping button order
  230. { pressed: this.controller.buttons.a, touched: this.controller.buttons.a, value: this.controller.buttons.a ? 1 : 0 }, // 0: A
  231. { pressed: this.controller.buttons.b, touched: this.controller.buttons.b, value: this.controller.buttons.b ? 1 : 0 }, // 1: B
  232. { pressed: this.controller.buttons.x, touched: this.controller.buttons.x, value: this.controller.buttons.x ? 1 : 0 }, // 2: X
  233. { pressed: this.controller.buttons.y, touched: this.controller.buttons.y, value: this.controller.buttons.y ? 1 : 0 }, // 3: Y
  234. { pressed: this.controller.buttons.leftBumper, touched: this.controller.buttons.leftBumper, value: this.controller.buttons.leftBumper ? 1 : 0 }, // 4: LB
  235. { pressed: this.controller.buttons.rightBumper, touched: this.controller.buttons.rightBumper, value: this.controller.buttons.rightBumper ? 1 : 0 }, // 5: RB
  236. { pressed: this.controller.buttons.leftTrigger > 0, touched: this.controller.buttons.leftTrigger > 0, value: this.controller.buttons.leftTrigger }, // 6: LT
  237. { pressed: this.controller.buttons.rightTrigger > 0, touched: this.controller.buttons.rightTrigger > 0, value: this.controller.buttons.rightTrigger }, // 7: RT
  238. { pressed: this.controller.buttons.back, touched: this.controller.buttons.back, value: this.controller.buttons.back ? 1 : 0 }, // 8: Back/Select
  239. { pressed: this.controller.buttons.start, touched: this.controller.buttons.start, value: this.controller.buttons.start ? 1 : 0 }, // 9: Start
  240. { pressed: this.controller.buttons.leftStickPress, touched: this.controller.buttons.leftStickPress, value: this.controller.buttons.leftStickPress ? 1 : 0 }, // 10: LS Press
  241. { pressed: this.controller.buttons.rightStickPress, touched: this.controller.buttons.rightStickPress, value: this.controller.buttons.rightStickPress ? 1 : 0 }, // 11: RS Press
  242. { pressed: this.controller.buttons.dpadUp, touched: this.controller.buttons.dpadUp, value: this.controller.buttons.dpadUp ? 1 : 0 }, // 12: Dpad Up
  243. { pressed: this.controller.buttons.dpadDown, touched: this.controller.buttons.dpadDown, value: this.controller.buttons.dpadDown ? 1 : 0 }, // 13: Dpad Down
  244. { pressed: this.controller.buttons.dpadLeft, touched: this.controller.buttons.dpadLeft, value: this.controller.buttons.dpadLeft ? 1 : 0 }, // 14: Dpad Left
  245. { pressed: this.controller.buttons.dpadRight, touched: this.controller.buttons.dpadRight, value: this.controller.buttons.dpadRight ? 1 : 0 }, // 15: Dpad Right
  246. // 16: Home/Guide (Optional, often not mappable)
  247. ]
  248. };
  249.  
  250. // --- Event Dispatching ---
  251. // Method 1: Overwrite navigator.getGamepads (More likely to work if game checks this directly)
  252. // This is somewhat hacky and might be blocked by browser security in some contexts.
  253. navigator.getGamepads = () => [gamepad, null, null, null]; // Present it as the first controller
  254.  
  255. // Method 2: Dispatch custom events (Less reliable, depends on game listening for non-standard events)
  256. // const connectEvent = new GamepadEvent('gamepadconnected', { gamepad: gamepad });
  257. // window.dispatchEvent(connectEvent);
  258. // If the game specifically polls getGamepads, events might be ignored.
  259.  
  260. } catch (e) {
  261. debug.error('Error sending controller input:', e);
  262. // Disable controller input if it fails repeatedly?
  263. }
  264. },
  265.  
  266. moveMouseTo(targetScreenX, targetScreenY) { // Calculates stick deflection based on target coords
  267. if (!this.gameContainer) return;
  268.  
  269. // Apply recoil adjustment *before* calculating stick deflection
  270. const compensatedTarget = this.applyRecoil(targetScreenX, targetScreenY);
  271. targetScreenX = compensatedTarget.x;
  272. targetScreenY = compensatedTarget.y;
  273.  
  274. if (config.game.controller.enabled) {
  275. const rect = this.gameContainer.getBoundingClientRect();
  276. const centerX = rect.left + rect.width / 2;
  277. const centerY = rect.top + rect.height / 2;
  278.  
  279. // Calculate delta (difference) between target and screen center
  280. const dx = targetScreenX - centerX;
  281. const dy = targetScreenY - centerY;
  282.  
  283. // Normalize delta based on half the container size and apply sensitivity
  284. // This gives a value roughly proportional to how far the stick should be pushed
  285. let rawStickX = (dx / (rect.width / 2)) * config.game.controller.xSensitivity;
  286. let rawStickY = (dy / (rect.height / 2)) * config.game.controller.ySensitivity;
  287.  
  288. // Clamp values to the [-1, 1] range expected for gamepad axes
  289. rawStickX = Math.max(-1, Math.min(1, rawStickX));
  290. rawStickY = Math.max(-1, Math.min(1, rawStickY));
  291.  
  292. // Apply Deadzone: If the calculated value is too small, treat it as zero
  293. let finalStickX = (Math.abs(rawStickX) < config.game.controller.deadzone) ? 0 : rawStickX;
  294. let finalStickY = (Math.abs(rawStickY) < config.game.controller.deadzone) ? 0 : rawStickY;
  295.  
  296. // Smooth the transition towards the target stick value using aimSpeed (interpolation)
  297. // CurrentStick = CurrentStick + (TargetStick - CurrentStick) * SpeedFactor
  298. this.controller.rightStickX += (finalStickX - this.controller.rightStickX) * config.game.aimSpeed;
  299. this.controller.rightStickY += (finalStickY - this.controller.rightStickY) * config.game.aimSpeed;
  300.  
  301. // Apply deadzone again AFTER smoothing to prevent drifting when near zero
  302. if (Math.abs(this.controller.rightStickX) < config.game.controller.deadzone) this.controller.rightStickX = 0;
  303. if (Math.abs(this.controller.rightStickY) < config.game.controller.deadzone) this.controller.rightStickY = 0;
  304.  
  305. this.sendControllerInput(); // Send the updated stick values
  306.  
  307. } else {
  308. // Fallback: If controller emulation is off, use basic mouse move (less likely to work well)
  309. this.fallbackMoveMouse(targetScreenX, targetScreenY);
  310. }
  311. },
  312.  
  313. fallbackMoveMouse(targetX, targetY) { // Basic mouse event dispatch (backup)
  314. const event = new MouseEvent('mousemove', {
  315. bubbles: true, clientX: targetX, clientY: targetY
  316. });
  317. if (this.gameContainer) { this.gameContainer.dispatchEvent(event); }
  318. this.mousePos = { x: targetX, y: targetY };
  319. },
  320.  
  321. // Simulates pressing and holding the shoot trigger
  322. startShooting() {
  323. if (this.isShooting || !config.game.controller.enabled) return;
  324. this.isShooting = true;
  325. debug.log("Shooting START");
  326. this.controller.buttons.rightTrigger = 1.0; // Full trigger press
  327. // Reset recoil immediately when shooting starts
  328. this.recoilOffset = { x: 0, y: 0 };
  329. this.sendControllerInput();
  330. },
  331.  
  332. // Simulates releasing the shoot trigger
  333. stopShooting() {
  334. if (!this.isShooting || !config.game.controller.enabled) return;
  335. this.isShooting = false;
  336. debug.log("Shooting STOP");
  337. this.controller.buttons.rightTrigger = 0.0; // Release trigger
  338. // Recoil recovery happens passively in applyRecoil over subsequent frames
  339. this.sendControllerInput();
  340. },
  341.  
  342. // Simulates a brief button press (e.g., for reload)
  343. pressButton(buttonName, duration = 50) {
  344. if (!config.game.controller.enabled || !this.controller.buttons.hasOwnProperty(buttonName)) return;
  345.  
  346. debug.log(`Pressing button: ${buttonName}`);
  347. this.controller.buttons[buttonName] = true; // Press
  348. // Handle trigger differently (set value to 1)
  349. if (buttonName === 'leftTrigger' || buttonName === 'rightTrigger') {
  350. this.controller.buttons[buttonName] = 1.0;
  351. }
  352. this.sendControllerInput();
  353.  
  354. setTimeout(() => {
  355. debug.log(`Releasing button: ${buttonName}`);
  356. this.controller.buttons[buttonName] = false; // Release
  357. if (buttonName === 'leftTrigger' || buttonName === 'rightTrigger') {
  358. this.controller.buttons[buttonName] = 0.0;
  359. }
  360. this.sendControllerInput();
  361. }, duration);
  362. },
  363.  
  364. // Fallback for keyboard key press simulation (might not work in cloud stream)
  365. pressKey(key, duration = 50) {
  366. debug.warn("Attempting keyboard press simulation (may not work reliably):", key);
  367. const eventInit = { bubbles: true, cancelable: true, view: window, key: key, code: key };
  368. try {
  369. // Try dispatching to document or game container
  370. const targetElement = this.gameContainer || document;
  371. targetElement.dispatchEvent(new KeyboardEvent('keydown', eventInit));
  372. setTimeout(() => {
  373. targetElement.dispatchEvent(new KeyboardEvent('keyup', eventInit));
  374. }, duration);
  375. } catch(e) {
  376. debug.error("Failed to simulate key press:", e);
  377. }
  378. }
  379. };
  380.  
  381. // --- Drawing Functions ---
  382. function createOverlayCanvas() { // Creates a canvas covering the screen for visuals
  383. if (overlayCanvas) return;
  384. overlayCanvas = document.createElement('canvas');
  385. overlayCanvas.id = 'xcloud-cheat-overlay';
  386. overlayCanvas.width = window.innerWidth;
  387. overlayCanvas.height = window.innerHeight;
  388. overlayCanvas.style.cssText = `position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 99998;`;
  389. overlayCtx = overlayCanvas.getContext('2d');
  390. document.body.appendChild(overlayCanvas);
  391. window.addEventListener('resize', () => { // Adjust canvas size on window resize
  392. overlayCanvas.width = window.innerWidth;
  393. overlayCanvas.height = window.innerHeight;
  394. });
  395. debug.log('Overlay canvas created');
  396. }
  397.  
  398. function drawOverlay(predictions = []) { // Draws FOV circle and bounding boxes
  399. if (!overlayCtx || !gameVideo) return; // Need context and video element
  400.  
  401. overlayCtx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height); // Clear previous frame
  402. const videoRect = gameVideo.getBoundingClientRect();
  403. if (!videoRect || videoRect.width === 0 || videoRect.height === 0) return; // Need valid video dimensions
  404.  
  405. // Draw FOV Circle (centered on video element)
  406. if (config.fovCircle.enabled) {
  407. overlayCtx.strokeStyle = config.fovCircle.color;
  408. overlayCtx.lineWidth = config.fovCircle.lineWidth;
  409. overlayCtx.beginPath();
  410. const centerX = videoRect.left + videoRect.width / 2;
  411. const centerY = videoRect.top + videoRect.height / 2;
  412. overlayCtx.arc(centerX, centerY, config.game.fovRadius, 0, Math.PI * 2);
  413. overlayCtx.stroke();
  414. }
  415.  
  416. // Draw Bounding Boxes for detected persons
  417. if (config.boundingBoxes.enabled && predictions.length > 0) {
  418. overlayCtx.strokeStyle = config.boundingBoxes.color;
  419. overlayCtx.lineWidth = config.boundingBoxes.lineWidth;
  420. overlayCtx.fillStyle = config.boundingBoxes.color; // For text
  421. overlayCtx.font = '12px sans-serif';
  422. overlayCtx.textBaseline = 'bottom';
  423.  
  424. predictions.forEach(p => {
  425. if (p.class === config.detection.targetClass) { // Only draw boxes for target class
  426. // Scale prediction bbox (relative to video) to screen coordinates
  427. const drawX = videoRect.left + (p.bbox[0] / gameVideo.videoWidth) * videoRect.width;
  428. const drawY = videoRect.top + (p.bbox[1] / gameVideo.videoHeight) * videoRect.height;
  429. const drawWidth = (p.bbox[2] / gameVideo.videoWidth) * videoRect.width;
  430. const drawHeight = (p.bbox[3] / gameVideo.videoHeight) * videoRect.height;
  431.  
  432. overlayCtx.strokeRect(drawX, drawY, drawWidth, drawHeight);
  433. // Draw class and confidence score above the box
  434. const scoreText = `${p.class} (${Math.round(p.score * 100)}%)`;
  435. overlayCtx.fillText(scoreText, drawX, drawY - 2);
  436. }
  437. });
  438. }
  439. }
  440.  
  441. // --- Crosshair ---
  442. function createCrosshair() { // Creates a simple crosshair canvas centered on screen
  443. if (!config.crosshair.enabled) return;
  444. const c = document.createElement('canvas');
  445. c.id = 'xcloud-crosshair';
  446. c.width = window.innerWidth; c.height = window.innerHeight;
  447. c.style.cssText = `position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; z-index: 99999;`; // Highest z-index
  448. const ctx = c.getContext('2d');
  449. document.body.appendChild(c);
  450.  
  451. function draw() { // Draws the configured crosshair style
  452. ctx.clearRect(0, 0, c.width, c.height);
  453. ctx.strokeStyle = config.crosshair.color;
  454. ctx.fillStyle = config.crosshair.color;
  455. ctx.lineWidth = 2;
  456. const centerX = c.width / 2;
  457. const centerY = c.height / 2;
  458. const size = config.crosshair.size;
  459.  
  460. switch (config.crosshair.style) {
  461. case 'circle':
  462. ctx.beginPath(); ctx.arc(centerX, centerY, size / 2, 0, Math.PI * 2); ctx.stroke(); break;
  463. case 'dot':
  464. ctx.beginPath(); ctx.arc(centerX, centerY, size / 4, 0, Math.PI * 2); ctx.fill(); break;
  465. case 'cross': default:
  466. ctx.beginPath(); ctx.moveTo(centerX - size / 2, centerY); ctx.lineTo(centerX + size / 2, centerY);
  467. ctx.moveTo(centerX, centerY - size / 2); ctx.lineTo(centerX, centerY + size / 2); ctx.stroke(); break;
  468. }
  469. }
  470. window.addEventListener('resize', () => { c.width = window.innerWidth; c.height = window.innerHeight; draw(); });
  471. draw();
  472. debug.log('Crosshair created');
  473. }
  474.  
  475. // --- Auto-actions ---
  476. function setupAutoCrouch() { // Binds crouch key to also trigger shooting
  477. if (!config.game.autoCrouchShoot) return;
  478. debug.log('Auto-crouch+shoot keybind active for:', config.game.crouchKey);
  479. document.addEventListener('keydown', (e) => {
  480. if (e.code === config.game.crouchKey && !e.repeat) {
  481. debug.log('Crouch key pressed, attempting shoot');
  482. InputSimulator.startShooting(); // Use controller simulation
  483. // Optionally simulate crouch button press (e.g., B button)
  484. // InputSimulator.pressButton('b', 50);
  485. }
  486. });
  487. document.addEventListener('keyup', (e) => { // Stop shooting when crouch is released
  488. if (e.code === config.game.crouchKey) {
  489. InputSimulator.stopShooting();
  490. }
  491. });
  492. }
  493.  
  494. function setupAutoReload() { // Binds reload key to simulate controller reload press
  495. if (!config.game.autoReload) return;
  496. debug.log('Auto-reload keybind active for:', config.game.reloadKey);
  497. document.addEventListener('keydown', (e) => {
  498. if (e.code === config.game.reloadKey && !e.repeat) {
  499. debug.log('Reload key pressed, simulating X button press');
  500. InputSimulator.pressButton('x', 75); // Simulate X button press (adjust duration if needed)
  501. // InputSimulator.pressKey(config.game.reloadKey); // Keep keyboard fallback? Less reliable.
  502. }
  503. });
  504. }
  505.  
  506.  
  507. // --- GUI Controls ---
  508. function createGUI() { // Creates the settings panel
  509. const gui = document.createElement('div');
  510. gui.style.cssText = `position: fixed; top: 10px; left: 10px; background: rgba(0,0,0,0.8); color: white; padding: 10px; border-radius: 8px; z-index: 100000; font-family: sans-serif; max-width: 300px; font-size: 13px; max-height: 90vh; overflow-y: auto;`; // Added scroll
  511.  
  512. // Check if GM_info is available, otherwise use a default string for the version
  513. const displayVersion = (typeof GM_info !== 'undefined' && GM_info.script)
  514. ? GM_info.script.version
  515. : '2.8.3 (Console)'; // Provide a fallback version
  516.  
  517. // HTML structure for the GUI elements, using displayVersion
  518. gui.innerHTML = `
  519. <h3 style="margin:0 0 10px; text-align:center; color:lightblue;">XcloudCheat v${displayVersion}</h3>
  520. <div style="border-bottom: 1px solid #444; padding-bottom: 5px; margin-bottom: 5px;">
  521. <label><input type="checkbox" id="detection-enabled" ${config.detection.enabled ? 'checked' : ''}> <b>Enable Aimbot</b></label><br>
  522. <label><input type="checkbox" id="auto-shoot" ${config.game.autoShoot ? 'checked' : ''}> Auto Shoot</label><br>
  523. <label><input type="checkbox" id="recoil-comp" ${config.game.recoilCompensation ? 'checked' : ''}> Recoil Comp</label><br>
  524. <label><input type="checkbox" id="auto-reload" ${config.game.autoReload ? 'checked' : ''}> Auto Reload (${config.game.reloadKey})</label><br>
  525. <label><input type="checkbox" id="draw-boxes" ${config.boundingBoxes.enabled ? 'checked' : ''}> Show Boxes</label><br>
  526. <label><input type="checkbox" id="draw-fov" ${config.fovCircle.enabled ? 'checked' : ''}> Show FOV</label>
  527. </div>
  528. <div style="border-bottom: 1px solid #444; padding-bottom: 5px; margin-bottom: 5px;">
  529. <label>Confidence: <span id="conf-val">${config.detection.confidence.toFixed(2)}</span></label>
  530. <input type="range" style="width: 95%;" id="confidence" min="0.1" max="0.9" step="0.05" value="${config.detection.confidence}">
  531. </div>
  532. <div>
  533. <label>Aim Speed: <span id="speed-val">${config.game.aimSpeed.toFixed(2)}</span></label>
  534. <input type="range" style="width: 95%;" id="aim-speed" min="0.05" max="1" step="0.05" value="${config.game.aimSpeed}">
  535. </div>
  536. <div>
  537. <label>FOV Radius: <span id="fov-val">${config.game.fovRadius}</span>px</label>
  538. <input type="range" style="width: 95%;" id="fov-radius" min="50" max="600" step="10" value="${config.game.fovRadius}">
  539. </div>
  540. <div>
  541. <label>Target Priority:
  542. <select id="target-priority" style="float: right;">
  543. <option value="closest" ${config.aim.targetPriority === "closest" ? 'selected' : ''}>Closest</option>
  544. <option value="center" ${config.aim.targetPriority === "center" ? 'selected' : ''}>Center</option>
  545. </select>
  546. </label>
  547. </div>
  548. <div>
  549. <label>Aim Point:
  550. <select id="aim-point" style="float: right;">
  551. <option value="center" ${config.aim.aimPoint === "center" ? 'selected' : ''}>Box Center</option>
  552. <option value="top" ${config.aim.aimPoint === "top" ? 'selected' : ''}>Box Top</option>
  553. </select>
  554. </label>
  555. </div>
  556. <div>
  557. <label>Recoil Level:
  558. <select id="recoil-level" style="float: right;">
  559. <option value="1" ${config.game.recoilLevel === 1 ? 'selected' : ''}>1 (None)</option>
  560. <option value="2" ${config.game.recoilLevel === 2 ? 'selected' : ''}>2 (Barely)</option>
  561. <option value="3" ${config.game.recoilLevel === 3 ? 'selected' : ''}>3 (Slight)</option>
  562. <option value="4" ${config.game.recoilLevel === 4 ? 'selected' : ''}>4 (A Lot)</option>
  563. </select>
  564. </label>
  565. </div>
  566.  
  567. <h4 style="margin:15px 0 5px; color:lightblue; border-top: 1px solid #444; padding-top: 10px;">Controller Emulation</h4>
  568. <label><input type="checkbox" id="controller-enabled" ${config.game.controller.enabled ? 'checked' : ''}> Enable Controller</label>
  569. <div>
  570. <label>X Sens: <span id="x-sens-val">${config.game.controller.xSensitivity.toFixed(2)}</span></label>
  571. <input type="range" style="width: 95%;" id="x-sensitivity" min="0.1" max="2" step="0.05" value="${config.game.controller.xSensitivity}">
  572. </div>
  573. <div>
  574. <label>Y Sens: <span id="y-sens-val">${config.game.controller.ySensitivity.toFixed(2)}</span></label>
  575. <input type="range" style="width: 95%;" id="y-sensitivity" min="0.1" max="2" step="0.05" value="${config.game.controller.ySensitivity}">
  576. </div>
  577. <div>
  578. <label>Deadzone: <span id="deadzone-val">${config.game.controller.deadzone.toFixed(2)}</span></label>
  579. <input type="range" style="width: 95%;" id="deadzone" min="0.01" max="0.5" step="0.01" value="${config.game.controller.deadzone}">
  580. </div>
  581. `;
  582. document.body.appendChild(gui);
  583.  
  584. // --- Bind GUI elements to config changes ---
  585. document.getElementById('detection-enabled').onchange = (e) => config.detection.enabled = e.target.checked;
  586. document.getElementById('auto-shoot').onchange = (e) => config.game.autoShoot = e.target.checked;
  587. document.getElementById('recoil-comp').onchange = (e) => config.game.recoilCompensation = e.target.checked;
  588. document.getElementById('auto-reload').onchange = (e) => config.game.autoReload = e.target.checked; // Setup happens once at start
  589. document.getElementById('draw-boxes').onchange = (e) => config.boundingBoxes.enabled = e.target.checked;
  590. document.getElementById('draw-fov').onchange = (e) => config.fovCircle.enabled = e.target.checked;
  591.  
  592. document.getElementById('confidence').oninput = (e) => {
  593. config.detection.confidence = parseFloat(e.target.value);
  594. document.getElementById('conf-val').textContent = config.detection.confidence.toFixed(2);
  595. };
  596. document.getElementById('aim-speed').oninput = (e) => {
  597. config.game.aimSpeed = parseFloat(e.target.value);
  598. document.getElementById('speed-val').textContent = config.game.aimSpeed.toFixed(2);
  599. };
  600. document.getElementById('fov-radius').oninput = (e) => {
  601. config.game.fovRadius = parseInt(e.target.value, 10);
  602. document.getElementById('fov-val').textContent = config.game.fovRadius;
  603. };
  604. document.getElementById('target-priority').onchange = (e) => config.aim.targetPriority = e.target.value;
  605. document.getElementById('aim-point').onchange = (e) => config.aim.aimPoint = e.target.value;
  606. document.getElementById('recoil-level').onchange = (e) => config.game.recoilLevel = parseInt(e.target.value, 10);
  607.  
  608. document.getElementById('controller-enabled').onchange = (e) => config.game.controller.enabled = e.target.checked;
  609. document.getElementById('x-sensitivity').oninput = (e) => {
  610. config.game.controller.xSensitivity = parseFloat(e.target.value);
  611. document.getElementById('x-sens-val').textContent = config.game.controller.xSensitivity.toFixed(2);
  612. };
  613. document.getElementById('y-sensitivity').oninput = (e) => {
  614. config.game.controller.ySensitivity = parseFloat(e.target.value);
  615. document.getElementById('y-sens-val').textContent = config.game.controller.ySensitivity.toFixed(2);
  616. };
  617. document.getElementById('deadzone').oninput = (e) => {
  618. config.game.controller.deadzone = parseFloat(e.target.value);
  619. document.getElementById('deadzone-val').textContent = config.game.controller.deadzone.toFixed(2);
  620. };
  621. debug.log("GUI Created");
  622. }
  623.  
  624.  
  625. // --- Main Aimbot Logic ---
  626.  
  627. async function findGameVideoAndInit() { // Locates the game video element and initializes the AI model
  628. gameVideo = document.querySelector(config.game.videoSelector);
  629. // Wait for video to have metadata loaded (readyState >= 2) and positive dimensions
  630. if (gameVideo && gameVideo.readyState >= 2 && gameVideo.videoWidth > 0 && gameVideo.videoHeight > 0) {
  631. debug.log(`Game video found: ${gameVideo.videoWidth}x${gameVideo.videoHeight}`);
  632.  
  633. // Initialize Coco SSD Model
  634. try {
  635. if (!detectionModel) { // Load model only if it hasn't been loaded yet
  636. debug.log("Loading Coco SSD model...");
  637. // Try to force WebGL backend for performance, fall back if needed
  638. try { await tf.setBackend('webgl'); } catch { debug.warn("WebGL backend failed, using default."); }
  639. await tf.ready(); // Wait for backend to be ready
  640. detectionModel = await cocoSsd.load(); // Load the model
  641. debug.log("Coco SSD model loaded successfully using backend:", tf.getBackend());
  642. } else {
  643. debug.log("Coco SSD model already loaded.");
  644. }
  645.  
  646. // Proceed with initializing other components
  647. if (InputSimulator.init()) {
  648. createOverlayCanvas();
  649. createCrosshair();
  650. createGUI(); // Will now use the fallback version if needed
  651. setupAutoCrouch();
  652. setupAutoReload();
  653. startAimLoop(); // Start the main detection and aiming loop
  654. } else {
  655. debug.error("InputSimulator initialization failed. Cannot proceed.");
  656. }
  657. } catch (err) {
  658. debug.error("Fatal Error during initialization (likely model loading):", err);
  659. // Use alert specifically for model loading errors, as it's critical
  660. if (err.message.toLowerCase().includes('coco') || err.message.toLowerCase().includes('model')) {
  661. alert("Failed to load AI Model. Aimbot cannot function. Check console (F12) for errors. You may need to refresh.");
  662. }
  663. // Optionally disable detection if loading fails
  664. config.detection.enabled = false;
  665. }
  666. } else {
  667. // If video not found or not ready, retry
  668. const status = gameVideo ? `readyState=${gameVideo.readyState}, dims=${gameVideo.videoWidth}x${gameVideo.videoHeight}` : 'not found';
  669. debug.log(`Game video not ready (${status}), retrying...`);
  670. setTimeout(findGameVideoAndInit, 1500); // Retry after 1.5 seconds
  671. }
  672. }
  673.  
  674. function startAimLoop() { // Starts the main loop using requestAnimationFrame
  675. debug.log('Starting main aim loop...');
  676. let lastFrameTime = 0;
  677. let animationFrameId = null; // To potentially cancel the loop
  678.  
  679. function loop(currentTime) {
  680. animationFrameId = requestAnimationFrame(loop); // Schedule next frame
  681.  
  682. // Calculate time since last frame for potential throttling/timing
  683. const deltaTime = currentTime - lastFrameTime;
  684.  
  685. // Enforce minimum interval between processing frames
  686. if (deltaTime < config.game.aimInterval) {
  687. return; // Skip this frame if too soon
  688. }
  689. lastFrameTime = currentTime;
  690.  
  691. utils.fps.update(); // Update FPS counter
  692.  
  693. // Core checks before running the aim logic
  694. if (!config.detection.enabled || !detectionModel || !gameVideo || gameVideo.paused || gameVideo.ended || gameVideo.videoWidth === 0) {
  695. // If disabled, model not loaded, or video problematic, stop aiming/shooting and clear visuals
  696. if (InputSimulator.isShooting) InputSimulator.stopShooting();
  697. // Reset stick input only if controller enabled
  698. if(config.game.controller.enabled) {
  699. InputSimulator.controller.rightStickX = 0;
  700. InputSimulator.controller.rightStickY = 0;
  701. InputSimulator.sendControllerInput(); // Send zeroed input
  702. }
  703. drawOverlay([]); // Clear drawings
  704. currentTarget = null; // Reset target
  705. positionHistory = []; // Clear history
  706. return; // Skip aim logic
  707. }
  708.  
  709. aimLoop(); // Run the main detection and aiming logic for this frame
  710. }
  711. loop(performance.now()); // Start the loop immediately
  712. }
  713.  
  714.  
  715. async function aimLoop() { // Single frame of detection and aiming
  716. if (!detectionModel || !gameVideo || gameVideo.videoWidth === 0) return; // Should be caught by startAimLoop, but double-check
  717.  
  718. let predictions = []; // Initialize predictions array
  719. try {
  720. // --- Perform Detection using Coco SSD ---
  721. // Check if video is ready before detection
  722. if (gameVideo.readyState < 2 || gameVideo.videoWidth === 0 || gameVideo.videoHeight === 0) {
  723. debug.warn("Video not ready for detection in aimLoop.");
  724. // predictions remains empty
  725. } else {
  726. // --- FIX: Removed tf.tidy() wrapper ---
  727. // Perform detection directly (detect handles its tensors)
  728. predictions = await detectionModel.detect(gameVideo, config.detection.maxDetections, config.detection.confidence);
  729. // --- End FIX ---
  730. }
  731.  
  732. // Filter predictions for the target class ('person')
  733. const persons = predictions.filter(p => p.class === config.detection.targetClass);
  734.  
  735. // --- Update Visual Overlay ---
  736. drawOverlay(persons); // Draw boxes/FOV based on current detections
  737.  
  738. // --- Process Targets and Aim ---
  739. processPredictions(persons);
  740.  
  741. } catch (e) {
  742. // Log specific TensorFlow errors differently
  743. if (e.message.includes("tensor") || e.message.includes("disposed") || e.message.includes("WebGL") || e.message.includes("backend")) { // Added 'backend'
  744. debug.warn("TensorFlow/WebGL/Backend error during detection (may recover):", e.message);
  745. } else {
  746. debug.error('Aimbot loop error:', e);
  747. }
  748. // Attempt to recover by stopping actions and clearing state
  749. if (InputSimulator.isShooting) InputSimulator.stopShooting();
  750. if(config.game.controller.enabled) {
  751. InputSimulator.controller.rightStickX = 0;
  752. InputSimulator.controller.rightStickY = 0;
  753. InputSimulator.sendControllerInput();
  754. }
  755. currentTarget = null;
  756. positionHistory = [];
  757. drawOverlay([]); // Clear overlay on error
  758. }
  759. }
  760.  
  761.  
  762. function processPredictions(targets) { // Finds the best target and triggers aiming/shooting
  763. const videoRect = gameVideo.getBoundingClientRect();
  764. // Need video position and size on screen to translate coordinates
  765. if (!targets.length || !videoRect || videoRect.width === 0) {
  766. // No valid targets found or video element not ready
  767. if (currentTarget) { // Only log if we *had* a target previously
  768. debug.log("Target lost.");
  769. }
  770. currentTarget = null;
  771. positionHistory = []; // Clear smoothing history
  772. if (InputSimulator.isShooting) InputSimulator.stopShooting();
  773. // Reset stick input
  774. if(config.game.controller.enabled) {
  775. InputSimulator.controller.rightStickX = 0;
  776. InputSimulator.controller.rightStickY = 0;
  777. InputSimulator.sendControllerInput();
  778. }
  779. return; // Exit if no targets
  780. }
  781.  
  782. // Screen center coordinates (relative to viewport)
  783. const screenCenterX = videoRect.left + videoRect.width / 2;
  784. const screenCenterY = videoRect.top + videoRect.height / 2;
  785.  
  786. let bestTarget = null;
  787. let minScore = Infinity; // Lower score is better (closer or higher priority)
  788.  
  789. // --- Find Best Target ---
  790. targets.forEach(target => {
  791. // Calculate the center of the detected bounding box (in video coordinates)
  792. const targetCenterX_video = target.bbox[0] + target.bbox[2] / 2;
  793. const targetCenterY_video = target.bbox[1] + target.bbox[3] / 2;
  794.  
  795. // Convert video coordinates to screen coordinates
  796. const targetCenterX_screen = videoRect.left + (targetCenterX_video / gameVideo.videoWidth) * videoRect.width;
  797. const targetCenterY_screen = videoRect.top + (targetCenterY_video / gameVideo.videoHeight) * videoRect.height;
  798.  
  799. // Calculate distance from the screen center (crosshair)
  800. const dx = targetCenterX_screen - screenCenterX;
  801. const dy = targetCenterY_screen - screenCenterY;
  802. const distance = Math.hypot(dx, dy);
  803.  
  804. // Check if target is within the defined Field of View radius
  805. if (distance > config.game.fovRadius) {
  806. return; // Skip this target, it's outside the FOV
  807. }
  808.  
  809. // Calculate score based on priority setting
  810. let score = Infinity;
  811. if (config.aim.targetPriority === "closest") {
  812. score = distance; // Prioritize purely by distance
  813. } else if (config.aim.targetPriority === "center") {
  814. // Alternative: Could slightly prioritize targets closer to exact center even within FOV
  815. score = distance; // Currently same as 'closest'
  816. // Example: score = distance + target.score * -10; // Factor in confidence?
  817. }
  818.  
  819. // Update best target if this one has a better score
  820. if (score < minScore) {
  821. minScore = score;
  822. bestTarget = target;
  823. // Store screen coords directly on bestTarget temporarily for convenience
  824. // bestTarget.screenCoords = { x: targetCenterX_screen, y: targetCenterY_screen }; // Might not be needed
  825. }
  826. });
  827.  
  828. // --- Aim at Best Target ---
  829. if (!bestTarget) {
  830. // No target within FOV met criteria
  831. if (currentTarget) debug.log("Target lost (Out of FOV or no priority match).");
  832. currentTarget = null;
  833. positionHistory = [];
  834. if (InputSimulator.isShooting) InputSimulator.stopShooting();
  835. if(config.game.controller.enabled) {
  836. InputSimulator.controller.rightStickX = 0;
  837. InputSimulator.controller.rightStickY = 0;
  838. InputSimulator.sendControllerInput();
  839. }
  840. return;
  841. }
  842.  
  843. // Log if a new target is acquired
  844. // Simple check: if currentTarget is null or different bbox[0]
  845. if (!currentTarget || currentTarget.bbox[0] !== bestTarget.bbox[0]) {
  846. debug.log(`New target acquired: ${bestTarget.class} (${(bestTarget.score*100).toFixed(1)}%), Dist: ${minScore.toFixed(0)}px`);
  847. }
  848. currentTarget = bestTarget; // Update the currently tracked target
  849.  
  850. // Calculate the specific point on the target to aim for (e.g., center or top)
  851. let aimScreenX, aimScreenY;
  852. const bboxX_screen = videoRect.left + (bestTarget.bbox[0] / gameVideo.videoWidth) * videoRect.width;
  853. const bboxY_screen = videoRect.top + (bestTarget.bbox[1] / gameVideo.videoHeight) * videoRect.height;
  854. const bboxW_screen = (bestTarget.bbox[2] / gameVideo.videoWidth) * videoRect.width;
  855. const bboxH_screen = (bestTarget.bbox[3] / gameVideo.videoHeight) * videoRect.height;
  856.  
  857. if (config.aim.aimPoint === "top") {
  858. // Aim near top-center of the bounding box
  859. aimScreenX = bboxX_screen + bboxW_screen / 2;
  860. aimScreenY = bboxY_screen + bboxH_screen * 0.15; // Adjust multiplier for desired head height
  861. } else { // Default to exact center
  862. aimScreenX = bboxX_screen + bboxW_screen / 2;
  863. aimScreenY = bboxY_screen + bboxH_screen / 2;
  864. }
  865.  
  866. // Apply Position Smoothing
  867. if (config.aim.positionSmoothing && config.aim.historySize > 0) {
  868. positionHistory.push({ x: aimScreenX, y: aimScreenY });
  869. if (positionHistory.length > config.aim.historySize) {
  870. positionHistory.shift(); // Remove oldest entry
  871. }
  872. // Calculate average position from history
  873. let sumX = 0, sumY = 0;
  874. positionHistory.forEach(pos => { sumX += pos.x; sumY += pos.y; });
  875. aimScreenX = sumX / positionHistory.length;
  876. aimScreenY = sumY / positionHistory.length;
  877. } else {
  878. positionHistory = []; // Clear history if smoothing disabled
  879. }
  880.  
  881. // --- Move Aim and Shoot ---
  882. InputSimulator.moveMouseTo(aimScreenX, aimScreenY); // Execute aim movement via controller sim
  883.  
  884. // Auto Shoot Logic
  885. if (config.game.autoShoot) {
  886. if (!InputSimulator.isShooting) { // Only start shooting if not already doing so
  887. InputSimulator.startShooting();
  888. }
  889. } else {
  890. if (InputSimulator.isShooting) { // If auto-shoot is off, make sure we stop shooting
  891. InputSimulator.stopShooting();
  892. }
  893. }
  894. }
  895.  
  896.  
  897. // --- Script Initialization ---
  898. (function init() {
  899. // Use a default name/version if GM_info is not available (console execution)
  900. const scriptName = typeof GM_info !== 'undefined' ? GM_info.script.name : "XcloudCheat (Console)";
  901. const scriptVersion = typeof GM_info !== 'undefined' ? GM_info.script.version : "2.8.3";
  902. console.log(`[${scriptName} v${scriptVersion}] Initializing...`);
  903.  
  904. // Delay initialization slightly to give the page and video element time to load fully
  905. setTimeout(findGameVideoAndInit, 2000); // Wait 2 seconds before starting setup
  906. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement