MooMoo.io Reload Timer

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

当前为 2023-03-18 提交的版本,查看 最新版本

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