Greasy Fork

Arras.io Gamepad support

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.

// ==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
// ==/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