Diep.io build selector

Allows adding, editing, and deleting builds dynamically and saves them using Tampermonkey's storage.

当前为 2024-06-26 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Diep.io build selector
  3. // @match *://diep.io/*
  4. // @version 1.4.0
  5. // @description Allows adding, editing, and deleting builds dynamically and saves them using Tampermonkey's storage.
  6. // @icon https://i.imgur.com/pvqsu5e.png
  7. // @license GNU GPLv3
  8. // @grant GM_getValue
  9. // @grant GM_setValue
  10. // @grant GM_addStyle
  11. // @grant GM_registerMenuCommand
  12. // @grant GM_unregisterMenuCommand
  13. // @run-at document-end
  14. // @namespace https://greasyfork.org/users/1003196
  15. // ==/UserScript==
  16.  
  17. function getBuilds() {
  18. const savedBuilds = GM_getValue("builds", null);
  19. return savedBuilds ? JSON.parse(savedBuilds) : [
  20. { name: "Anni", values: [1, 1, 0, 7, 7, 7, 3, 7] },
  21. { name: "Glass", values: [0, 0, 0, 7, 7, 7, 7, 5] },
  22. { name: "Ram", values: [5, 7, 7, 0, 0, 0, 7, 7] },
  23. { name: "OverLord", values: [0, 5, 0, 7, 7, 7, 0, 7] },
  24. { name: "Trapper", values: [5, 7, 0, 0, 7, 7, 7, 0] },
  25. { name: "Necro", values: [0, 0, 0, 7, 6, 7, 6, 7] },
  26. { name: "Spammer", values: [2, 3, 0, 7, 7, 7, 7, 0] },
  27. { name: "Tri-Angle", values: [4, 4, 4, 0, 7, 7, 7, 0] },
  28. { name: "Assassin", values: [2, 3, 0, 7, 7, 7, 3, 4] },
  29. { name: "Predator", values: [0, 0, 0, 6, 7, 7, 7, 6] },
  30. { name: "Penta", values: [1, 3, 0, 5, 6, 6, 7, 5] }
  31. ];
  32. }
  33.  
  34. function saveBuilds(builds) {
  35. GM_setValue("builds", JSON.stringify(builds));
  36. updateBuildMenu(); // Update build menu after saving builds
  37. }
  38.  
  39. let builds = getBuilds();
  40.  
  41. function sendCommand(command) {
  42. input.execute(command);
  43. }
  44.  
  45. function convertBuildToString(build) {
  46. return build.values.map((value, index) => (index + 1).toString().repeat(value)).join('');
  47. }
  48.  
  49. function optimizeBuildString(buildString) {
  50. const count = new Array(8).fill(0);
  51. buildString.split('').forEach(char => count[parseInt(char) - 1]++);
  52. return count.map((count, index) => (index + 1).toString().repeat(count)).join('');
  53. }
  54.  
  55. function determineBuildType(values) {
  56. const damageStats = values[4] + values[5];
  57. const ramStats = values[1] + values[2];
  58.  
  59. if (damageStats > ramStats) {
  60. return "damage";
  61. } else if (ramStats > damageStats) {
  62. return "ram";
  63. } else {
  64. return "balanced";
  65. }
  66. }
  67.  
  68. function selectBuild(build) {
  69. const buildType = determineBuildType(build.values);
  70. const initialPoints = buildType === "damage" ? "65" : buildType === "ram" ? "23" : "";
  71.  
  72. const buildString = initialPoints + optimizeBuildString(convertBuildToString(build));
  73. sendCommand(`game_stats_build ${buildString}`);
  74. closeSubmenus();
  75. }
  76.  
  77. function createButton(label, icon, clickHandler) {
  78. const button = document.createElement("button");
  79. button.innerHTML = icon + " " + label;
  80. button.style.marginTop = "10px";
  81. button.style.backgroundColor = "rgba(0, 0, 0, 0.7)";
  82. button.style.color = "white";
  83. button.style.border = "none";
  84. button.style.cursor = "pointer";
  85. button.style.padding = "5px 10px";
  86. button.addEventListener("click", clickHandler);
  87. return button;
  88. }
  89.  
  90. function showManageBuildsMenu() {
  91. let menu = document.querySelector("#manageBuildsMenu");
  92.  
  93. if (menu) {
  94. menu.parentNode.removeChild(menu);
  95. closeSubmenus();
  96. return;
  97. }
  98.  
  99. menu = document.createElement("div");
  100. menu.id = "manageBuildsMenu";
  101. menu.style.cssText = "position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: rgba(0, 0, 0, 0.7); border: 1px solid grey; padding: 10px; text-align: center; z-index: 9999; color: white;";
  102.  
  103. builds.forEach((build, index) => {
  104. const buildElement = document.createElement("div");
  105. buildElement.classList.add("menu-item");
  106. buildElement.style.cssText = "font-family: sans-serif; display: flex; justify-content: space-between; align-items: center;";
  107.  
  108. const buildInfo = document.createElement("span");
  109. buildInfo.innerHTML = `${build.name}`;
  110. buildInfo.style.flex = "1";
  111.  
  112. const editButton = createButton("", "✎", (event) => {
  113. event.stopPropagation();
  114. editBuild(index);
  115. });
  116.  
  117. const deleteButton = createButton("", "⛌", (event) => {
  118. event.stopPropagation();
  119. deleteBuild(index);
  120. });
  121.  
  122. buildElement.appendChild(buildInfo);
  123. buildElement.appendChild(editButton);
  124. buildElement.appendChild(deleteButton);
  125.  
  126. menu.appendChild(buildElement);
  127. });
  128.  
  129. menu.appendChild(createButton("Add New Build", "➕", addNewBuild));
  130. menu.appendChild(createButton("Close", "➖", () => menu.parentNode.removeChild(menu)));
  131.  
  132. document.body.appendChild(menu);
  133. }
  134.  
  135. function editBuild(index) {
  136. let buildName = prompt("Enter the new name of the build:", builds[index].name);
  137. if (!buildName) return;
  138.  
  139. let buildValues = prompt("Enter the new build values (e.g., 0/2/3/0/7/7/7/7):", builds[index].values.join('/'));
  140. if (!buildValues) return;
  141.  
  142. buildValues = buildValues.split("/").map(Number);
  143. if (buildValues.length !== 8) {
  144. alert("Invalid build values. There must be 8 values.");
  145. return;
  146. }
  147.  
  148. builds[index] = { name: buildName, values: buildValues };
  149. saveBuilds(builds);
  150. showManageBuildsMenu();
  151. updateBuildMenu(); // Update build menu after editing
  152. }
  153.  
  154. function deleteBuild(index) {
  155. if (confirm("Are you sure you want to delete the build ${builds[index].name}?")) {
  156. builds.splice(index, 1);
  157. saveBuilds(builds);
  158. showManageBuildsMenu();
  159. updateBuildMenu(); // Update build menu after deleting
  160. }
  161. }
  162.  
  163. function addNewBuild() {
  164. let buildName = prompt("Enter the name of the new build:");
  165. if (!buildName) return;
  166.  
  167. let buildValues = prompt("Enter the build values (e.g., 0/2/3/0/7/7/7/7):");
  168. if (!buildValues) return;
  169.  
  170. buildValues = buildValues.split("/").map(Number);
  171. if (buildValues.length !== 8) {
  172. alert("Invalid build values. There must be 8 values.");
  173. return;
  174. }
  175.  
  176. let newBuild = { name: buildName, values: buildValues };
  177. builds.push(newBuild);
  178. saveBuilds(builds);
  179. showManageBuildsMenu();
  180. updateBuildMenu(); // Update build menu after adding new build
  181. }
  182.  
  183. function closeSubmenus() {
  184. document.querySelectorAll("#buildMenu, #manageBuildsMenu, #buildPreview").forEach(menu => menu.parentNode.removeChild(menu));
  185. }
  186.  
  187. document.addEventListener("keydown", function(event) {
  188. if (event.key === "r") {
  189. showBuilds();
  190. let values = document.querySelector(".build-values");
  191. if (values) {
  192. values.parentNode.removeChild(values);
  193. }
  194. }
  195. });
  196.  
  197. function showBuilds() {
  198. let menu = document.querySelector("#buildMenu");
  199.  
  200. if (menu) {
  201. menu.parentNode.removeChild(menu);
  202. closeSubmenus();
  203. return;
  204. }
  205.  
  206. menu = document.createElement("div");
  207. menu.id = "buildMenu";
  208. menu.style.cssText = "position: fixed; top: 50%; right: 0%; transform: translate(0, -50%); background-color: rgba(0, 0, 0, 0.7); border: 1px solid grey; padding: 10px; z-index: 9999; color: white;";
  209.  
  210. const buildPreview = document.createElement("div");
  211. buildPreview.id = "buildPreview";
  212. buildPreview.style.cssText = "position: fixed; bottom: 10px; left: 10px; background-color: rgba(0, 0, 0, 0.5); border: 1px solid grey; padding: 10px; z-index: 10000; color: white; display: none;";
  213. document.body.appendChild(buildPreview);
  214.  
  215. builds.forEach(build => {
  216. let buildElement = document.createElement("div");
  217. buildElement.classList.add("menu-item");
  218. buildElement.innerHTML = build.name;
  219. buildElement.style.cssText = "cursor: pointer; font-family: sans-serif;";
  220. buildElement.addEventListener("click", () => {
  221. selectBuild(build);
  222. closeSubmenus();
  223. });
  224. buildElement.addEventListener("mouseover", () => {
  225. buildPreview.innerHTML = build.values.join("/");
  226. buildPreview.style.display = "block";
  227. });
  228. buildElement.addEventListener("mouseout", () => {
  229. buildPreview.style.display = "none";
  230. });
  231. menu.appendChild(buildElement);
  232. });
  233.  
  234. const manageBuildsButton = createButton("Manage Builds", "", showManageBuildsMenu);
  235. menu.appendChild(manageBuildsButton);
  236.  
  237. document.body.appendChild(menu);
  238. }
  239.  
  240. function updateBuildMenu() {
  241. closeSubmenus();
  242. showBuilds();
  243. }
  244.  
  245. showBuilds();