🐭️ Mousehunt - Location Catches

View your mouse catches in your current location.

目前为 2023-04-01 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name 🐭️ Mousehunt - Location Catches
  3. // @version 1.2.1
  4. // @description View your mouse catches in your current location.
  5. // @license MIT
  6. // @author bradp
  7. // @namespace bradp
  8. // @match https://www.mousehuntgame.com/*
  9. // @icon https://i.mouse.rip/mouse.png
  10. // @grant none
  11. // @run-at document-end
  12. // @require https://cdn.jsdelivr.net/npm/mousehunt-utils@1.2.0/mousehunt-utils.js
  13. // ==/UserScript==
  14.  
  15. ((function () {
  16. 'use strict';
  17.  
  18. /**
  19. * Get the mouse stats.
  20. *
  21. * @return {Object} The mouse stats.
  22. */
  23. const getMouseStats = async () => {
  24. const data = await doRequest(
  25. 'managers/ajax/mice/mouse_list.php',
  26. {
  27. action: 'get_environment',
  28. category: user.environment_type, // eslint-disable-line no-undef
  29. user_id: user.user_id, // eslint-disable-line no-undef
  30. display_mode: 'stats',
  31. view: 'ViewMouseListEnvironments',
  32. }
  33. );
  34.  
  35. // Grab the data from the response.
  36. const mouseData = data?.mouse_list_category?.subgroups[ 0 ]?.mice;
  37.  
  38. // Reorder by the num_catches key.
  39. mouseData.sort((a, b) => {
  40. return b.num_catches - a.num_catches;
  41. });
  42.  
  43. // Return the data.
  44. return mouseData ? mouseData : [];
  45. };
  46.  
  47. /**
  48. * Build the markup for the stats.
  49. *
  50. * @param {Object} mouseData The mouse data.
  51. *
  52. * @return {Node} The node to append.
  53. */
  54. const buildMouseMarkup = (mouseData) => {
  55. // Fallbacks for mouse data.
  56. const mouse = Object.assign({}, {
  57. name: '',
  58. type: '',
  59. image: '',
  60. crown: 'none',
  61. num_catches: 0,
  62. }, mouseData);
  63.  
  64. const mouseEl = document.createElement('a');
  65. mouseEl.classList.add('mh-catch-stats');
  66.  
  67. mouseEl.title = mouse.name;
  68. mouseEl.addEventListener('click', () => {
  69. if ('undefined' !== hg?.views?.MouseView?.show) { // eslint-disable-line no-undef
  70. hg.views.MouseView.show(mouse.type); // eslint-disable-line no-undef
  71. }
  72. });
  73.  
  74. // Create the image element.
  75. const image = document.createElement('div');
  76. image.classList.add('mh-catch-stats-image');
  77. image.style.backgroundImage = `url('${mouse.image}')`;
  78.  
  79. // If the mouse has a crown, add it.
  80. if (mouse.crown && 'none' !== mouse.crown) {
  81. const crown = document.createElement('div');
  82. crown.classList.add('mh-catch-stats-crown');
  83. crown.style.backgroundImage = `url('https://www.mousehuntgame.com/images/ui/crowns/crown_${mouse.crown}.png')`;
  84. image.appendChild(crown);
  85. }
  86.  
  87. // Create the name element.
  88. const name = document.createElement('div');
  89. name.classList.add('mh-catch-stats-name');
  90. name.innerText = mouse.name;
  91.  
  92. // Create a wrapper for the name and image.
  93. const imageNameContainer = document.createElement('div');
  94. imageNameContainer.appendChild(image);
  95. imageNameContainer.appendChild(name);
  96.  
  97. // Create the catches element.
  98. const catches = document.createElement('div');
  99. catches.classList.add('mh-catch-stats-catches');
  100. catches.innerText = mouse.num_catches;
  101.  
  102. mouseEl.appendChild(imageNameContainer);
  103. mouseEl.appendChild(catches);
  104.  
  105. return mouseEl;
  106. };
  107.  
  108. /**
  109. * Show the stat modal.
  110. */
  111. const showModal = async () => {
  112. // Remove the existing modal.
  113. const existing = document.getElementById('mh-catch-stats');
  114. if (existing) {
  115. existing.remove();
  116. }
  117.  
  118. // Create the modal.
  119. const modalWrapper = document.createElement('div');
  120. modalWrapper.id = 'mh-catch-stats';
  121.  
  122. // Create the wrapper.
  123. const modal = document.createElement('div');
  124. modal.classList.add('mh-catch-stats-wrapper');
  125.  
  126. // Create the header.
  127. const header = document.createElement('div');
  128. header.classList.add('mh-catch-stats-header');
  129.  
  130. // Add the title;
  131. const title = document.createElement('h1');
  132. title.innerText = 'Mouse Catch Stats';
  133. header.appendChild(title);
  134.  
  135. // Create a close button icon.
  136. const closeIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  137. closeIcon.classList.add('mh-catch-stats-close');
  138. closeIcon.setAttribute('viewBox', '0 0 24 24');
  139. closeIcon.setAttribute('width', '18');
  140. closeIcon.setAttribute('height', '18');
  141. closeIcon.setAttribute('fill', 'none');
  142. closeIcon.setAttribute('stroke', 'currentColor');
  143. closeIcon.setAttribute('stroke-width', '1.5');
  144.  
  145. // Create the path.
  146. const closePath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  147. closePath.setAttribute('d', 'M18 6L6 18M6 6l12 12');
  148. closeIcon.appendChild(closePath);
  149.  
  150. // Close the modal when the icon is clicked.
  151. closeIcon.addEventListener('click', () => {
  152. modalWrapper.remove();
  153. });
  154.  
  155. // Append the button.
  156. header.appendChild(closeIcon);
  157.  
  158. // Add the header to the modal.
  159. modal.appendChild(header);
  160.  
  161. // Make the mouse stats table.
  162. const mouseBody = document.createElement('div');
  163. mouseBody.classList.add('mh-catch-stats-body');
  164.  
  165. // Get the mouse stats.
  166. const mouseStats = await getMouseStats();
  167.  
  168. // Loop through the stats and add them to the modal.
  169. mouseStats.forEach((mouseData) => {
  170. mouseBody.appendChild(buildMouseMarkup(mouseData, mouseBody));
  171. });
  172.  
  173. // Add the mouse stats to the modal.
  174. modal.appendChild(mouseBody);
  175.  
  176. // Add the modal to the wrapper.
  177. modalWrapper.appendChild(modal);
  178.  
  179. // Add the wrapper to the body.
  180. document.body.appendChild(modalWrapper);
  181.  
  182. // Make the modal draggable.
  183. makeElementDraggable('#mh-catch-stats', '.mh-catch-stats-header', 25, 25, 'mh-catch-stats-position');
  184. };
  185.  
  186. addStyles(`#mh-catch-stats {
  187. position: absolute;
  188. top: 25px;
  189. left: 25px;
  190. z-index: 50;
  191. }
  192.  
  193. .mh-catch-stats-wrapper {
  194. width: 275px;
  195. background: #f6f3eb;
  196. border: 1px solid #534022;
  197. box-shadow: 1px 1px 1px 0px #9d917f, 1px 3px 5px 0px #6c6c6c;
  198. transition: box-shadow .25s;
  199. }
  200.  
  201. .mh-is-dragging .mh-catch-stats-wrapper {
  202. box-shadow: 1px 1px 1px 0px #9d917f, 0px 7px 9px 2px #6c6c6c;
  203. }
  204.  
  205. .mh-catch-stats-header {
  206. display: flex;
  207. justify-content: space-between;
  208. align-items: center;
  209. border-bottom: 1px solid #ceb7a6;
  210. background-color: #926944;
  211. padding: 10px;
  212. color: #f6f3eb;
  213. cursor: -webkit-grab;
  214. cursor: grab;
  215. }
  216.  
  217. .mh-catch-stats-header h1 {
  218. color: #f6f3eb;
  219. }
  220.  
  221. .mh-catch-stats-close {
  222. cursor: pointer;
  223. }
  224.  
  225. .mh-catch-stats-close:hover {
  226. outline: 1px solid #ccc;
  227. background-color: #eee;
  228. border-radius: 50%;
  229. color: #926944;
  230. }
  231.  
  232. .mh-catch-stats-body {
  233. max-height: 90vh;
  234. overflow-y: scroll;
  235. overflow-x: hidden;
  236. }
  237.  
  238. .mh-catch-stats-wrapper .mh-catch-stats:nth-child(odd) {
  239. background-color: #e8e3d7;
  240. }
  241.  
  242. .mh-catch-stats {
  243. display: flex;
  244. justify-content: space-between;
  245. padding: 2px 0;
  246. align-items: center;
  247. padding: 10px 10px;
  248. color: #000;
  249. }
  250.  
  251. .mh-catch-stats:hover,
  252. .mh-catch-stats-wrapper .mh-catch-stats:nth-child(odd):hover {
  253. outline: 1px solid #ccc;
  254. background-color: #eee;
  255. text-decoration: none;
  256. color: #665f5f;
  257. }
  258.  
  259. .mh-catch-stats-image {
  260. position: relative;
  261. width: 40px;
  262. height: 40px;
  263. display: inline-block;
  264. vertical-align: middle;
  265. background-size: contain;
  266. background-repeat: no-repeat;
  267. border-radius: 2px;
  268. box-shadow: 1px 1px 1px #999;
  269. }
  270.  
  271. .mh-catch-stats-crown {
  272. position: absolute;
  273. right: -5px;
  274. bottom: -5px;
  275. width: 20px;
  276. height: 20px;
  277. background-repeat: no-repeat;
  278. background-position: 50% 50%;
  279. background-color: #fff;
  280. border: 1px solid #333;
  281. background-size: 80%;
  282. border-radius: 50%;
  283. }
  284.  
  285. .mh-catch-stats-name {
  286. display: inline-block;
  287. vertical-align: middle;
  288. padding-left: 10px;
  289. }
  290.  
  291. .mh-catch-stats-catches {
  292. padding-right: 5px;
  293. }
  294. `);
  295.  
  296. addSubmenuItem({
  297. menu: 'mice',
  298. label: 'Location Catch Stats',
  299. icon: 'https://www.mousehuntgame.com/images/ui/hud/menu/prize_shoppe.png?',
  300. callback: showModal
  301. });
  302. })());