MooMoo.io Reload Timer

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

当前为 2023-11-02 提交的版本,查看 最新版本

  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. // @require https://greasyfork.org/scripts/478839-moomoo-io-packet-code/code/MooMooio%20Packet%20Code.js?version=1274028
  9. // @run-at document-start
  10. // @grant unsafeWindow
  11. // @license MIT
  12. // @version 0.4
  13. // @namespace https://greasyfork.org/users/999838
  14. // ==/UserScript==
  15.  
  16. ;(async () => {
  17. unsafeWindow.reloadTimer = true
  18.  
  19. let weaponSpeed = [300, 400, 400, 300, 300, 700, 300, 100, 400, 600, 400, 0, 700, 230, 700, 1500]
  20. let weaponSrc = [
  21. "hammer_1",
  22. "axe_1",
  23. "great_axe_1",
  24. "sword_1",
  25. "samurai_1",
  26. "spear_1",
  27. "bat_1",
  28. "dagger_1",
  29. "stick_1",
  30. "bow_1",
  31. "great_hammer_1",
  32. "shield_1",
  33. "crossbow_1",
  34. "crossbow_2",
  35. "grab_1",
  36. "musket_1"
  37. ]
  38. var myPlayer,
  39. mySID,
  40. inGame = false,
  41. reloads = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  42. var now, delta, lastUpdate
  43. const reloadTimer1 = document.createElement("div")
  44. reloadTimer1.id = "reloadTimer1"
  45. reloadTimer1.className = "resourceDisplay"
  46. reloadTimer1.innerText = "0"
  47.  
  48. const reloadTimer2 = document.createElement("div")
  49. reloadTimer2.id = "reloadTimer2"
  50. reloadTimer2.className = "resourceDisplay"
  51. reloadTimer2.innerText = "-"
  52.  
  53. await new Promise(async (resolve) => {
  54. let { send } = WebSocket.prototype
  55.  
  56. WebSocket.prototype.send = function (...x) {
  57. send.apply(this, x)
  58. this.send = send
  59. this.addEventListener("message", (e) => {
  60. if (!e.origin.includes("moomoo.io") && unsafeWindow.privateServer) return
  61. const [packet, data] = msgpack.decode(new Uint8Array(e.data))
  62. switch (packet) {
  63. case OLDPACKETCODE.RECEIVE["1"]:
  64. inGame = true
  65. mySID = data[0]
  66. break
  67. case OLDPACKETCODE.RECEIVE["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 OLDPACKETCODE.RECEIVE["7"]:
  72. if (data[0] == mySID) reloads[data[2]] = weaponSpeed[data[2]]
  73. break
  74. case OLDPACKETCODE.RECEIVE["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) reloads[projectileID] = weaponSpeed[projectileID]
  96. }
  97. break
  98. }
  99. })
  100. resolve(this)
  101. }
  102. })
  103.  
  104. function updateReload() {
  105. now = Date.now()
  106. delta = now - lastUpdate
  107. lastUpdate = now
  108. if (inGame && myPlayer) {
  109. if (myPlayer.buildIndex == -1) {
  110. reloads[myPlayer.weaponIndex] = Math.max(0, reloads[myPlayer.weaponIndex] - delta)
  111. }
  112. if (myPlayer.weapons[0] != null) {
  113. reloadTimer1.style.backgroundImage = `url(../img/weapons/${weaponSrc[myPlayer.weapons[0]]}.png)`
  114. reloadTimer1.innerText = reloads[myPlayer.weapons[0]]
  115. }
  116. if (myPlayer.weapons[1] != null) {
  117. reloadTimer2.style.backgroundImage = `url(../img/weapons/${weaponSrc[myPlayer.weapons[1]]}.png)`
  118. reloadTimer2.style.backgroundColor = "rgba(0, 0, 0, 0.25)"
  119. reloadTimer2.innerText = reloads[myPlayer.weapons[1]]
  120. } else {
  121. reloadTimer2.style.backgroundImage = null
  122. reloadTimer2.style.backgroundColor = null
  123. reloadTimer2.innerText = "-"
  124. }
  125. }
  126. unsafeWindow.requestAnimationFrame(updateReload)
  127. }
  128. lastUpdate = Date.now()
  129. unsafeWindow.requestAnimationFrame(updateReload)
  130.  
  131. function waitForElm(selector) {
  132. return new Promise((resolve) => {
  133. if (document.querySelector(selector)) {
  134. return resolve(document.querySelector(selector))
  135. }
  136.  
  137. const observer = new MutationObserver((mutations) => {
  138. if (document.querySelector(selector)) {
  139. resolve(document.querySelector(selector))
  140. observer.disconnect()
  141. }
  142. })
  143.  
  144. observer.observe(document.body, {
  145. childList: true,
  146. subtree: true
  147. })
  148. })
  149. }
  150.  
  151. const symbol = Symbol("minimapCounter")
  152. Object.defineProperty(Object.prototype, "minimapCounter", {
  153. get() {
  154. return this[symbol]
  155. },
  156. set(value) {
  157. this[symbol] = value
  158. if (this.isPlayer === true && this.sid === mySID) {
  159. myPlayer = this
  160. }
  161. },
  162. configurable: true
  163. })
  164.  
  165. waitForElm("#topInfoHolder").then((topInfoHolder) => {
  166. const style = document.createElement("style")
  167. style.innerHTML = `
  168. #reloadTimer1 {
  169. right: 0px;
  170. margin-top: 65px;
  171. color: #fff;
  172. font-size: 28px;
  173. background-color: rgba(0, 0, 0, 0.25);
  174. -webkit-border-radius: 4px;
  175. -moz-border-radius: 4px;
  176. border-radius: 4px;
  177. }
  178.  
  179. #reloadTimer2 {
  180. right: 0px;
  181. margin-top: 120px;
  182. color: #fff;
  183. font-size: 28px;
  184. -webkit-border-radius: 4px;
  185. -moz-border-radius: 4px;
  186. border-radius: 4px;
  187. }
  188. `
  189. document.head.appendChild(style)
  190.  
  191. topInfoHolder.appendChild(reloadTimer1)
  192. topInfoHolder.appendChild(reloadTimer2)
  193. })
  194. })()