Diep.io build selector

Allows adding, editing, and deleting builds dynamically and saves them on the go.

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

  1. // ==UserScript==
  2. // @name Diep.io build selector
  3. // @match *://diep.io/*
  4. // @version 1.4.1
  5. // @description Allows adding, editing, and deleting builds dynamically and saves them on the go.
  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. for (let i = 0; i < buildString.length; i++) {
  52. count[buildString[i] - 1]++;
  53. }
  54.  
  55. let result = "";
  56. while (result.length < buildString.length) {
  57. let max = 0;
  58. let maxValue = null;
  59. for (let i = 0; i < count.length; i++) {
  60. if (count[i] > max) {
  61. max = count[i];
  62. maxValue = i + 1;
  63. }
  64. }
  65. result += maxValue.toString();
  66. count[maxValue - 1]--;
  67. }
  68.  
  69. return result;
  70. }
  71.  
  72. function determineBuildType(values) {
  73. const damageStats = values[4] + values[5];
  74. const ramStats = values[1] + values[2];
  75.  
  76. if (damageStats > ramStats) {
  77. return "damage";
  78. } else if (ramStats > damageStats) {
  79. return "ram";
  80. } else {
  81. return "balanced";
  82. }
  83. }
  84.  
  85. function selectBuild(build) {
  86. const buildType = determineBuildType(build.values);
  87. const initialPoints = buildType === "damage" ? "65" : buildType === "ram" ? "23" : "";
  88.  
  89. const buildString = initialPoints + optimizeBuildString(convertBuildToString(build));
  90. sendCommand(`game_stats_build ${buildString}`);
  91. console.log(`Build order: ${buildString}`);
  92. closeSubmenus();
  93. }
  94.  
  95. function createButton(label, icon, clickHandler) {
  96. const button = document.createElement("button");
  97. button.innerHTML = icon + " " + label;
  98. button.style.marginTop = "10px";
  99. button.style.backgroundColor = "rgba(0, 0, 0, 0.7)";
  100. button.style.color = "white";
  101. button.style.border = "none";
  102. button.style.cursor = "pointer";
  103. button.style.padding = "5px 10px";
  104. button.addEventListener("click", clickHandler);
  105. return button;
  106. }
  107.  
  108. function showManageBuildsMenu() {
  109. let menu = document.querySelector("#manageBuildsMenu");
  110.  
  111. if (menu) {
  112. menu.parentNode.removeChild(menu);
  113. closeSubmenus();
  114. return;
  115. }
  116.  
  117. menu = document.createElement("div");
  118. menu.id = "manageBuildsMenu";
  119. 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;";
  120.  
  121. builds.forEach((build, index) => {
  122. const buildElement = document.createElement("div");
  123. buildElement.classList.add("menu-item");
  124. buildElement.style.cssText = "font-family: sans-serif; display: flex; justify-content: space-between; align-items: center;";
  125.  
  126. const buildInfo = document.createElement("span");
  127. buildInfo.innerHTML = `${build.name}`;
  128. buildInfo.style.flex = "1";
  129.  
  130. const editButton = createButton("", "✎", (event) => {
  131. event.stopPropagation();
  132. editBuild(index);
  133. });
  134.  
  135. const deleteButton = createButton("", "⛌", (event) => {
  136. event.stopPropagation();
  137. deleteBuild(index);
  138. });
  139.  
  140. buildElement.appendChild(buildInfo);
  141. buildElement.appendChild(editButton);
  142. buildElement.appendChild(deleteButton);
  143.  
  144. menu.appendChild(buildElement);
  145. });
  146.  
  147. menu.appendChild(createButton("Add New Build", "➕", addNewBuild));
  148. menu.appendChild(createButton("Close", "➖", () => menu.parentNode.removeChild(menu)));
  149.  
  150. document.body.appendChild(menu);
  151. }
  152.  
  153. function editBuild(index) {
  154. let buildName = prompt("Enter the new name of the build:", builds[index].name);
  155. if (!buildName) return;
  156.  
  157. let buildValues = prompt("Enter the new build values (e.g., 0/2/3/0/7/7/7/7):", builds[index].values.join('/'));
  158. if (!buildValues) return;
  159.  
  160. buildValues = buildValues.split("/").map(Number);
  161. if (buildValues.length !== 8) {
  162. alert("Invalid build values. There must be 8 values.");
  163. return;
  164. }
  165.  
  166. builds[index] = { name: buildName, values: buildValues };
  167. saveBuilds(builds);
  168. showManageBuildsMenu();
  169. updateBuildMenu(); // Update build menu after editing
  170. }
  171.  
  172. function deleteBuild(index) {
  173. if (confirm("Are you sure you want to delete the build ${builds[index].name}?")) {
  174. builds.splice(index, 1);
  175. saveBuilds(builds);
  176. showManageBuildsMenu();
  177. updateBuildMenu(); // Update build menu after deleting
  178. }
  179. }
  180.  
  181. function addNewBuild() {
  182. let buildName = prompt("Enter the name of the new build:");
  183. if (!buildName) return;
  184.  
  185. let buildValues = prompt("Enter the build values (e.g., 0/2/3/0/7/7/7/7):");
  186. if (!buildValues) return;
  187.  
  188. buildValues = buildValues.split("/").map(Number);
  189. if (buildValues.length !== 8) {
  190. alert("Invalid build values. There must be 8 values.");
  191. return;
  192. }
  193.  
  194. let newBuild = { name: buildName, values: buildValues };
  195. builds.push(newBuild);
  196. saveBuilds(builds);
  197. showManageBuildsMenu();
  198. updateBuildMenu(); // Update build menu after adding new build
  199. }
  200.  
  201. function closeSubmenus() {
  202. document.querySelectorAll("#buildMenu, #manageBuildsMenu, #buildPreview").forEach(menu => menu.parentNode.removeChild(menu));
  203. }
  204.  
  205. document.addEventListener("keydown", function(event) {
  206. if (event.key === "r") {
  207. showBuilds();
  208. let values = document.querySelector(".build-values");
  209. if (values) {
  210. values.parentNode.removeChild(values);
  211. }
  212. }
  213. });
  214.  
  215. function showBuilds() {
  216. let menu = document.querySelector("#buildMenu");
  217.  
  218. if (menu) {
  219. menu.parentNode.removeChild(menu);
  220. closeSubmenus();
  221. return;
  222. }
  223.  
  224. menu = document.createElement("div");
  225. menu.id = "buildMenu";
  226. 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;";
  227.  
  228. const buildPreview = document.createElement("div");
  229. buildPreview.id = "buildPreview";
  230. 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;";
  231. document.body.appendChild(buildPreview);
  232.  
  233. builds.forEach(build => {
  234. let buildElement = document.createElement("div");
  235. buildElement.classList.add("menu-item");
  236. buildElement.innerHTML = build.name;
  237. buildElement.style.cssText = "cursor: pointer; font-family: sans-serif;";
  238. buildElement.addEventListener("click", () => {
  239. selectBuild(build);
  240. closeSubmenus();
  241. });
  242. buildElement.addEventListener("mouseover", () => {
  243. buildPreview.innerHTML = build.values.join("/");
  244. buildPreview.style.display = "block";
  245. });
  246. buildElement.addEventListener("mouseout", () => {
  247. buildPreview.style.display = "none";
  248. });
  249. menu.appendChild(buildElement);
  250. });
  251.  
  252. const manageBuildsButton = createButton("Manage Builds", "", showManageBuildsMenu);
  253. menu.appendChild(manageBuildsButton);
  254.  
  255. document.body.appendChild(menu);
  256. }
  257.  
  258. function updateBuildMenu() {
  259. closeSubmenus();
  260. showBuilds();
  261. }