MooMoo.io Reload Timer

Helps you determine the reload time of your weapon(s)

当前为 2023-04-08 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name MooMoo.io Reload Timer
  3. // @description Helps you determine the reload time of your weapon(s)
  4. // @author KOOKY WARRIOR
  5. // @match *://*.moomoo.io/*
  6. // @icon https://moomoo.io/img/favicon.png?v=1
  7. // @require https://cdnjs.cloudflare.com/ajax/libs/msgpack-lite/0.1.26/msgpack.min.js
  8. // @run-at document-start
  9. // @grant unsafeWindow
  10. // @license MIT
  11. // @version 0.2
  12. // @namespace https://greasyfork.org/users/999838
  13. // ==/UserScript==
  14.  
  15. ;(async () => {
  16. unsafeWindow.reloadTimer = true
  17.  
  18. let weaponSpeed = [
  19. 300, 400, 400, 300, 300, 700, 300, 100, 400, 600, 400, 0, 700, 230, 700, 1500
  20. ]
  21. let weaponSrc = [
  22. "hammer_1",
  23. "axe_1",
  24. "great_axe_1",
  25. "sword_1",
  26. "samurai_1",
  27. "spear_1",
  28. "bat_1",
  29. "dagger_1",
  30. "stick_1",
  31. "bow_1",
  32. "great_hammer_1",
  33. "shield_1",
  34. "crossbow_1",
  35. "crossbow_2",
  36. "grab_1",
  37. "musket_1"
  38. ]
  39. var myPlayer,
  40. mySID,
  41. inGame = false,
  42. reloads = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  43. var now, delta, lastUpdate
  44. const reloadTimer1 = document.createElement("div")
  45. reloadTimer1.id = "reloadTimer1"
  46. reloadTimer1.className = "resourceDisplay"
  47. reloadTimer1.innerText = "0"
  48.  
  49. const reloadTimer2 = document.createElement("div")
  50. reloadTimer2.id = "reloadTimer2"
  51. reloadTimer2.className = "resourceDisplay"
  52. reloadTimer2.innerText = "-"
  53.  
  54. await new Promise(async (resolve) => {
  55. let { send } = WebSocket.prototype
  56.  
  57. WebSocket.prototype.send = function (...x) {
  58. send.apply(this, x)
  59. this.send = send
  60. this.addEventListener("message", (e) => {
  61. const [packet, data] = msgpack.decode(new Uint8Array(e.data))
  62. switch (packet) {
  63. case "1":
  64. inGame = true
  65. mySID = data[0]
  66. break
  67. case "11":
  68. inGame = false
  69. reloads = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  70. break
  71. case "7":
  72. if (data[0] == mySID) reloads[data[2]] = weaponSpeed[data[2]]
  73. break
  74. case "18":
  75. if ([1000, 1200, 1400].includes(data[3])) {
  76. let projectileID
  77. switch (data[5]) {
  78. case 0:
  79. projectileID = 9
  80. break
  81. case 2:
  82. projectileID = 12
  83. break
  84. case 3:
  85. projectileID = 13
  86. break
  87. case 5:
  88. projectileID = 15
  89. break
  90. default:
  91. projectileID = null
  92. }
  93. let x = data[0] - Math.cos(data[2]) * 35
  94. let y = data[1] - Math.sin(data[2]) * 35
  95. if (Math.sqrt((x -= myPlayer.x) * x + (y -= myPlayer.y) * y) <= 70)
  96. reloads[projectileID] = weaponSpeed[projectileID]
  97. }
  98. break
  99. }
  100. })
  101. resolve(this)
  102. }
  103. })
  104.  
  105. function updateReload() {
  106. now = Date.now()
  107. delta = now - lastUpdate
  108. lastUpdate = now
  109. if (inGame && myPlayer) {
  110. if (myPlayer.buildIndex == -1) {
  111. reloads[myPlayer.weaponIndex] = Math.max(
  112. 0,
  113. reloads[myPlayer.weaponIndex] - delta
  114. )
  115. }
  116. if (myPlayer.weapons[0] != null) {
  117. reloadTimer1.style.backgroundImage = `url(../img/weapons/${
  118. weaponSrc[myPlayer.weapons[0]]
  119. }.png)`
  120. reloadTimer1.innerText = reloads[myPlayer.weapons[0]]
  121. }
  122. if (myPlayer.weapons[1] != null) {
  123. reloadTimer2.style.backgroundImage = `url(../img/weapons/${
  124. weaponSrc[myPlayer.weapons[1]]
  125. }.png)`
  126. reloadTimer2.style.backgroundColor = "rgba(0, 0, 0, 0.25)"
  127. reloadTimer2.innerText = reloads[myPlayer.weapons[1]]
  128. } else {
  129. reloadTimer2.style.backgroundImage = null
  130. reloadTimer2.style.backgroundColor = null
  131. reloadTimer2.innerText = "-"
  132. }
  133. }
  134. unsafeWindow.requestAnimationFrame(updateReload)
  135. }
  136. lastUpdate = Date.now()
  137. unsafeWindow.requestAnimationFrame(updateReload)
  138.  
  139. function waitForElm(selector) {
  140. return new Promise((resolve) => {
  141. if (document.querySelector(selector)) {
  142. return resolve(document.querySelector(selector))
  143. }
  144.  
  145. const observer = new MutationObserver((mutations) => {
  146. if (document.querySelector(selector)) {
  147. resolve(document.querySelector(selector))
  148. observer.disconnect()
  149. }
  150. })
  151.  
  152. observer.observe(document.body, {
  153. childList: true,
  154. subtree: true
  155. })
  156. })
  157. }
  158.  
  159. const symbol = Symbol("minimapCounter")
  160. Object.defineProperty(Object.prototype, "minimapCounter", {
  161. get() {
  162. return this[symbol]
  163. },
  164. set(value) {
  165. this[symbol] = value
  166. if (this.isPlayer === true && this.sid === mySID) {
  167. myPlayer = this
  168. }
  169. },
  170. configurable: true
  171. })
  172.  
  173. waitForElm("#topInfoHolder").then((topInfoHolder) => {
  174. const style = document.createElement("style")
  175. style.innerHTML = `
  176. #reloadTimer1 {
  177. visibility: visible;
  178. right: 0px;
  179. margin-top: 65px;
  180. color: #fff;
  181. font-size: 28px;
  182. background-color: rgba(0, 0, 0, 0.25);
  183. -webkit-border-radius: 4px;
  184. -moz-border-radius: 4px;
  185. border-radius: 4px;
  186. }
  187.  
  188. #reloadTimer2 {
  189. visibility: visible;
  190. right: 0px;
  191. margin-top: 120px;
  192. color: #fff;
  193. font-size: 28px;
  194. -webkit-border-radius: 4px;
  195. -moz-border-radius: 4px;
  196. border-radius: 4px;
  197. }
  198. `
  199. document.head.appendChild(style)
  200.  
  201. topInfoHolder.appendChild(reloadTimer1)
  202. topInfoHolder.appendChild(reloadTimer2)
  203. })
  204. })()