Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // == Xbox Cloud Gaming Keyboard/Mouse to Controller Mapper v10.2 ==
- // == !! EXPERIMENTAL - Fixed Weapon Switching & Weapon-Specific Anti-Recoil !! ==
- // == Fixes issue where 2/3/4 might not switch weapons. Ensures button press happens THEN recoil profile updates. ==
- // == WARNING: Requires tuning ALL Anti-Recoil values. Micro-movements speculative. HIGH BAN RISK. ==
- // == >>> VERIFY D-PAD MAPPINGS ('1'-'4' in keyMap) <<< HARD REFRESH first! ==
- (function() {
- console.log("Initializing Experimental KBM Mapper v10.2 (Fix Weapon Switch & Wep AR)...");
- console.warn(">>> EXTREME WARNING: WEAPON-SPECIFIC ANTI-RECOIL & MICRO-MOVEMENTS ACTIVE. HIGH BAN RISK. TUNE VALUES. VERIFY D-PAD MAPS. HARD REFRESH FIRST! <<<");
- // --- Configuration --- (Same as 10.1)
- const MOUSE_SENSITIVITY_X = 0.0025;
- const MOUSE_SENSITIVITY_Y = 0.0025;
- const ADS_SENSITIVITY_MULTIPLIER = 0.75;
- const MOUSE_DECAY = 0.85;
- const STATE_POLLING_RATE_MS = 16;
- const CONNECTION_DISPATCH_RATE_MS = 100;
- const AXIS_DEADZONE = 0.05;
- const FIRE_BUTTON_INDEX = 7;
- const ENABLE_ANTI_RECOIL = true;
- const ADS_BUTTON_INDEX = 6;
- const ENABLE_MICRO_MOVEMENTS = true;
- const MICRO_MOVEMENT_RADIUS = 0.02;
- const MICRO_MOVEMENT_SPEED = 0.1;
- // --- WEAPON-SPECIFIC Anti-Recoil Strengths (TUNE THESE!) --- (Same as 10.1)
- const ANTI_RECOIL_DEFAULT = 0.015;
- const ANTI_RECOIL_PICKAXE = 0.0; // Slot '1'
- const ANTI_RECOIL_SHOTGUN = 0.003; // Slot '2'
- const ANTI_RECOIL_AR = 0.015; // Slot '3'
- const ANTI_RECOIL_SMG = 0.025; // Slot '4'
- // --- Key Mapping ---
- // !!! CRITICAL: VERIFY these 'i' values match your game's D-Pad bindings for weapon slots 1-4 !!!
- // Standard D-Pad: Up=12, Down=13, Left=14, Right=15. These are JUST EXAMPLES.
- const keyMap = {
- // Movement & Core
- 'w': { t: 'a', a: 1, v: -1 }, 'a': { t: 'a', a: 0, v: -1 }, 's': { t: 'a', a: 1, v: 1 }, 'd': { t: 'a', a: 0, v: 1 },
- ' ': { t: 'b', i: 0 }, 'shift': { t: 'b', i: 10 }, 'control': { t: 'b', i: 11 },
- 'r': { t: 'b', i: 2 }, 'e': { t: 'b', i: 3 }, 'escape': { t: 'b', i: 9 }, 'tab': { t: 'b', i: 8 },
- // Combat
- 'q': { t: 'b', i: ADS_BUTTON_INDEX }, // ADS (LT)
- 'z': { t: 'b', i: FIRE_BUTTON_INDEX }, // Fire (RT)
- // Build (Examples)
- 'f': { t: 'b', i: 5 }, 'c': { t: 'b', i: 4 }, 'g': { t: 'b', i: 1 },
- // Weapon Slots (Map to D-Pad buttons AND set anti-recoil profile)
- '1': { t: 'b', i: 15 }, // Weapon Slot 1 (D-Pad Right?) -> Pickaxe Recoil --- VERIFY i:15 ---
- '2': { t: 'b', i: 12 }, // Weapon Slot 2 (D-Pad Up?) -> Shotgun Recoil --- VERIFY i:12 ---
- '3': { t: 'b', i: 14 }, // Weapon Slot 3 (D-Pad Left?) -> AR Recoil --- VERIFY i:14 ---
- '4': { t: 'b', i: 13 }, // Weapon Slot 4 (D-Pad Down?) -> SMG Recoil --- VERIFY i:13 ---
- };
- const mouseMap = { /* ... Same ... */
- 0: { t: 'b', i: FIRE_BUTTON_INDEX }, 2: { t: 'b', i: ADS_BUTTON_INDEX }
- };
- // --- State Tracking --- (Same as 10.1)
- const controllerState = { /* ... Same ... */
- axes: [0.0, 0.0, 0.0, 0.0], buttons: Array(17).fill(false).map((_, i) => ({ pressed: false, touched: false, value: 0.0, index: i })),
- axisKeyPresses: { 0: { neg: false, pos: false }, 1: { neg: false, pos: false } }, mouseDeltaX: 0, mouseDeltaY: 0, isConnected: true,
- timestamp: performance.now(), microMovementAngle: 0, currentAntiRecoilStrength: ANTI_RECOIL_DEFAULT
- };
- let pointerLocked = false; /* ... Same ... */ let stateIntervalId = null; let connectionIntervalId = null; let gameAreaElement = null;
- // --- Gamepad Object Construction --- (Same as 10.1)
- function createGamepadObject() { /* ... Same ... */
- const axes = controllerState.axes.map(val => Math.abs(val) < AXIS_DEADZONE ? 0.0 : val);
- return { axes: axes, buttons: controllerState.buttons, connected: controllerState.isConnected, id: "KBM Emulated Xbox Controller v10.2 (Wep AR Fix)", index: 0, mapping: "standard", timestamp: controllerState.timestamp };
- }
- // --- Core Simulation Function (Updates State) --- (Same as 10.1)
- function updateAndSimulateGamepad() { /* ... Same logic as 10.1 ... */
- let currentSensX = MOUSE_SENSITIVITY_X; let currentSensY = MOUSE_SENSITIVITY_Y; const isADS = controllerState.buttons[ADS_BUTTON_INDEX].pressed; const isFiring = controllerState.buttons[FIRE_BUTTON_INDEX].pressed; if (isADS) { currentSensX *= ADS_SENSITIVITY_MULTIPLIER; currentSensY *= ADS_SENSITIVITY_MULTIPLIER; } let targetRX = controllerState.axes[2]; let targetRY = controllerState.axes[3]; if (pointerLocked) { targetRX *= MOUSE_DECAY; targetRY *= MOUSE_DECAY; targetRX += controllerState.mouseDeltaX * currentSensX; targetRY += controllerState.mouseDeltaY * currentSensY; if (ENABLE_MICRO_MOVEMENTS && isADS) { const angle = controllerState.microMovementAngle; targetRX += Math.cos(angle) * MICRO_MOVEMENT_RADIUS; targetRY += Math.sin(angle) * MICRO_MOVEMENT_RADIUS; controllerState.microMovementAngle = (angle + MICRO_MOVEMENT_SPEED) % (2 * Math.PI); } if (ENABLE_ANTI_RECOIL && isFiring) { targetRY += controllerState.currentAntiRecoilStrength; } controllerState.mouseDeltaX = 0; controllerState.mouseDeltaY = 0; } else { targetRX = 0; targetRY = 0; controllerState.mouseDeltaX = 0; controllerState.mouseDeltaY = 0; controllerState.microMovementAngle = 0; } controllerState.axes[0] = Math.max(-1, Math.min(1, controllerState.axes[0])); controllerState.axes[1] = Math.max(-1, Math.min(1, controllerState.axes[1])); controllerState.axes[2] = Math.max(-1, Math.min(1, targetRX)); controllerState.axes[3] = Math.max(-1, Math.min(1, targetRY)); controllerState.timestamp = performance.now(); navigator.getGamepads = function() { return [createGamepadObject(), null, null, null]; };
- }
- // --- Event Handlers ---
- // *** REVISED handleKeyDown ***
- function handleKeyDown(event) {
- const key = event.key.toLowerCase();
- const mappedKey = (key === 'controlleft' || key === 'controlright') ? 'control' : key;
- const mapping = keyMap[mappedKey]; // Check mapping FIRST
- if (!mapping) return; // Exit if the key isn't mapped at all
- // Key is mapped, proceed with simulation
- event.preventDefault();
- event.stopPropagation();
- // 1. Simulate the primary button press or axis move based on keyMap
- if (mapping.t === 'b') { // Button press
- const button = controllerState.buttons[mapping.i];
- if (!button.pressed) {
- button.pressed = true;
- button.touched = true;
- button.value = 1.0;
- // Add specific log for weapon keys to confirm button press attempt
- if (['1', '2', '3', '4'].includes(mappedKey)) {
- console.log(`Attempting button press for weapon key '${mappedKey}': Button index ${mapping.i}`);
- }
- }
- } else if (mapping.t === 'a') { // Axis movement
- const axisState = controllerState.axisKeyPresses[mapping.a];
- if (mapping.v < 0) axisState.neg = true; else axisState.pos = true;
- if (axisState.neg && axisState.pos) { controllerState.axes[mapping.a] = 0; }
- else { controllerState.axes[mapping.a] = axisState.neg ? -1 : 1; }
- }
- // 2. Check if this key ALSO needs to update the anti-recoil profile
- let profileName = "";
- let newRecoilStrength = controllerState.currentAntiRecoilStrength; // Keep current if not changed
- switch (mappedKey) {
- case '1': newRecoilStrength = ANTI_RECOIL_PICKAXE; profileName = "Pickaxe"; break;
- case '2': newRecoilStrength = ANTI_RECOIL_SHOTGUN; profileName = "Shotgun"; break;
- case '3': newRecoilStrength = ANTI_RECOIL_AR; profileName = "AR"; break;
- case '4': newRecoilStrength = ANTI_RECOIL_SMG; profileName = "SMG"; break;
- }
- // Update and log only if the strength actually changed
- if (newRecoilStrength !== controllerState.currentAntiRecoilStrength) {
- controllerState.currentAntiRecoilStrength = newRecoilStrength;
- console.log(`Anti-Recoil Profile set to ${profileName} (${controllerState.currentAntiRecoilStrength})`);
- }
- }
- // handleKeyUp remains the same - releases the button/axis correctly
- function handleKeyUp(event) { /* ... Same as 10.1 ... */ const key = event.key.toLowerCase(); const mappedKey = (key === 'controlleft' || key === 'controlright') ? 'control' : key; const mapping = keyMap[mappedKey]; if (!mapping) return; event.preventDefault(); event.stopPropagation(); if (mapping.t === 'b') { const button = controllerState.buttons[mapping.i]; if (button.pressed) { button.pressed = false; button.touched = false; button.value = 0.0; } } else if (mapping.t === 'a') { const axisState = controllerState.axisKeyPresses[mapping.a]; if (mapping.v < 0) axisState.neg = false; else axisState.pos = false; if (axisState.neg) { controllerState.axes[mapping.a] = -1; } else if (axisState.pos) { controllerState.axes[mapping.a] = 1; } else { controllerState.axes[mapping.a] = 0; } } }
- // Other handlers remain the same
- function handleMouseDown(event) { /* ... Same ... */ const mapping = mouseMap[event.button]; if (!mapping || (!pointerLocked && event.target !== gameAreaElement)) return; event.preventDefault(); event.stopPropagation(); if (mapping.t === 'b') { const button = controllerState.buttons[mapping.i]; if (!button.pressed) { button.pressed = true; button.touched = true; button.value = 1.0; } } }
- function handleMouseUp(event) { /* ... Same ... */ const mapping = mouseMap[event.button]; if (!mapping) return; event.preventDefault(); event.stopPropagation(); if (mapping.t === 'b') { const button = controllerState.buttons[mapping.i]; if (button.pressed) { button.pressed = false; button.touched = false; button.value = 0.0; } } }
- function handleMouseMove(event) { /* ... Same ... */ if (!pointerLocked) return; event.preventDefault(); event.stopPropagation(); const movementX = event.movementX || 0; const movementY = event.movementY || 0; controllerState.mouseDeltaX += movementX; controllerState.mouseDeltaY += movementY; }
- function handlePointerLockChange() { /* ... Same ... */ const lockedElement = document.pointerLockElement; if (lockedElement === gameAreaElement) { console.log('%cPointer Locked', 'color: lightgreen; font-weight: bold;'); pointerLocked = true; } else { console.warn(`Pointer Unlocked. Was locked to: ${gameAreaElement?.id || gameAreaElement?.tagName}`); pointerLocked = false; controllerState.axes[2] = 0; controllerState.axes[3] = 0; controllerState.mouseDeltaX = 0; controllerState.mouseDeltaY = 0; controllerState.microMovementAngle = 0; Object.values(mouseMap).forEach(mapping => { if (mapping.t === 'b') { const button = controllerState.buttons[mapping.i]; button.pressed = false; button.touched = false; button.value = 0.0; } }); } }
- function requestPointerLock() { /* ... Same ... */ if (!gameAreaElement) { console.error("Cannot request pointer lock: Game area element not found."); return; } if (document.pointerLockElement !== gameAreaElement) { console.log("Requesting pointer lock on:", gameAreaElement); gameAreaElement.requestPointerLock().catch(e => { console.error("Pointer lock request failed:", e); }); } }
- function dispatchConnectionEvent() { /* ... Same ... */ try { const gamepad = createGamepadObject(); const gamepadConnectedEvent = new CustomEvent('gamepadconnected', { detail: { gamepad: gamepad } }); gamepadConnectedEvent.gamepad = gamepad; window.dispatchEvent(gamepadConnectedEvent); } catch (e) { console.error("Error dispatching periodic connection event:", e); } }
- // --- Initialization --- (Same as 10.1)
- console.log("Attempting to find game area element..."); gameAreaElement = document.getElementById('game-stream') || document.querySelector('video[playsinline]') || document.querySelector('video') || document.body; if (!gameAreaElement || gameAreaElement === document.body) { console.warn("Could not find specific game stream element, using document.body."); gameAreaElement = document.body; } else { console.log("Found game area element:", gameAreaElement); } navigator.getGamepads = function() { return [createGamepadObject(), null, null, null]; }; console.log("Initial navigator.getGamepads override set."); window.addEventListener('keydown', handleKeyDown, { capture: true }); window.addEventListener('keyup', handleKeyUp, { capture: true }); const mouseEventTarget = gameAreaElement; mouseEventTarget.addEventListener('mousemove', handleMouseMove, { capture: true }); mouseEventTarget.addEventListener('mousedown', handleMouseDown, { capture: true }); mouseEventTarget.addEventListener('mouseup', handleMouseUp, { capture: true }); document.addEventListener('pointerlockchange', handlePointerLockChange, false); if (gameAreaElement && gameAreaElement !== document.body) { gameAreaElement.addEventListener('click', requestPointerLock); console.log(">>> CLICK THE GAME AREA TO ENABLE MOUSE AIM <<<"); } else { console.warn("Game area is body or not found. Click anywhere on the page body to attempt pointer lock."); document.body.addEventListener('click', requestPointerLock); } try { dispatchConnectionEvent(); console.log("Dispatched initial gamepadconnected event."); } catch (e) { console.error("Error dispatching initial connection event:", e); } stateIntervalId = setInterval(updateAndSimulateGamepad, STATE_POLLING_RATE_MS); connectionIntervalId = setInterval(dispatchConnectionEvent, CONNECTION_DISPATCH_RATE_MS); console.log(`%cKBM Mapper V10.2 Active! State polling ID: ${stateIntervalId}, Connection dispatch ID: ${connectionIntervalId}.`, "color: cyan;"); if (ENABLE_ANTI_RECOIL) console.log(`Weapon-Specific Anti-Recoil ACTIVE. Initial/Default: ${controllerState.currentAntiRecoilStrength}. Press 1/2/3/4 to change.`); else console.log("Anti-Recoil DISABLED."); if (ENABLE_MICRO_MOVEMENTS) console.log(`Micro-Movements ACTIVE when ADS. Radius: ${MICRO_MOVEMENT_RADIUS}, Speed: ${MICRO_MOVEMENT_SPEED}.`); else console.log("Micro-Movements DISABLED."); console.warn(">>> REMEMBER: HIGH BAN RISK with these features enabled. Tune values! VERIFY D-PAD MAPS (keys 1-4)! Use responsibly! <<<"); console.log("To disable, refresh page or type: stopKbmMapper();");
- // --- Cleanup Function --- (Same as 10.1)
- window.stopKbmMapper = function() { /* ... Same as 10.1 ... */ console.log("Stopping KBM Mapper V10.2..."); if (stateIntervalId) clearInterval(stateIntervalId); if (connectionIntervalId) clearInterval(connectionIntervalId); stateIntervalId = null; connectionIntervalId = null; window.removeEventListener('keydown', handleKeyDown, { capture: true }); window.removeEventListener('keyup', handleKeyUp, { capture: true }); mouseEventTarget.removeEventListener('mousemove', handleMouseMove, { capture: true }); mouseEventTarget.removeEventListener('mousedown', handleMouseDown, { capture: true }); mouseEventTarget.removeEventListener('mouseup', handleMouseUp, { capture: true }); document.removeEventListener('pointerlockchange', handlePointerLockChange, false); if (gameAreaElement) gameAreaElement.removeEventListener('click', requestPointerLock); if (document.body && gameAreaElement === document.body) document.body.removeEventListener('click', requestPointerLock); if (document.pointerLockElement) { document.exitPointerLock(); } navigator.getGamepads = function() { return [null, null, null, null]; }; console.log("KBM Mapper stopped. Event listeners removed. Gamepad override disabled. Refresh recommended."); };
- })(); // End of IIFE
Add Comment
Please, Sign In to add comment