HookX Client

Enhanced Sploop.io client with legal mods including custom crosshair and account management

  1. // ==UserScript==
  2. // @name HookX Client
  3. // @namespace http://tampermonkey.net/
  4. // @version 5.3
  5. // @description Enhanced Sploop.io client with legal mods including custom crosshair and account management
  6. // @author hooder
  7. // @match https://sploop.io/*
  8. // @grant none
  9. // @require https://update.greasyfork.org/scripts/130/10066/Portable%20MD5%20Function.js
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. function addStyle(css) {
  16. const style = document.createElement('style');
  17. style.textContent = css;
  18. document.head.appendChild(style);
  19. return style;
  20. }
  21.  
  22. function makeDraggable(element) {
  23. let posX = 0, posY = 0, mouseX = 0, mouseY = 0;
  24. element.onmousedown = dragMouseDown;
  25.  
  26. function dragMouseDown(e) {
  27. if (!isDragging) return;
  28. e.preventDefault();
  29. mouseX = e.clientX;
  30. mouseY = e.clientY;
  31. document.onmouseup = closeDragElement;
  32. document.onmousemove = elementDrag;
  33. }
  34.  
  35. function elementDrag(e) {
  36. e.preventDefault();
  37. posX = mouseX - e.clientX;
  38. posY = mouseY - e.clientY;
  39. mouseX = e.clientX;
  40. mouseY = e.clientY;
  41. const newTop = element.offsetTop - posY;
  42. const newLeft = element.offsetLeft - posX;
  43. element.style.top = Math.max(0, Math.min(newTop, window.innerHeight - element.offsetHeight)) + "px";
  44. element.style.left = Math.max(0, Math.min(newLeft, window.innerWidth - element.offsetWidth)) + "px";
  45. }
  46.  
  47. function closeDragElement() {
  48. document.onmouseup = null;
  49. document.onmousemove = null;
  50. }
  51. }
  52.  
  53. let isDragging = false;
  54. let menuVisible = true;
  55. let currentTheme = 'green';
  56. let pulseSpeed = 1.5;
  57. let spinSpeed = 3.1;
  58.  
  59. addStyle(`
  60. .hookx-menu {
  61. position: fixed;
  62. top: 50px;
  63. left: 50px;
  64. width: 480px;
  65. height: 500px;
  66. background: linear-gradient(135deg, #1a3c34, #1a1a1a);
  67. border: 2px solid #4caf50;
  68. border-radius: 15px;
  69. color: #e0e0e0;
  70. font-family: 'Segoe UI', Arial, sans-serif;
  71. z-index: 10000;
  72. padding: 15px;
  73. box-shadow: 0 0 20px rgba(0, 0, 0, 0.6);
  74. overflow-y: auto;
  75. display: flex;
  76. flex-direction: column;
  77. }
  78. .hookx-menu h2 {
  79. margin: 0 0 10px 0;
  80. text-align: center;
  81. color: #a5d6a7;
  82. cursor: move;
  83. font-size: 24px;
  84. font-weight: 600;
  85. }
  86. .tab-buttons {
  87. display: flex;
  88. justify-content: center;
  89. gap: 10px;
  90. margin-bottom: 15px;
  91. }
  92. .tab-button {
  93. background: #4caf50;
  94. border: none;
  95. padding: 8px 20px;
  96. color: #ffffff;
  97. cursor: pointer;
  98. border-radius: 8px;
  99. transition: all 0.3s;
  100. font-size: 14px;
  101. }
  102. .tab-button:hover {
  103. background: #a5d6a7;
  104. color: #1a1a1a;
  105. }
  106. .tab-content {
  107. display: none;
  108. flex-grow: 1;
  109. }
  110. .tab-content.active {
  111. display: block;
  112. }
  113. .mod-toggle {
  114. margin: 10px 0;
  115. display: flex;
  116. align-items: center;
  117. justify-content: space-between;
  118. padding: 5px 10px;
  119. background: rgba(255, 255, 255, 0.05);
  120. border-radius: 5px;
  121. font-size: 14px;
  122. }
  123. .move-mods-btn {
  124. background: #4caf50;
  125. border: none;
  126. padding: 10px 20px;
  127. color: #ffffff;
  128. cursor: pointer;
  129. border-radius: 8px;
  130. margin-top: 15px;
  131. width: 150px;
  132. align-self: center;
  133. transition: all 0.3s;
  134. font-size: 14px;
  135. }
  136. .move-mods-btn:hover {
  137. background: #a5d6a7;
  138. color: #1a1a1a;
  139. }
  140. .mod-ui {
  141. position: fixed;
  142. padding: 10px;
  143. color: #e0e0e0;
  144. z-index: 1000;
  145. display: none;
  146. border-radius: 5px;
  147. box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
  148. background: rgba(26, 26, 26, 0.8);
  149. font-size: 14px;
  150. }
  151. .keystrokes-ui, .pulse-effect-ui, .crosshair-ui {
  152. display: flex;
  153. flex-direction: column;
  154. gap: 8px;
  155. }
  156. .keystrokes-ui div {
  157. display: flex;
  158. justify-content: center;
  159. gap: 5px;
  160. }
  161. .keystroke-key {
  162. width: 40px;
  163. height: 40px;
  164. background: rgba(255, 255, 255, 0.1);
  165. border: 1px solid #e0e0e0;
  166. border-radius: 5px;
  167. display: flex;
  168. align-items: center;
  169. justify-content: center;
  170. transition: all 0.1s;
  171. }
  172. .keystroke-key.active {
  173. background: rgba(255, 255, 255, 0.8);
  174. color: #000;
  175. }
  176. .arraylist-container {
  177. width: auto;
  178. max-width: 200px;
  179. background: rgba(26, 26, 26, 0.7);
  180. border-radius: 5px;
  181. padding: 5px;
  182. }
  183. .arraylist-item {
  184. padding: 3px 8px;
  185. background: rgba(255, 255, 255, 0.1);
  186. margin: 2px 0;
  187. border-radius: 3px;
  188. transition: all 0.2s;
  189. font-size: 12px;
  190. }
  191. .arraylist-item:hover {
  192. background: rgba(255, 255, 255, 0.2);
  193. }
  194. .player-list {
  195. position: fixed;
  196. top: 50px;
  197. left: 50px;
  198. width: 300px;
  199. max-height: 500px;
  200. background: linear-gradient(135deg, #1a3c34, #1a1a1a);
  201. border: 2px solid #4caf50;
  202. border-radius: 15px;
  203. padding: 15px;
  204. color: #e0e0e0;
  205. font-family: 'Segoe UI', Arial, sans-serif;
  206. overflow-y: auto;
  207. z-index: 9999;
  208. display: none;
  209. box-shadow: 0 0 20px rgba(0, 0, 0, 0.6);
  210. }
  211. .player-list::-webkit-scrollbar {
  212. width: 8px;
  213. }
  214. .player-list::-webkit-scrollbar-thumb {
  215. background: #4caf50;
  216. border-radius: 4px;
  217. }
  218. .player-name {
  219. margin: 5px 0;
  220. font-size: 16px;
  221. opacity: 0;
  222. transition: opacity 0.5s;
  223. }
  224. .join-notification {
  225. position: fixed;
  226. bottom: 20px;
  227. right: 20px;
  228. background: rgba(26, 26, 26, 0.7);
  229. color: #e0e0e0;
  230. padding: 6px 12px;
  231. border-radius: 6px;
  232. font-size: 12px;
  233. opacity: 0;
  234. transition: opacity 0.5s;
  235. z-index: 10001;
  236. }
  237. .theme-buttons-container {
  238. position: fixed;
  239. top: 10%;
  240. left: 5%;
  241. display: none;
  242. flex-direction: column;
  243. gap: 10px;
  244. }
  245. .theme-button {
  246. width: 40px;
  247. height: 40px;
  248. border-radius: 50%;
  249. cursor: pointer;
  250. border: 2px solid #4caf50;
  251. transition: transform 0.3s;
  252. }
  253. .theme-button:hover {
  254. transform: scale(1.1);
  255. }
  256. .pink-button { background: linear-gradient(135deg, #f8bbd0, #ec407a); }
  257. .light-orange-button { background: linear-gradient(135deg, #ffcc80, #ff9800); }
  258. .skye-blue-button { background: linear-gradient(135deg, #81d4fa, #0288d1); }
  259. .green-button { background: linear-gradient(135deg, #a5d6a7, #4caf50); }
  260. .purple-button { background: linear-gradient(135deg, #d1c4e9, #7e57c2); }
  261. .neon-button { background: linear-gradient(135deg, #80deea, #26a69a); }
  262. .red-button { background: linear-gradient(135deg, #ef9a9a, #e53935); }
  263. .yellow-button { background: linear-gradient(135deg, #fff59d, #fbc02d); }
  264. .account-form {
  265. display: flex;
  266. flex-direction: column;
  267. gap: 10px;
  268. margin-bottom: 15px;
  269. }
  270. .account-form input {
  271. padding: 8px;
  272. background: #333;
  273. color: #e0e0e0;
  274. border: 1px solid #4caf50;
  275. border-radius: 5px;
  276. font-size: 14px;
  277. }
  278. .account-form button {
  279. background: #4caf50;
  280. border: none;
  281. padding: 8px;
  282. color: #ffffff;
  283. cursor: pointer;
  284. border-radius: 5px;
  285. font-size: 14px;
  286. }
  287. .account-form button:hover {
  288. background: #a5d6a7;
  289. color: #1a1a1a;
  290. }
  291. .account-list {
  292. overflow-y: auto;
  293. flex-grow: 1;
  294. margin-top: 10px;
  295. }
  296. .account-card {
  297. display: flex;
  298. align-items: center;
  299. justify-content: space-between;
  300. padding: 10px;
  301. margin: 5px 0;
  302. background: rgba(255, 255, 255, 0.05);
  303. border-radius: 5px;
  304. font-size: 14px;
  305. }
  306. .account-buttons {
  307. display: flex;
  308. gap: 10px;
  309. }
  310. .acc-btn {
  311. padding: 5px 15px;
  312. border: none;
  313. border-radius: 5px;
  314. color: #ffffff;
  315. cursor: pointer;
  316. transition: all 0.3s;
  317. font-size: 12px;
  318. }
  319. .acc-btn-switch {
  320. background: #4caf50;
  321. }
  322. .acc-btn-switch:hover {
  323. background: #a5d6a7;
  324. color: #1a1a1a;
  325. }
  326. .acc-btn-remove {
  327. background: #d32f2f;
  328. }
  329. .acc-btn-remove:hover {
  330. background: #ef5350;
  331. }
  332. @keyframes screenPulse {
  333. 0% { transform: scale(1); }
  334. 50% { transform: scale(1.05); }
  335. 100% { transform: scale(1); }
  336. }
  337. @keyframes hitFade {
  338. 0% { opacity: 1; transform: rotate(45deg) scale(1); }
  339. 100% { opacity: 0; transform: rotate(45deg) scale(1.2); }
  340. }
  341. @keyframes swingFade {
  342. 0% { opacity: 1; transform: scale(1); }
  343. 100% { opacity: 0; transform: scale(2); }
  344. }
  345. .crosshair {
  346. position: fixed;
  347. z-index: 99999;
  348. pointer-events: none;
  349. display: none;
  350. transform: translate(-50%, -50%);
  351. will-change: transform;
  352. }
  353. .crosshair.dot {
  354. border-radius: 50%;
  355. }
  356. .crosshair.cross, .crosshair.xcross {
  357. width: 20px;
  358. height: 20px;
  359. }
  360. .crosshair.cross::before, .crosshair.cross::after,
  361. .crosshair.xcross::before, .crosshair.xcross::after {
  362. content: '';
  363. position: absolute;
  364. background-color: currentColor;
  365. }
  366. .crosshair.cross::before {
  367. top: 50%;
  368. left: 0;
  369. width: 100%;
  370. height: 2px;
  371. transform: translateY(-50%);
  372. }
  373. .crosshair.cross::after {
  374. top: 0;
  375. left: 50%;
  376. width: 2px;
  377. height: 100%;
  378. transform: translateX(-50%);
  379. }
  380. .crosshair.xcross::before {
  381. left: 50%;
  382. top: 0;
  383. width: 2px;
  384. height: 100%;
  385. transform: rotate(45deg);
  386. }
  387. .crosshair.xcross::after {
  388. left: 50%;
  389. top: 0;
  390. width: 2px;
  391. height: 100%;
  392. transform: rotate(-45deg);
  393. }
  394. .crosshair.spike {
  395. background-image: url("https://sploop.io/img/entity/hard_spike.png");
  396. background-size: cover;
  397. }
  398. .crosshair.square {
  399. border: 2px solid;
  400. }
  401. .crosshair.triangle {
  402. width: 0;
  403. height: 0;
  404. border-left: 10px solid transparent;
  405. border-right: 10px solid transparent;
  406. border-bottom: 18px solid currentColor;
  407. }
  408. body.hide-cursor * {
  409. cursor: none !important;
  410. }
  411. .crosshair-select, .crosshair-color, .hookx-select, .hookx-color, .hookx-range {
  412. margin: 5px 0;
  413. width: 100%;
  414. padding: 5px;
  415. background: #333;
  416. color: #e0e0e0;
  417. border: 1px solid #4caf50;
  418. border-radius: 4px;
  419. font-size: 12px;
  420. }
  421. .hookx-label {
  422. font-size: 12px;
  423. color: #4caf50;
  424. margin: 5px 0 2px;
  425. }
  426. .hookx-range {
  427. -webkit-appearance: none;
  428. appearance: none;
  429. height: 5px;
  430. background: #444;
  431. outline: none;
  432. }
  433. .hookx-range::-webkit-slider-thumb {
  434. -webkit-appearance: none;
  435. appearance: none;
  436. width: 15px;
  437. height: 15px;
  438. background: #4caf50;
  439. cursor: pointer;
  440. border-radius: 50%;
  441. }
  442. #watermark {
  443. position: fixed;
  444. top: 50%;
  445. left: 10px;
  446. transform: translateY(-50%);
  447. color: rgba(255, 255, 255, 0.1);
  448. font-size: 24px;
  449. font-family: 'Segoe UI', sans-serif;
  450. pointer-events: none;
  451. z-index: 100001;
  452. user-select: none;
  453. }
  454. `);
  455.  
  456. const themes = {
  457. green: { background: `linear-gradient(135deg, #1a3c34, #1a1a1a)`, border: `#4caf50`, button: `#4caf50` },
  458. blue: { background: `linear-gradient(135deg, #0d47a1, #1a1a1a)`, border: `#2196f3`, button: `#2196f3` },
  459. red: { background: `linear-gradient(135deg, #b71c1c, #1a1a1a)`, border: `#d32f2f`, button: `#d32f2f` },
  460. purple: { background: `linear-gradient(135deg, #4a148c, #1a1a1a)`, border: `#7e57c2`, button: `#7e57c2` },
  461. orange: { background: `linear-gradient(135deg, #e65100, #1a1a1a)`, border: `#ff9800`, button: `#ff9800` },
  462. cyan: { background: `linear-gradient(135deg, #006064, #1a1a1a)`, border: `#26a69a`, button: `#26a69a` },
  463. pink: { background: `linear-gradient(135deg, #ad1457, #1a1a1a)`, border: `#ec407a`, button: `#ec407a` },
  464. yellow: { background: `linear-gradient(135deg, #f57f17, #1a1a1a)`, border: `#fbc02d`, button: `#fbc02d` },
  465. neon: { background: `linear-gradient(135deg, #00b8d4, #1a1a1a)`, border: `#00e5ff`, button: `#00e5ff` },
  466. dark: { background: `linear-gradient(135deg, #212121, #1a1a1a)`, border: `#424242`, button: `#424242` },
  467. forest: { background: `linear-gradient(135deg, #2e7d32, #1a1a1a)`, border: `#66bb6a`, button: `#66bb6a` },
  468. ocean: { background: `linear-gradient(135deg, #01579b, #1a1a1a)`, border: `#29b6f6`, button: `#29b6f6` }
  469. };
  470.  
  471. function applyTheme(element, theme) {
  472. element.style.background = themes[theme].background;
  473. element.style.border = `2px solid ${themes[theme].border}`;
  474. if (element.className.includes('tab-button') || element.className.includes('move-mods-btn') || element.className.includes('acc-btn')) {
  475. element.style.background = themes[theme].button;
  476. }
  477. }
  478.  
  479. const menu = document.createElement('div');
  480. menu.className = 'hookx-menu';
  481. menu.innerHTML = `
  482. <h2>HookX Client</h2>
  483. <div class="tab-buttons">
  484. <button class="tab-button" data-tab="visual">Visual</button>
  485. <button class="tab-button" data-tab="utility">Utility</button>
  486. <button class="tab-button" data-tab="combat">Combat</button>
  487. <button class="tab-button" data-tab="players">Players</button>
  488. <button class="tab-button" data-tab="accounts">Accounts</button>
  489. </div>
  490. <div id="visual-tab" class="tab-content">
  491. <div class="mod-toggle"><input type="checkbox" id="menuThemeMod"> Menu Theme</div>
  492. <div class="mod-toggle"><input type="checkbox" id="arrayListMod"> ArrayList</div>
  493. <div class="mod-toggle"><input type="checkbox" id="zoomMod"> Zoom</div>
  494. <div class="mod-toggle"><input type="checkbox" id="nightVisionMod"> Night Vision</div>
  495. <div class="mod-toggle"><input type="checkbox" id="spinningSpikesMod"> Spike Spin Mod</div>
  496. <div class="mod-toggle"><input type="checkbox" id="pulseEffectMod"> Pulse Effect</div>
  497. </div>
  498. <div id="utility-tab" class="tab-content">
  499. <div class="mod-toggle"><input type="checkbox" id="fpsMod"> FPS</div>
  500. <div class="mod-toggle"><input type="checkbox" id="cpsMod"> CPS</div>
  501. <div class="mod-toggle"><input type="checkbox" id="fpsBoosterMod"> FPS Booster</div>
  502. <div class="mod-toggle"><input type="checkbox" id="pingMod"> Ping</div>
  503. <div class="mod-toggle"><input type="checkbox" id="keystrokesMod"> Keystrokes</div>
  504. <div class="mod-toggle"><input type="checkbox" id="coordinatesMod"> Coordinates</div>
  505. <div class="mod-toggle"><input type="checkbox" id="timerMod"> Timer</div>
  506. </div>
  507. <div id="combat-tab" class="tab-content">
  508. <div class="mod-toggle"><input type="checkbox" id="hitMarkersMod"> Hit Markers</div>
  509. <div class="mod-toggle"><input type="checkbox" id="rangeIndicatorMod"> Range Indicator</div>
  510. <div class="mod-toggle"><input type="checkbox" id="crosshairMod"> Custom Crosshair</div>
  511. <div class="mod-toggle"><input type="checkbox" id="swingAnimationMod"> Swing Animation</div>
  512. </div>
  513. <div id="players-tab" class="tab-content">
  514. <p>Player list is displayed here. Toggle with ; key.</p>
  515. <p>Made by blubby, edited by hooder</p>
  516. </div>
  517. <div id="accounts-tab" class="tab-content">
  518. <div class="account-form">
  519. <input type="text" id="account-email" placeholder="Email">
  520. <input type="password" id="account-password" placeholder="Password">
  521. <button id="add-account-btn">Add Account</button>
  522. </div>
  523. <div class="account-list" id="account-list"></div>
  524. </div>
  525. <button class="move-mods-btn">Move Mods</button>
  526. `;
  527. document.body.appendChild(menu);
  528. makeDraggable(menu);
  529. applyTheme(menu, currentTheme);
  530.  
  531. const watermark = document.createElement('div');
  532. watermark.id = 'watermark';
  533. watermark.textContent = 'hooder';
  534. document.body.appendChild(watermark);
  535.  
  536. const tabButtons = menu.querySelectorAll('.tab-button');
  537. const tabContents = menu.querySelectorAll('.tab-content');
  538. tabButtons.forEach(button => {
  539. button.addEventListener('click', () => {
  540. tabContents.forEach(content => content.classList.remove('active'));
  541. menu.querySelector(`#${button.dataset.tab}-tab`).classList.add('active');
  542. });
  543. applyTheme(button, currentTheme);
  544. });
  545. menu.querySelector('#visual-tab').classList.add('active');
  546.  
  547. const moveModsBtn = menu.querySelector('.move-mods-btn');
  548. moveModsBtn.addEventListener('click', () => {
  549. isDragging = !isDragging;
  550. moveModsBtn.textContent = isDragging ? 'Stop Moving' : 'Move Mods';
  551. });
  552. applyTheme(moveModsBtn, currentTheme);
  553.  
  554. document.addEventListener('keydown', (e) => {
  555. if (e.key === 'Shift' && e.location === KeyboardEvent.DOM_KEY_LOCATION_RIGHT) {
  556. menuVisible = !menuVisible;
  557. menu.style.display = menuVisible ? 'flex' : 'none';
  558. }
  559. });
  560.  
  561. const playerList = document.createElement('div');
  562. playerList.className = 'player-list';
  563. document.body.appendChild(playerList);
  564. const playerNames = new Set();
  565.  
  566. function addPlayerName(name) {
  567. if (!playerNames.has(name)) {
  568. const playerNameElement = document.createElement('div');
  569. playerNameElement.textContent = name;
  570. playerNameElement.className = 'player-name';
  571. playerList.appendChild(playerNameElement);
  572. playerNames.add(name);
  573. setTimeout(() => playerNameElement.style.opacity = '1', 100);
  574. displayJoinNotification(name);
  575. }
  576. }
  577.  
  578. function displayJoinNotification(name) {
  579. const notification = document.createElement('div');
  580. notification.textContent = `${name} has joined!`;
  581. notification.className = 'join-notification';
  582. document.body.appendChild(notification);
  583. setTimeout(() => notification.style.opacity = '1', 100);
  584. setTimeout(() => {
  585. notification.style.opacity = '0';
  586. setTimeout(() => notification.remove(), 500);
  587. }, 3000);
  588. }
  589.  
  590. WebSocket.prototype.realSend = WebSocket.prototype.send;
  591. WebSocket.prototype.send = function(data) {
  592. this.realSend(data);
  593. this.addEventListener('message', handleWebSocketMessages);
  594. };
  595.  
  596. function handleWebSocketMessages(event) {
  597. try {
  598. const messageData = JSON.parse(event.data);
  599. if (messageData[0] === 33) {
  600. playerList.innerHTML = '';
  601. playerNames.clear();
  602. const players = messageData[3];
  603. if (players.length === 0) addPlayerName("Server Joined");
  604. else players.forEach(player => addPlayerName(player[1]));
  605. } else if (messageData[0] === 32 || messageData[0] === 35) {
  606. addPlayerName(messageData[2]);
  607. }
  608. } catch (error) {
  609. console.error('Error parsing WebSocket message:', error);
  610. }
  611. }
  612.  
  613. let displayToggled = false;
  614. document.addEventListener('keydown', (e) => {
  615. if (e.key === ';') {
  616. displayToggled = !displayToggled;
  617. playerList.style.display = displayToggled ? 'block' : 'none';
  618. themeButtonsContainer.style.display = displayToggled ? 'flex' : 'none';
  619. }
  620. });
  621.  
  622. const themeButtonsContainer = document.createElement('div');
  623. themeButtonsContainer.className = 'theme-buttons-container';
  624. const pinkButton = createThemeButton('pink-button', () => setTheme('#f8bbd0', '#ec407a', '#ec407a'));
  625. const orangeButton = createThemeButton('light-orange-button', () => setTheme('#ffcc80', '#ff9800', '#ff9800'));
  626. const blueButton = createThemeButton('skye-blue-button', () => setTheme('#81d4fa', '#0288d1', '#0288d1'));
  627. const greenButton = createThemeButton('green-button', () => setTheme('#a5d6a7', '#4caf50', '#4caf50'));
  628. const purpleButton = createThemeButton('purple-button', () => setTheme('#d1c4e9', '#7e57c2', '#7e57c2'));
  629. const neonButton = createThemeButton('neon-button', () => setTheme('#80deea', '#26a69a', '#26a69a'));
  630. const redButton = createThemeButton('red-button', () => setTheme('#ef9a9a', '#e53935', '#e53935'));
  631. const yellowButton = createThemeButton('yellow-button', () => setTheme('#fff59d', '#fbc02d', '#fbc02d'));
  632. themeButtonsContainer.append(pinkButton, orangeButton, blueButton, greenButton, purpleButton, neonButton, redButton, yellowButton);
  633. document.body.appendChild(themeButtonsContainer);
  634.  
  635. function createThemeButton(className, onClick) {
  636. const button = document.createElement('div');
  637. button.className = `theme-button ${className}`;
  638. button.onclick = onClick;
  639. return button;
  640. }
  641.  
  642. function setTheme(start, end, border) {
  643. playerList.style.background = `linear-gradient(135deg, ${start}, ${end})`;
  644. playerList.style.borderColor = border;
  645. playerList.querySelectorAll('.player-name').forEach(name => name.style.color = '#e0e0e0');
  646. }
  647.  
  648. const accountList = menu.querySelector('#account-list');
  649. const addAccBtn = menu.querySelector('#add-account-btn');
  650. const emailInput = menu.querySelector('#account-email');
  651. const passInput = menu.querySelector('#account-password');
  652.  
  653. let userpass = [];
  654. function createAccountCard(data) {
  655. const card = document.createElement('div');
  656. card.className = 'account-card';
  657. card.id = data.randomString;
  658. card.innerHTML = `
  659. <span>${data.name} (Score: ${data.score})</span>
  660. <div class="account-buttons">
  661. <button class="acc-btn acc-btn-switch">Switch</button>
  662. <button class="acc-btn acc-btn-remove">Remove</button>
  663. </div>
  664. `;
  665. const switchBtn = card.querySelector('.acc-btn-switch');
  666. const removeBtn = card.querySelector('.acc-btn-remove');
  667. applyTheme(switchBtn, currentTheme);
  668. applyTheme(removeBtn, currentTheme);
  669. switchBtn.addEventListener('click', () => {
  670. const loginBtn = document.getElementById('login');
  671. const logoutBtn = document.getElementById('logout');
  672. const gameEmailInput = document.getElementById('enter-mail');
  673. const gamePassInput = document.getElementById('enter-password');
  674. logoutBtn.click();
  675. gameEmailInput.value = data.email;
  676. gamePassInput.value = data.password;
  677. loginBtn.click();
  678. });
  679. removeBtn.addEventListener('click', () => {
  680. const storedData = JSON.parse(localStorage.getItem('cards') || '[]');
  681. const index = storedData.findIndex(item => item.randomString === data.randomString);
  682. storedData.splice(index, 1);
  683. localStorage.setItem('cards', JSON.stringify(storedData));
  684. card.remove();
  685. });
  686. return card;
  687. }
  688.  
  689. function displayAccounts() {
  690. accountList.innerHTML = '';
  691. const storedData = JSON.parse(localStorage.getItem('cards') || '[]');
  692. storedData.forEach(data => accountList.appendChild(createAccountCard(data)));
  693. }
  694.  
  695. addAccBtn.addEventListener('click', () => {
  696. const email = emailInput.value;
  697. const password = passInput.value;
  698. if (email && password) {
  699. fetch(`https://account.sploop.io:443/login?mail=${email}&hash=${hex_md5(password)}`)
  700. .then(response => response.json())
  701. .then(json => {
  702. if (json.error) {
  703. alert('Invalid Account');
  704. return;
  705. }
  706. const storedData = JSON.parse(localStorage.getItem('cards') || '[]');
  707. const randomString = Math.random().toString(36).substring(2, 12);
  708. const newData = { name: json.nickname, email, password, score: json.score, randomString };
  709. storedData.push(newData);
  710. localStorage.setItem('cards', JSON.stringify(storedData));
  711. accountList.appendChild(createAccountCard(newData));
  712. emailInput.value = '';
  713. passInput.value = '';
  714. })
  715. .catch(() => alert('Error adding account'));
  716. } else {
  717. alert('Please enter both email and password');
  718. }
  719. });
  720.  
  721. const logo = document.createElement('div');
  722. logo.style = `
  723. position: fixed;
  724. top: 10px;
  725. left: 50%;
  726. transform: translateX(-50%);
  727. color: #a5d6a7;
  728. font-family: 'Segoe UI', Arial, sans-serif;
  729. font-size: 20px;
  730. z-index: 1000;
  731. cursor: move;
  732. `;
  733. logo.textContent = 'HookX Client';
  734. document.body.appendChild(logo);
  735. makeDraggable(logo);
  736.  
  737. // Spinning Spikes Mod with Adjustable Speed
  738. const spinningSpikesUI = document.createElement('div');
  739. spinningSpikesUI.className = 'mod-ui';
  740. spinningSpikesUI.style.top = '10px';
  741. spinningSpikesUI.style.left = '150px';
  742. spinningSpikesUI.innerHTML = `
  743. <label>Spin Speed:</label>
  744. <input type="range" id="spinSpeedSlider" min="0.5" max="10" step="0.1" value="${spinSpeed}">
  745. `;
  746. document.body.appendChild(spinningSpikesUI);
  747. makeDraggable(spinningSpikesUI);
  748. applyTheme(spinningSpikesUI, currentTheme);
  749.  
  750. const spinSpeedSlider = spinningSpikesUI.querySelector('#spinSpeedSlider');
  751. spinSpeedSlider.addEventListener('input', (e) => {
  752. spinSpeed = parseFloat(e.target.value);
  753. });
  754.  
  755. function initSpinningSpikes() {
  756. const gameCanvas = document.getElementById('game-canvas');
  757. if (!gameCanvas) {
  758. console.log('Waiting for game canvas...');
  759. setTimeout(initSpinningSpikes, 500);
  760. return;
  761. }
  762.  
  763. const ctx2D = gameCanvas.getContext('2d');
  764. const ctxWebGL = gameCanvas.getContext('webgl') || gameCanvas.getContext('experimental-webgl');
  765. console.log('Canvas context - 2D:', !!ctx2D, 'WebGL:', !!ctxWebGL);
  766.  
  767. if (!ctx2D && ctxWebGL) {
  768. console.log('WebGL detected; 2D spinning spikes mod may not work. Attempting overlay fallback.');
  769. initOverlayFallback(gameCanvas);
  770. return;
  771. }
  772.  
  773. if (!ctx2D) {
  774. console.log('No rendering context found; spikes mod cannot initialize.');
  775. return;
  776. }
  777.  
  778. console.log('Spinning Spikes initialized on canvas (2D):', gameCanvas.id);
  779.  
  780. const spikeUrls = new Set([
  781. "https://sploop.io/img/entity/spike.png?v=1923912",
  782. "https://sploop.io/img/entity/hard_spike.png?v=1923912",
  783. "https://sploop.io/img/entity/big_spike.png?v=1923912"
  784. ]);
  785.  
  786. const spikeUpdate = (ctx, img, x, y, width, height, rotation) => {
  787. ctx.save();
  788. ctx.translate(x + width / 2, y + height / 2);
  789. ctx.rotate(rotation);
  790. ogdraw.call(ctx, img, -width / 2, -height / 2, width, height);
  791. ctx.restore();
  792. };
  793.  
  794. const ogdraw = CanvasRenderingContext2D.prototype.drawImage;
  795. CanvasRenderingContext2D.prototype.drawImage = function(img, ...args) {
  796. const isSpinningEnabled = document.getElementById('spinningSpikesMod')?.checked || false;
  797. if (this.canvas && this.canvas.id === "game-canvas" && img instanceof HTMLImageElement && spikeUrls.has(img.src) && isSpinningEnabled) {
  798. console.log('Spike detected:', img.src, 'Args:', args);
  799. let x, y, width, height;
  800. if (args.length === 2) {
  801. [x, y] = args;
  802. width = img.width;
  803. height = img.height;
  804. } else if (args.length === 4) {
  805. [x, y, width, height] = args;
  806. } else if (args.length === 8) {
  807. [, , , , x, y, width, height] = args;
  808. } else {
  809. console.log('Unsupported drawImage call:', args);
  810. return ogdraw.apply(this, [img, ...args]);
  811. }
  812. this.globalAlpha = 0;
  813. ogdraw.apply(this, [img, ...args]);
  814. this.globalAlpha = 1;
  815. const rotation = (performance.now() / 1000 * spinSpeed) % (2 * Math.PI);
  816. spikeUpdate(this, img, x, y, width, height, rotation);
  817. } else {
  818. return ogdraw.apply(this, [img, ...args]);
  819. }
  820. };
  821. }
  822.  
  823. function initOverlayFallback(canvas) {
  824. console.log('Overlay fallback not implemented yet; spikes will not spin.');
  825. }
  826.  
  827. setTimeout(() => {
  828. initSpinningSpikes();
  829. console.log('Spike Spin Mod initialization attempted');
  830. }, 4000);
  831.  
  832. const pulseEffectUI = document.createElement('div');
  833. pulseEffectUI.className = 'mod-ui pulse-effect-ui';
  834. pulseEffectUI.style.top = '60px';
  835. pulseEffectUI.style.left = '150px';
  836. pulseEffectUI.innerHTML = `
  837. <label>Pulse Speed (seconds): </label>
  838. <input type="range" id="pulseSpeedSlider" min="0.5" max="3" step="0.1" value="${pulseSpeed}">
  839. `;
  840. document.body.appendChild(pulseEffectUI);
  841. makeDraggable(pulseEffectUI);
  842. applyTheme(pulseEffectUI, currentTheme);
  843.  
  844. const pulseSpeedSlider = pulseEffectUI.querySelector('#pulseSpeedSlider');
  845. pulseSpeedSlider.addEventListener('input', (e) => {
  846. pulseSpeed = parseFloat(e.target.value);
  847. updateCanvasEffects();
  848. });
  849.  
  850. // Crosshair Mod
  851. const crosshairUI = document.createElement('div');
  852. crosshairUI.className = 'mod-ui crosshair-ui';
  853. crosshairUI.style.top = '460px';
  854. crosshairUI.style.left = '10px';
  855. crosshairUI.innerHTML = `
  856. <label><input type="checkbox" id="toggleCrosshair"> Enable Crosshair</label>
  857. <select id="crosshairStyle" class="hookx-select">
  858. <option value="dot">Dot</option>
  859. <option value="cross">Cross</option>
  860. <option value="spike">Spike</option>
  861. <option value="square">Square</option>
  862. <option value="triangle">Triangle</option>
  863. <option value="xcross">X Cross</option>
  864. </select>
  865. <input type="color" id="crosshairColor" class="hookx-color" value="#4caf50">
  866. <div class="hookx-label">Crosshair Size</div>
  867. <input type="range" id="crosshairSize" class="hookx-range" min="5" max="50" value="12">
  868. <div class="hookx-label">Opacity</div>
  869. <input type="range" id="crosshairOpacity" class="hookx-range" min="0.1" max="1" step="0.1" value="1">
  870. <div class="hookx-label">Offset</div>
  871. <input type="range" id="crosshairOffset" class="hookx-range" min="0" max="20" value="0">
  872. `;
  873. document.body.appendChild(crosshairUI);
  874. makeDraggable(crosshairUI);
  875. applyTheme(crosshairUI, currentTheme);
  876.  
  877. let crosshair = document.createElement('div');
  878. crosshair.className = 'crosshair dot';
  879. document.body.appendChild(crosshair);
  880.  
  881. const toggleCrosshair = crosshairUI.querySelector('#toggleCrosshair');
  882. const crosshairStyleSelect = crosshairUI.querySelector('#crosshairStyle');
  883. const crosshairColorPicker = crosshairUI.querySelector('#crosshairColor');
  884. const sizeSlider = crosshairUI.querySelector('#crosshairSize');
  885. const opacitySlider = crosshairUI.querySelector('#crosshairOpacity');
  886. const offsetSlider = crosshairUI.querySelector('#crosshairOffset');
  887.  
  888. function loadSettings() {
  889. const savedCrosshair = localStorage.getItem('crosshair') || 'dot';
  890. const savedColor = localStorage.getItem('crosshairColor') || '#4caf50';
  891. const savedSize = localStorage.getItem('crosshairSize') || 12;
  892. const savedOpacity = localStorage.getItem('crosshairOpacity') || 1;
  893. const savedOffset = localStorage.getItem('crosshairOffset') || 0;
  894. const savedToggle = JSON.parse(localStorage.getItem('toggleCrosshair')) || false;
  895.  
  896. crosshairStyleSelect.value = savedCrosshair;
  897. crosshairColorPicker.value = savedColor;
  898. sizeSlider.value = savedSize;
  899. opacitySlider.value = savedOpacity;
  900. offsetSlider.value = savedOffset;
  901. toggleCrosshair.checked = savedToggle;
  902.  
  903. setCrosshairStyle(savedCrosshair);
  904. crosshairColorPicker.dispatchEvent(new Event('input'));
  905. sizeSlider.dispatchEvent(new Event('input'));
  906. opacitySlider.dispatchEvent(new Event('input'));
  907. offsetSlider.dispatchEvent(new Event('input'));
  908. toggleCrosshair.dispatchEvent(new Event('change'));
  909. }
  910.  
  911. function saveSettings() {
  912. localStorage.setItem('crosshair', crosshairStyleSelect.value);
  913. localStorage.setItem('crosshairColor', crosshairColorPicker.value);
  914. localStorage.setItem('crosshairSize', sizeSlider.value);
  915. localStorage.setItem('crosshairOpacity', opacitySlider.value);
  916. localStorage.setItem('crosshairOffset', offsetSlider.value);
  917. localStorage.setItem('toggleCrosshair', JSON.stringify(toggleCrosshair.checked));
  918. }
  919.  
  920. function setCrosshairStyle(styleName) {
  921. const newCrosshair = document.createElement('div');
  922. newCrosshair.className = `crosshair ${styleName}`;
  923. const size = parseInt(sizeSlider.value);
  924. if (styleName === 'triangle') {
  925. newCrosshair.style.borderLeftWidth = `${size / 2}px`;
  926. newCrosshair.style.borderRightWidth = `${size / 2}px`;
  927. newCrosshair.style.borderBottomWidth = `${size * 0.9}px`;
  928. newCrosshair.style.borderLeftColor = 'transparent';
  929. newCrosshair.style.borderRightColor = 'transparent';
  930. newCrosshair.style.borderBottomColor = crosshairColorPicker.value;
  931. } else {
  932. newCrosshair.style.width = `${size}px`;
  933. newCrosshair.style.height = `${size}px`;
  934. }
  935. document.body.replaceChild(newCrosshair, crosshair);
  936. crosshair = newCrosshair;
  937. updateCrosshairColor();
  938. if (toggleCrosshair.checked) crosshair.style.display = 'block';
  939. }
  940.  
  941. function updateCrosshairColor() {
  942. const color = crosshairColorPicker.value;
  943. crosshair.style.color = color;
  944. crosshair.style.opacity = parseFloat(opacitySlider.value);
  945. crosshair.style.backgroundColor = '';
  946. crosshair.style.borderColor = '';
  947. if (crosshair.classList.contains('dot')) {
  948. crosshair.style.backgroundColor = color;
  949. } else if (crosshair.classList.contains('square')) {
  950. crosshair.style.borderColor = color;
  951. } else if (crosshair.classList.contains('triangle')) {
  952. crosshair.style.borderBottomColor = color;
  953. }
  954. }
  955.  
  956. function moveCrosshair(e) {
  957. const offset = parseInt(offsetSlider.value);
  958. crosshair.style.left = `${e.clientX + offset}px`;
  959. crosshair.style.top = `${e.clientY + offset}px`;
  960. }
  961.  
  962. toggleCrosshair.addEventListener('change', () => {
  963. if (toggleCrosshair.checked) {
  964. crosshair.style.display = 'block';
  965. document.body.classList.add('hide-cursor');
  966. document.addEventListener('mousemove', moveCrosshair);
  967. } else {
  968. crosshair.style.display = 'none';
  969. document.body.classList.remove('hide-cursor');
  970. document.removeEventListener('mousemove', moveCrosshair);
  971. }
  972. saveSettings();
  973. });
  974.  
  975. crosshairStyleSelect.addEventListener('change', () => {
  976. setCrosshairStyle(crosshairStyleSelect.value);
  977. saveSettings();
  978. });
  979. crosshairColorPicker.addEventListener('input', () => {
  980. updateCrosshairColor();
  981. saveSettings();
  982. });
  983. sizeSlider.addEventListener('input', () => {
  984. setCrosshairStyle(crosshairStyleSelect.value);
  985. saveSettings();
  986. });
  987. opacitySlider.addEventListener('input', () => {
  988. updateCrosshairColor();
  989. saveSettings();
  990. });
  991. offsetSlider.addEventListener('input', () => {
  992. moveCrosshair({ clientX: crosshair.offsetLeft, clientY: crosshair.offsetTop });
  993. saveSettings();
  994. });
  995.  
  996. function updateCanvasEffects() {
  997. const canvas = document.getElementById('game-canvas');
  998. if (!canvas) return;
  999.  
  1000. const zoomLevel = document.getElementById('zoomLevel')?.value || 1;
  1001. canvas.style.transform = `scale(${zoomLevel})`;
  1002. canvas.style.transformOrigin = 'center center';
  1003.  
  1004. const isPulseEnabled = document.getElementById('pulseEffectMod')?.checked;
  1005. canvas.style.animation = isPulseEnabled ? `screenPulse ${pulseSpeed}s infinite ease-in-out` : 'none';
  1006.  
  1007. const isFpsBoostEnabled = document.getElementById('fpsBoosterMod')?.checked;
  1008. const isNightVisionEnabled = document.getElementById('nightVisionMod')?.checked;
  1009. let filter = '';
  1010. if (isNightVisionEnabled) filter += ' brightness(1.5)';
  1011. canvas.style.filter = filter.trim();
  1012. }
  1013.  
  1014. const fpsUI = document.createElement('div');
  1015. fpsUI.className = 'mod-ui';
  1016. fpsUI.style.top = '60px';
  1017. fpsUI.style.left = '10px';
  1018. document.body.appendChild(fpsUI);
  1019. makeDraggable(fpsUI);
  1020. applyTheme(fpsUI, currentTheme);
  1021. let lastTime = performance.now();
  1022. function updateFPS() {
  1023. const now = performance.now();
  1024. const fps = Math.round(1000 / (now - lastTime));
  1025. fpsUI.textContent = `FPS: ${fps}`;
  1026. lastTime = now;
  1027. requestAnimationFrame(updateFPS);
  1028. }
  1029.  
  1030. const cpsUI = document.createElement('div');
  1031. cpsUI.className = 'mod-ui';
  1032. cpsUI.style.top = '110px';
  1033. cpsUI.style.left = '10px';
  1034. document.body.appendChild(cpsUI);
  1035. makeDraggable(cpsUI);
  1036. applyTheme(cpsUI, currentTheme);
  1037. let clickTimes = [];
  1038. document.addEventListener('mousedown', () => clickTimes.push(Date.now()));
  1039. setInterval(() => {
  1040. const now = Date.now();
  1041. clickTimes = clickTimes.filter(time => now - time < 1000);
  1042. cpsUI.textContent = `CPS: ${clickTimes.length}`;
  1043. }, 500);
  1044.  
  1045. const fpsBoosterUI = document.createElement('div');
  1046. fpsBoosterUI.className = 'mod-ui';
  1047. fpsBoosterUI.style.top = '160px';
  1048. fpsBoosterUI.style.left = '10px';
  1049. document.body.appendChild(fpsBoosterUI);
  1050. makeDraggable(fpsBoosterUI);
  1051. applyTheme(fpsBoosterUI, currentTheme);
  1052. function toggleFPSBooster(on) {
  1053. const canvas = document.getElementById('game-canvas');
  1054. if (on) {
  1055. canvas.style.imageRendering = 'pixelated';
  1056. document.body.style.background = '#000';
  1057. fpsBoosterUI.textContent = 'FPS Booster: ON';
  1058. } else {
  1059. canvas.style.imageRendering = 'auto';
  1060. document.body.style.background = '#1a1a1a';
  1061. fpsBoosterUI.textContent = 'FPS Booster: OFF';
  1062. }
  1063. updateCanvasEffects();
  1064. }
  1065.  
  1066. const pingUI = document.createElement('div');
  1067. pingUI.className = 'mod-ui';
  1068. pingUI.style.top = '210px';
  1069. pingUI.style.left = '10px';
  1070. document.body.appendChild(pingUI);
  1071. makeDraggable(pingUI);
  1072. applyTheme(pingUI, currentTheme);
  1073. function updatePing() {
  1074. const start = performance.now();
  1075. fetch('https://sploop.io/').then(() => {
  1076. pingUI.textContent = `Ping: ${Math.round(performance.now() - start)}ms`;
  1077. }).catch(() => pingUI.textContent = 'Ping: N/A');
  1078. }
  1079.  
  1080. const keystrokesUI = document.createElement('div');
  1081. keystrokesUI.className = 'mod-ui keystrokes-ui';
  1082. keystrokesUI.style.top = '260px';
  1083. keystrokesUI.style.left = '10px';
  1084. keystrokesUI.innerHTML = `
  1085. <div><div class="keystroke-key" id="keyW">W</div></div>
  1086. <div>
  1087. <div class="keystroke-key" id="keyA">A</div>
  1088. <div class="keystroke-key" id="keyS">S</div>
  1089. <div class="keystroke-key" id="keyD">D</div>
  1090. </div>
  1091. <div><div class="keystroke-key" id="keySpace"> </div></div>
  1092. <div>
  1093. <div class="keystroke-key" id="keyLMB">LMB</div>
  1094. <div class="keystroke-key" id="keyRMB">RMB</div>
  1095. </div>
  1096. `;
  1097. document.body.appendChild(keystrokesUI);
  1098. makeDraggable(keystrokesUI);
  1099. applyTheme(keystrokesUI, currentTheme);
  1100. const keyElements = {
  1101. w: keystrokesUI.querySelector('#keyW'),
  1102. a: keystrokesUI.querySelector('#keyA'),
  1103. s: keystrokesUI.querySelector('#keyS'),
  1104. d: keystrokesUI.querySelector('#keyD'),
  1105. space: keystrokesUI.querySelector('#keySpace'),
  1106. lmb: keystrokesUI.querySelector('#keyLMB'),
  1107. rmb: keystrokesUI.querySelector('#keyRMB')
  1108. };
  1109. document.addEventListener('keydown', (e) => {
  1110. if (!keystrokesMod.checked) return;
  1111. switch (e.key.toLowerCase()) {
  1112. case 'w': keyElements.w.classList.add('active'); break;
  1113. case 'a': keyElements.a.classList.add('active'); break;
  1114. case 's': keyElements.s.classList.add('active'); break;
  1115. case 'd': keyElements.d.classList.add('active'); break;
  1116. case ' ': keyElements.space.classList.add('active'); break;
  1117. }
  1118. });
  1119. document.addEventListener('keyup', (e) => {
  1120. if (!keystrokesMod.checked) return;
  1121. switch (e.key.toLowerCase()) {
  1122. case 'w': keyElements.w.classList.remove('active'); break;
  1123. case 'a': keyElements.a.classList.remove('active'); break;
  1124. case 's': keyElements.s.classList.remove('active'); break;
  1125. case 'd': keyElements.d.classList.remove('active'); break;
  1126. case ' ': keyElements.space.classList.remove('active'); break;
  1127. }
  1128. });
  1129. document.addEventListener('mousedown', (e) => {
  1130. if (!keystrokesMod.checked) return;
  1131. if (e.button === 0) keyElements.lmb.classList.add('active');
  1132. if (e.button === 2) keyElements.rmb.classList.add('active');
  1133. });
  1134. document.addEventListener('mouseup', (e) => {
  1135. if (!keystrokesMod.checked) return;
  1136. if (e.button === 0) keyElements.lmb.classList.remove('active');
  1137. if (e.button === 2) keyElements.rmb.classList.remove('active');
  1138. });
  1139.  
  1140. const menuThemeUI = document.createElement('div');
  1141. menuThemeUI.className = 'mod-ui';
  1142. menuThemeUI.style.top = '10px';
  1143. menuThemeUI.style.left = '150px';
  1144. menuThemeUI.innerHTML = `
  1145. <label>Menu Theme: </label>
  1146. <select id="themeSelect">
  1147. <option value="green">Green</option>
  1148. <option value="blue">Blue</option>
  1149. <option value="red">Red</option>
  1150. <option value="purple">Purple</option>
  1151. <option value="orange">Orange</option>
  1152. <option value="cyan">Cyan</option>
  1153. <option value="pink">Pink</option>
  1154. <option value="yellow">Yellow</option>
  1155. <option value="neon">Neon</option>
  1156. <option value="dark">Dark</option>
  1157. <option value="forest">Forest</option>
  1158. <option value="ocean">Ocean</option>
  1159. </select>
  1160. `;
  1161. document.body.appendChild(menuThemeUI);
  1162. makeDraggable(menuThemeUI);
  1163. applyTheme(menuThemeUI, currentTheme);
  1164.  
  1165. const themeSelectMenu = menuThemeUI.querySelector('#themeSelect');
  1166. themeSelectMenu.addEventListener('change', (e) => {
  1167. currentTheme = e.target.value;
  1168. applyTheme(menu, currentTheme);
  1169. tabButtons.forEach(btn => applyTheme(btn, currentTheme));
  1170. applyTheme(moveModsBtn, currentTheme);
  1171. applyTheme(fpsUI, currentTheme);
  1172. applyTheme(cpsUI, currentTheme);
  1173. applyTheme(menuThemeUI, currentTheme);
  1174. applyTheme(arrayListUI, currentTheme);
  1175. applyTheme(hitMarkersUI, currentTheme);
  1176. applyTheme(rangeIndicatorUI, currentTheme);
  1177. applyTheme(crosshairUI, currentTheme);
  1178. applyTheme(fpsBoosterUI, currentTheme);
  1179. applyTheme(swingAnimationUI, currentTheme);
  1180. applyTheme(pingUI, currentTheme);
  1181. applyTheme(keystrokesUI, currentTheme);
  1182. applyTheme(zoomUI, currentTheme);
  1183. applyTheme(nightVisionUI, currentTheme);
  1184. applyTheme(coordinatesUI, currentTheme);
  1185. applyTheme(timerUI, currentTheme);
  1186. applyTheme(playerList, currentTheme);
  1187. applyTheme(pulseEffectUI, currentTheme);
  1188. applyTheme(spinningSpikesUI, currentTheme);
  1189. accountList.querySelectorAll('.acc-btn').forEach(btn => applyTheme(btn, currentTheme));
  1190. });
  1191.  
  1192. const arrayListUI = document.createElement('div');
  1193. arrayListUI.className = 'mod-ui arraylist-container';
  1194. arrayListUI.style.top = '10px';
  1195. arrayListUI.style.right = '10px';
  1196. document.body.appendChild(arrayListUI);
  1197. makeDraggable(arrayListUI);
  1198. applyTheme(arrayListUI, currentTheme);
  1199.  
  1200. function updateArrayList() {
  1201. const activeMods = [];
  1202. if (fpsMod.checked) activeMods.push('FPS');
  1203. if (cpsMod.checked) activeMods.push('CPS');
  1204. if (menuThemeMod.checked) activeMods.push('Menu Theme');
  1205. if (arrayListMod.checked) activeMods.push('ArrayList');
  1206. if (hitMarkersMod.checked) activeMods.push('Hit Markers');
  1207. if (rangeIndicatorMod.checked) activeMods.push('Range Indicator');
  1208. if (crosshairMod.checked) activeMods.push('Custom Crosshair');
  1209. if (fpsBoosterMod.checked) activeMods.push('FPS Booster');
  1210. if (swingAnimationMod.checked) activeMods.push('Swing Animation');
  1211. if (pingMod.checked) activeMods.push('Ping');
  1212. if (keystrokesMod.checked) activeMods.push('Keystrokes');
  1213. if (zoomMod.checked) activeMods.push('Zoom');
  1214. if (nightVisionMod.checked) activeMods.push('Night Vision');
  1215. if (coordinatesMod.checked) activeMods.push('Coordinates');
  1216. if (timerMod.checked) activeMods.push('Timer');
  1217. if (spinningSpikesMod.checked) activeMods.push('Spike Spin Mod');
  1218. if (pulseEffectMod.checked) activeMods.push('Pulse Effect');
  1219. activeMods.sort();
  1220. arrayListUI.innerHTML = activeMods.map(mod => `<div class="arraylist-item">${mod}</div>`).join('');
  1221. }
  1222.  
  1223. const hitMarkersUI = document.createElement('div');
  1224. hitMarkersUI.className = 'mod-ui';
  1225. hitMarkersUI.style.top = '360px';
  1226. hitMarkersUI.style.left = '10px';
  1227. document.body.appendChild(hitMarkersUI);
  1228. makeDraggable(hitMarkersUI);
  1229. applyTheme(hitMarkersUI, currentTheme);
  1230. document.addEventListener('mousedown', (e) => {
  1231. if (!hitMarkersMod.checked || e.button !== 0) return;
  1232. const marker = document.createElement('div');
  1233. marker.style = `
  1234. position: fixed;
  1235. top: ${e.clientY - 5}px;
  1236. left: ${e.clientX - 5}px;
  1237. width: 10px;
  1238. height: 10px;
  1239. background: transparent;
  1240. border: 2px solid #4caf50;
  1241. border-radius: 0;
  1242. transform: rotate(45deg);
  1243. z-index: 1000;
  1244. animation: hitFade 0.5s ease-out forwards;
  1245. pointer-events: none;
  1246. `;
  1247. document.body.appendChild(marker);
  1248. setTimeout(() => marker.remove(), 500);
  1249. });
  1250.  
  1251. const rangeIndicatorUI = document.createElement('div');
  1252. rangeIndicatorUI.className = 'mod-ui';
  1253. rangeIndicatorUI.style.top = '410px';
  1254. rangeIndicatorUI.style.left = '10px';
  1255. rangeIndicatorUI.innerHTML = `
  1256. <label>Range: </label>
  1257. <input type="range" id="rangeSize" min="50" max="200" value="100">
  1258. `;
  1259. document.body.appendChild(rangeIndicatorUI);
  1260. makeDraggable(rangeIndicatorUI);
  1261. applyTheme(rangeIndicatorUI, currentTheme);
  1262. const rangeCircle = document.createElement('div');
  1263. rangeCircle.style = `
  1264. position: fixed;
  1265. border: 2px solid #4caf50;
  1266. border-radius: 50%;
  1267. z-index: 999;
  1268. pointer-events: none;
  1269. display: none;
  1270. `;
  1271. document.body.appendChild(rangeCircle);
  1272. document.addEventListener('mousemove', (e) => {
  1273. if (!rangeIndicatorMod.checked) return;
  1274. const size = rangeIndicatorUI.querySelector('#rangeSize').value;
  1275. rangeCircle.style.width = `${size}px`;
  1276. rangeCircle.style.height = `${size}px`;
  1277. rangeCircle.style.top = `${e.clientY - size / 2}px`;
  1278. rangeCircle.style.left = `${e.clientX - size / 2}px`;
  1279. rangeCircle.style.display = 'block';
  1280. });
  1281.  
  1282. const swingAnimationUI = document.createElement('div');
  1283. swingAnimationUI.className = 'mod-ui';
  1284. swingAnimationUI.style.top = '510px';
  1285. swingAnimationUI.style.left = '10px';
  1286. document.body.appendChild(swingAnimationUI);
  1287. makeDraggable(swingAnimationUI);
  1288. applyTheme(swingAnimationUI, currentTheme);
  1289. document.addEventListener('mousedown', (e) => {
  1290. if (!swingAnimationMod.checked || e.button !== 0) return;
  1291. const swing = document.createElement('div');
  1292. swing.style = `
  1293. position: fixed;
  1294. top: ${e.clientY - 30}px;
  1295. left: ${e.clientX - 30}px;
  1296. width: 60px;
  1297. height: 60px;
  1298. background: rgba(76, 175, 80, 0.3);
  1299. border: none;
  1300. border-radius: 50%;
  1301. z-index: 1000;
  1302. animation: swingFade 0.7s ease-out forwards;
  1303. pointer-events: none;
  1304. `;
  1305. document.body.appendChild(swing);
  1306. setTimeout(() => swing.remove(), 700);
  1307. });
  1308.  
  1309. const zoomUI = document.createElement('div');
  1310. zoomUI.className = 'mod-ui';
  1311. zoomUI.style.top = '110px';
  1312. zoomUI.style.left = '150px';
  1313. zoomUI.innerHTML = `
  1314. <label>Zoom: </label>
  1315. <input type="range" id="zoomLevel" min="0.5" max="2" step="0.1" value="1">
  1316. `;
  1317. document.body.appendChild(zoomUI);
  1318. makeDraggable(zoomUI);
  1319. applyTheme(zoomUI, currentTheme);
  1320. const zoomLevel = zoomUI.querySelector('#zoomLevel');
  1321. zoomLevel.addEventListener('input', () => updateCanvasEffects());
  1322.  
  1323. const nightVisionUI = document.createElement('div');
  1324. nightVisionUI.className = 'mod-ui';
  1325. nightVisionUI.style.top = '160px';
  1326. nightVisionUI.style.left = '150px';
  1327. nightVisionUI.textContent = 'Night Vision: OFF';
  1328. document.body.appendChild(nightVisionUI);
  1329. makeDraggable(nightVisionUI);
  1330. applyTheme(nightVisionUI, currentTheme);
  1331. function toggleNightVision(on) {
  1332. nightVisionUI.textContent = `Night Vision: ${on ? 'ON' : 'OFF'}`;
  1333. updateCanvasEffects();
  1334. }
  1335.  
  1336. let playerPos = { x: 0, y: 0 };
  1337.  
  1338. const coordinatesUI = document.createElement('div');
  1339. coordinatesUI.className = 'mod-ui';
  1340. coordinatesUI.style.top = '310px';
  1341. coordinatesUI.style.left = '10px';
  1342. coordinatesUI.textContent = 'X: 0, Y: 0';
  1343. document.body.appendChild(coordinatesUI);
  1344. makeDraggable(coordinatesUI);
  1345. applyTheme(coordinatesUI, currentTheme);
  1346. function updateCoordinates() {
  1347. if (!coordinatesMod.checked) return;
  1348. coordinatesUI.textContent = `X: ${Math.round(playerPos.x)}, Y: ${Math.round(playerPos.y)}`;
  1349. }
  1350. setInterval(updateCoordinates, 100);
  1351.  
  1352. const timerUI = document.createElement('div');
  1353. timerUI.className = 'mod-ui';
  1354. timerUI.style.top = '360px';
  1355. timerUI.style.left = '10px';
  1356. timerUI.textContent = 'Time: 00:00';
  1357. document.body.appendChild(timerUI);
  1358. makeDraggable(timerUI);
  1359. applyTheme(timerUI, currentTheme);
  1360. let startTime = Date.now();
  1361. function updateTimer() {
  1362. if (!timerMod.checked) return;
  1363. const elapsed = Math.floor((Date.now() - startTime) / 1000);
  1364. const minutes = String(Math.floor(elapsed / 60)).padStart(2, '0');
  1365. const seconds = String(elapsed % 60).padStart(2, '0');
  1366. timerUI.textContent = `Time: ${minutes}:${seconds}`;
  1367. }
  1368. setInterval(updateTimer, 1000);
  1369.  
  1370. const fpsMod = menu.querySelector('#fpsMod');
  1371. const cpsMod = menu.querySelector('#cpsMod');
  1372. const menuThemeMod = menu.querySelector('#menuThemeMod');
  1373. const arrayListMod = menu.querySelector('#arrayListMod');
  1374. const hitMarkersMod = menu.querySelector('#hitMarkersMod');
  1375. const rangeIndicatorMod = menu.querySelector('#rangeIndicatorMod');
  1376. const crosshairMod = menu.querySelector('#crosshairMod');
  1377. const fpsBoosterMod = menu.querySelector('#fpsBoosterMod');
  1378. const swingAnimationMod = menu.querySelector('#swingAnimationMod');
  1379. const pingMod = menu.querySelector('#pingMod');
  1380. const keystrokesMod = menu.querySelector('#keystrokesMod');
  1381. const zoomMod = menu.querySelector('#zoomMod');
  1382. const nightVisionMod = menu.querySelector('#nightVisionMod');
  1383. const coordinatesMod = menu.querySelector('#coordinatesMod');
  1384. const timerMod = menu.querySelector('#timerMod');
  1385. const spinningSpikesMod = menu.querySelector('#spinningSpikesMod');
  1386. const pulseEffectMod = menu.querySelector('#pulseEffectMod');
  1387.  
  1388. const modUIs = {
  1389. fps: fpsUI,
  1390. cps: cpsUI,
  1391. menuTheme: menuThemeUI,
  1392. arrayList: arrayListUI,
  1393. hitMarkers: hitMarkersUI,
  1394. rangeIndicator: rangeIndicatorUI,
  1395. crosshair: crosshairUI,
  1396. fpsBooster: fpsBoosterUI,
  1397. swingAnimation: swingAnimationUI,
  1398. ping: pingUI,
  1399. keystrokes: keystrokesUI,
  1400. zoom: zoomUI,
  1401. nightVision: nightVisionUI,
  1402. coordinates: coordinatesUI,
  1403. timer: timerUI,
  1404. spinningSpikes: spinningSpikesUI,
  1405. pulseEffect: pulseEffectUI
  1406. };
  1407.  
  1408. function initializeModUIs() {
  1409. Object.keys(modUIs).forEach(mod => {
  1410. const checkbox = menu.querySelector(`#${mod}Mod`);
  1411. modUIs[mod].style.display = checkbox.checked ? 'block' : 'none';
  1412. if (mod === 'rangeIndicator' && checkbox.checked) rangeCircle.style.display = 'block';
  1413. if (mod === 'crosshair' && checkbox.checked) toggleCrosshair.checked = true;
  1414. if (mod === 'fps' && checkbox.checked) requestAnimationFrame(updateFPS);
  1415. if (mod === 'ping' && checkbox.checked) setInterval(updatePing, 2000);
  1416. if (mod === 'fpsBooster' && checkbox.checked) toggleFPSBooster(true);
  1417. if (mod === 'nightVision' && checkbox.checked) toggleNightVision(true);
  1418. if (mod === 'timer' && checkbox.checked) startTime = Date.now();
  1419. });
  1420. updateCanvasEffects();
  1421. updateArrayList();
  1422. displayAccounts();
  1423. loadSettings();
  1424. }
  1425.  
  1426. function forceCanvasRedraw() {
  1427. const canvas = document.getElementById('game-canvas');
  1428. if (canvas) {
  1429. console.log('Forcing canvas redraw');
  1430. canvas.style.opacity = '0.99';
  1431. requestAnimationFrame(() => {
  1432. canvas.style.opacity = '1';
  1433. });
  1434. }
  1435. }
  1436.  
  1437. fpsMod.addEventListener('change', () => {
  1438. modUIs.fps.style.display = fpsMod.checked ? 'block' : 'none';
  1439. if (fpsMod.checked) requestAnimationFrame(updateFPS);
  1440. updateArrayList();
  1441. });
  1442. cpsMod.addEventListener('change', () => {
  1443. modUIs.cps.style.display = cpsMod.checked ? 'block' : 'none';
  1444. updateArrayList();
  1445. });
  1446. menuThemeMod.addEventListener('change', () => {
  1447. modUIs.menuTheme.style.display = menuThemeMod.checked ? 'block' : 'none';
  1448. updateArrayList();
  1449. });
  1450. arrayListMod.addEventListener('change', () => {
  1451. modUIs.arrayList.style.display = arrayListMod.checked ? 'block' : 'none';
  1452. updateArrayList();
  1453. });
  1454. hitMarkersMod.addEventListener('change', () => {
  1455. modUIs.hitMarkers.style.display = hitMarkersMod.checked ? 'block' : 'none';
  1456. updateArrayList();
  1457. });
  1458. rangeIndicatorMod.addEventListener('change', () => {
  1459. modUIs.rangeIndicator.style.display = rangeIndicatorMod.checked ? 'block' : 'none';
  1460. rangeCircle.style.display = rangeIndicatorMod.checked ? 'block' : 'none';
  1461. updateArrayList();
  1462. });
  1463. crosshairMod.addEventListener('change', () => {
  1464. modUIs.crosshair.style.display = crosshairMod.checked ? 'block' : 'none';
  1465. toggleCrosshair.checked = crosshairMod.checked;
  1466. toggleCrosshair.dispatchEvent(new Event('change'));
  1467. updateArrayList();
  1468. });
  1469. fpsBoosterMod.addEventListener('change', () => {
  1470. modUIs.fpsBooster.style.display = fpsBoosterMod.checked ? 'block' : 'none';
  1471. toggleFPSBooster(fpsBoosterMod.checked);
  1472. updateArrayList();
  1473. });
  1474. swingAnimationMod.addEventListener('change', () => {
  1475. modUIs.swingAnimation.style.display = swingAnimationMod.checked ? 'block' : 'none';
  1476. updateArrayList();
  1477. });
  1478. pingMod.addEventListener('change', () => {
  1479. modUIs.ping.style.display = pingMod.checked ? 'block' : 'none';
  1480. if (pingMod.checked) setInterval(updatePing, 2000);
  1481. updateArrayList();
  1482. });
  1483. keystrokesMod.addEventListener('change', () => {
  1484. modUIs.keystrokes.style.display = keystrokesMod.checked ? 'block' : 'none';
  1485. updateArrayList();
  1486. });
  1487. zoomMod.addEventListener('change', () => {
  1488. modUIs.zoom.style.display = zoomMod.checked ? 'block' : 'none';
  1489. if (!zoomMod.checked) zoomLevel.value = 1;
  1490. updateCanvasEffects();
  1491. updateArrayList();
  1492. });
  1493. nightVisionMod.addEventListener('change', () => {
  1494. modUIs.nightVision.style.display = nightVisionMod.checked ? 'block' : 'none';
  1495. toggleNightVision(nightVisionMod.checked);
  1496. updateArrayList();
  1497. });
  1498. coordinatesMod.addEventListener('change', () => {
  1499. modUIs.coordinates.style.display = coordinatesMod.checked ? 'block' : 'none';
  1500. updateArrayList();
  1501. });
  1502. timerMod.addEventListener('change', () => {
  1503. modUIs.timer.style.display = timerMod.checked ? 'block' : 'none';
  1504. if (timerMod.checked) startTime = Date.now();
  1505. updateArrayList();
  1506. });
  1507. spinningSpikesMod.addEventListener('change', () => {
  1508. modUIs.spinningSpikes.style.display = spinningSpikesMod.checked ? 'block' : 'none';
  1509. updateArrayList();
  1510. forceCanvasRedraw();
  1511. });
  1512. pulseEffectMod.addEventListener('change', () => {
  1513. modUIs.pulseEffect.style.display = pulseEffectMod.checked ? 'block' : 'none';
  1514. updateCanvasEffects();
  1515. updateArrayList();
  1516. });
  1517.  
  1518. initializeModUIs();
  1519. })();