// ==UserScript== // @name Arras.io Gamepad support // @namespace Violentmonkey Scripts // @match *://arras.io/* // @grant none // @version 1.2 // @author alexandra // @description Allows you to use your Gamepad to play arras.io! Press F1 to toggle between active and disabled. Controls: Right thumb stick to move your tank, Left thumb stick to aim, RT to shoot, LT for right click, A for autofire, B for autospin, X for override and Y for taking control of other tanks. Setup "commandKeys" in the script to match your keybindings ingame. // @run-at document-start // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/519408/Arrasio%20Gamepad%20support.user.js // @updateURL https://update.greasyfork.icu/scripts/519408/Arrasio%20Gamepad%20support.meta.js // ==/UserScript== let commandKeys = { // change this if you want autofire: "KeyE", autospin: "KeyC", override: "KeyR", takeControl: "KeyF" } let enabled = false window.addEventListener("keydown", (e) => { if (e.code === "F1") { e.preventDefault() enabled = !enabled } }) let windowListener = window.addEventListener window.addEventListener = function(...args) { let type = args[0] if (type === "keydown" || type === "keyup") { let callback = args[1] args[1] = function(event) { return callback.call(this, { isTrusted: true, key: event.key, code: event.code, preventDefault: function(){} }) } } return windowListener.apply(this, args) } let cnvsElementListener = HTMLDivElement.prototype.addEventListener HTMLDivElement.prototype.addEventListener = function(...args) { let type = args[0] if (type === "mousedown" || type === "mouseup" || type === "mousemove") { let callback = args[1] args[1] = function(event) { return callback.call(this, { isTrusted: true, clientX: event.clientX, clientY: event.clientY, button: event.button, preventDefault: function(){} }) } } return cnvsElementListener.apply(this, args) } function keyEvent(key, type) { window.dispatchEvent(new KeyboardEvent(type ? "keydown" : "keyup", { code: key })) } function mouseEvent(x, y, button, type) { let event = new MouseEvent(type, { clientX: x, clientY: y, button: button, }) document.querySelector("#canvas").dispatchEvent(event) } function eightDirMoveTo(cx, cy, ex, ey) { if (ex > cx) { keyEvent("ArrowLeft", false) keyEvent("ArrowRight", true) } else if (ex < cx) { keyEvent("ArrowLeft", true) keyEvent("ArrowRight", false) } else { keyEvent("ArrowLeft", false) keyEvent("ArrowRight", false) } if (ey > cy) { keyEvent("ArrowUp", false) keyEvent("ArrowDown", true) } else if (ey < cy) { keyEvent("ArrowUp", true) keyEvent("ArrowDown", false) } else { keyEvent("ArrowUp", false) keyEvent("ArrowDown", false) } } let stsText = document.createElement("div") stsText.style.position = "absolute" stsText.style.margin = "15px" stsText.style.color = "white" stsText.style.fontSize = "20px" stsText.style.fontWeight = "bold" stsText.style.fontFamily = "Ubuntu" stsText.textContent = "No Gamepad connected!" stsText.style.textShadow = "-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black" stsText.style.pointerEvents = "none" let enText = document.createElement("div") enText.style.position = "absolute" enText.style.margin = "15px" enText.style.color = "white" enText.style.fontSize = "15px" enText.style.fontWeight = "bold" enText.style.fontFamily = "Ubuntu" enText.textContent = "Disabled!" enText.style.textShadow = "-1px 0 black, 0 1px black, 1px 0 black, 0 -1px black" enText.style.top = "20px" enText.style.pointerEvents = "none" let crosshair = document.createElement("img") crosshair.style.position = "absolute" crosshair.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAYAAADgKtSgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACjSURBVEhL1Y5BDsUgCEQ9SJe9/816Bqs2kAHFIrGLvmSSysD7Py2QIdvJ13H+S05ClFPCsKRKdbAvWUJI8W11JS74mL4XZq9YBzgn2nswHzJb9sx1J5gtmvIao2ORXuoS6J5id1iOgaJLoBPoJUT8I6DNjE4wW/TMdddhLY/k7W386BB9wHHMXPAhHuvviJjoRBjsS8KwZKdUg/LtfCuHOEjpBh0tTqQ2XaPuAAAAAElFTkSuQmCC" crosshair.style.pointerEvents = "none" crosshair.style.visibility = "hidden" crosshair.style.margin = 0 let movArrow = document.createElement("img") movArrow.style.position = "absolute" movArrow.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAlCAYAAAAA7LqSAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEaSURBVFhH1ZYJCgMhEAQ1//+zYUQXSTxanWsLFiEIWvaMJiiQyidKLKMUPQGRNSVFZimwr2slUmFb/1NGK9h6xzqRlqu9WCfScpWOqkhKy70ey9Q42Wp1RhWJEaqirVKjySoSxG8igBAsY9ojYKlBB23e7IAMsZzk4tYiGTCdId0eAU9JhNOLwNM7kjlNx51IBZR5JrkVIcASz5Pc9ciIVe+4TqRldbivEXl9IiSA/JVxLbLzprgVQVIoX8adCFpKZXygH1TuWuRKPxGoqIkQI5mdXhhhXlocEoSpCFhKW6aqfcKVQsvW5E3+DodEbhp6hqoIwPF+PL0jV4fqIRGWPVgnwnaQVomwryspQvRkRNaUFiFaGaH1QvgCHmRUMUA6MH0AAAAASUVORK5CYII=" movArrow.style.pointerEvents = "none" movArrow.style.visibility = "hidden" movArrow.style.margin = 0 movArrow.style.padding = 0 movArrow.style.transformOrigin = "center center" movArrow.width = 40 document.addEventListener("DOMContentLoaded", () => { document.body.appendChild(movArrow) document.body.appendChild(crosshair) document.body.appendChild(stsText) document.body.appendChild(enText) }) let gamepadControls = { A: 0, B: 0, X: 0, Y: 0 } let gamepadRangeX = window.innerWidth let gamepadRangeY = window.innerHeight // buttons[0] A // buttons[1] B // buttons[2] X // buttons[3] Y // buttons[4] LB // buttons[5] RB // buttons[6] LT // buttons[7] RT let gamepad setInterval(() => { let gamepads = navigator.getGamepads().find((x) => x !== null) if (gamepads) { gamepad = gamepads stsText.textContent = "Gamepad connected!" } else { gamepad = undefined stsText.textContent = "No Gamepad connected!" } if (enabled) { enText.textContent = "Enabled!" if (gamepad) { crosshair.style.visibility = "visible" movArrow.style.visibility = "visible" let target = gamepad.axes.slice(0, 2).map((x) => Math.round(x)) let cursorPos = gamepad.axes.slice(2, 4).map((x) => x + 1) cursorPos[0] *= gamepadRangeX cursorPos[1] *= gamepadRangeY cursorPos[0] -= gamepadRangeX / 2 cursorPos[1] -= gamepadRangeY / 2 if (cursorPos[0] > window.innerWidth) cursorPos[0] = window.innerWidth if (cursorPos[0] < 0) cursorPos[0] = 0 if (cursorPos[1] > window.innerHeight) cursorPos[1] = window.innerHeight if (cursorPos[1] < 0) cursorPos[1] = 0 if (gamepad.buttons[6].pressed) { keyEvent("ShiftLeft", true) } else { keyEvent("ShiftLeft", false) } if (gamepad.buttons[0].pressed) { gamepadControls.A++ } else { gamepadControls.A = 0 } if (gamepad.buttons[1].pressed) { gamepadControls.B++ } else { gamepadControls.B = 0 } if (gamepad.buttons[2].pressed) { gamepadControls.X++ } else { gamepadControls.X = 0 } if (gamepad.buttons[3].pressed) { gamepadControls.Y++ } else { gamepadControls.Y = 0 } if (gamepadControls.A === 1) { keyEvent(commandKeys.autofire, true) keyEvent(commandKeys.autofire, false) } if (gamepadControls.B === 1) { keyEvent(commandKeys.autospin, true) keyEvent(commandKeys.autospin, false) } if (gamepadControls.X === 1) { keyEvent(commandKeys.override, true) keyEvent(commandKeys.override, false) } if (gamepadControls.Y === 1) { keyEvent(commandKeys.takeControl, true) keyEvent(commandKeys.takeControl, false) } crosshair.style.left = cursorPos[0] - 11.5 + "px" crosshair.style.top = cursorPos[1] - 11.5 + "px" if (target[0] || target[1]) { let dir = Math.atan2(target[1], target[0]) movArrow.style.transform = `rotate(${dir}rad)` movArrow.style.left = ((window.innerWidth / 2) + Math.cos(dir) * 75) - 20 + "px" movArrow.style.top = ((window.innerHeight / 2) + Math.sin(dir) * 75) - 15 + "px" } else { movArrow.style.visibility = "hidden" } eightDirMoveTo(0, 0, target[0], target[1]) mouseEvent( cursorPos[0], cursorPos[1], 0, gamepad.buttons[7].pressed ? "mousedown" : "mouseup" ) } else { crosshair.style.visibility = "hidden" movArrow.style.visibility = "hidden" } } else { enText.textContent = "Disabled!" crosshair.style.visibility = "hidden" movArrow.style.visibility = "hidden" } }) // empty space wooo