Hammer Senpa.io Mod - Enhanced UI & Fast Mode

Tweaks Senpa.io UI: draggable mod box, fast mode, visual enhancements, help menu

当前为 2025-04-21 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Hammer Senpa.io Mod - Enhanced UI & Fast Mode
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.0
  5. // @description Tweaks Senpa.io UI: draggable mod box, fast mode, visual enhancements, help menu
  6. // @author Hammer
  7. // @match https://senpa.io/*
  8. // @grant GM_addStyle
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. const localStorageKey = 'modBoxPosition';
  15. let optimizationEnabled = true;
  16. let fxOn = true;
  17. let isFrozen = false;
  18. let fastMode = false;
  19.  
  20. function savePosition(x, y) {
  21. localStorage.setItem(localStorageKey, JSON.stringify({ x, y }));
  22. }
  23.  
  24. function loadPosition() {
  25. const pos = localStorage.getItem(localStorageKey);
  26. return pos ? JSON.parse(pos) : null;
  27. }
  28.  
  29. const smallGui = document.createElement('div');
  30. smallGui.id = 'small-gui';
  31. Object.assign(smallGui.style, {
  32. position: 'fixed',
  33. width: '70px',
  34. height: '50px',
  35. backgroundColor: 'rgba(0, 0, 0, 0.7)',
  36. color: 'white',
  37. textAlign: 'center',
  38. fontSize: '14px',
  39. borderRadius: '5px',
  40. cursor: 'grab',
  41. zIndex: '9999',
  42. border: '2px solid red',
  43. transition: 'top 0.3s ease, left 0.3s ease'
  44. });
  45. smallGui.innerText = 'Mods';
  46. document.body.appendChild(smallGui);
  47.  
  48. const helpBox = document.createElement('div');
  49. helpBox.innerText = `
  50. Mod Features:
  51. FPS Optimization: Hides backgrounds, ads, & animations
  52. FX Toggle: Adds visual contrast for better vision
  53. Freeze on Death: Prevents respawn inputs for 3 seconds
  54. Fast Mode: Removes unnecessary UI but allows respawn
  55. Draggable GUI: Move and place mod menu where you like
  56. `;
  57. Object.assign(helpBox.style, {
  58. backgroundColor: '#fff',
  59. color: '#000',
  60. padding: '10px',
  61. borderRadius: '8px',
  62. fontSize: '12px',
  63. marginTop: '10px',
  64. display: 'none',
  65. whiteSpace: 'pre-wrap'
  66. });
  67.  
  68. const guiContainer = document.createElement('div');
  69. guiContainer.id = 'gui-container';
  70. Object.assign(guiContainer.style, {
  71. position: 'fixed',
  72. width: '250px',
  73. backgroundColor: 'rgba(0, 0, 0, 0.85)',
  74. color: 'white',
  75. padding: '20px',
  76. borderRadius: '10px',
  77. zIndex: '9999',
  78. display: 'none',
  79. fontFamily: 'Arial, sans-serif',
  80. border: '2px solid red',
  81. transition: 'top 0.3s ease, left 0.3s ease'
  82. });
  83.  
  84. const closeButton = document.createElement('button');
  85. closeButton.innerText = 'X';
  86. Object.assign(closeButton.style, {
  87. backgroundColor: '#dc3545',
  88. color: 'white',
  89. border: 'none',
  90. padding: '5px',
  91. borderRadius: '50%',
  92. cursor: 'pointer',
  93. position: 'absolute',
  94. top: '10px',
  95. right: '10px'
  96. });
  97. closeButton.onclick = () => {
  98. guiContainer.style.display = 'none';
  99. helpBox.style.display = 'none';
  100. };
  101.  
  102. function createToggleButton(textOn, textOff, initial, callback) {
  103. const btn = document.createElement('button');
  104. btn.innerText = initial ? textOff : textOn;
  105. btn.style.backgroundColor = initial ? '#28a745' : '#dc3545';
  106. btn.style.color = 'white';
  107. btn.style.border = 'none';
  108. btn.style.padding = '10px';
  109. btn.style.borderRadius = '5px';
  110. btn.style.cursor = 'pointer';
  111. btn.style.marginBottom = '10px';
  112. btn.style.width = '100%';
  113. btn.addEventListener('click', () => {
  114. const state = callback();
  115. btn.innerText = state ? textOff : textOn;
  116. btn.style.backgroundColor = state ? '#28a745' : '#dc3545';
  117. });
  118. return btn;
  119. }
  120.  
  121. function enableOptimization() {
  122. document.querySelectorAll('.ad, .sidebar, .popup').forEach(e => e.remove());
  123. document.body.style.backgroundImage = 'none';
  124. document.querySelectorAll('img').forEach(img => img.src = '');
  125. const style = document.createElement('style');
  126. style.innerHTML = `
  127. * {
  128. animation: none !important;
  129. transition: none !important;
  130. box-shadow: none !important;
  131. }
  132. canvas {
  133. image-rendering: optimizeSpeed;
  134. will-change: transform;
  135. }
  136. body, html {
  137. background: #000 !important;
  138. overflow: hidden;
  139. margin: 0;
  140. padding: 0;
  141. }
  142. `;
  143. document.head.appendChild(style);
  144. document.querySelectorAll('audio').forEach(a => a.pause());
  145. }
  146.  
  147. function disableOptimization() {
  148. const style = document.createElement('style');
  149. style.innerHTML = `
  150. * {
  151. animation: initial !important;
  152. transition: initial !important;
  153. }
  154. `;
  155. document.head.appendChild(style);
  156. }
  157.  
  158. function applyVisualEffects() {
  159. const canvas = document.querySelector('canvas');
  160. if (canvas) {
  161. canvas.style.filter = fxOn ? 'brightness(1.1) contrast(1.2) saturate(1.1)' : 'none';
  162. }
  163. }
  164.  
  165. function freezeOnDeath() {
  166. if (!isFrozen) return;
  167. const prevent = e => e.preventDefault();
  168. document.addEventListener('keydown', prevent);
  169. document.addEventListener('mousemove', prevent);
  170. document.addEventListener('mousedown', prevent);
  171. setTimeout(() => {
  172. document.removeEventListener('keydown', prevent);
  173. document.removeEventListener('mousemove', prevent);
  174. document.removeEventListener('mousedown', prevent);
  175. }, 3000);
  176. }
  177.  
  178. function enableFastMode() {
  179. document.querySelectorAll('img, .ad, .sidebar, .middle, .popup, .footer, .header, .menu, .info').forEach(e => e.remove());
  180. }
  181.  
  182. guiContainer.appendChild(closeButton);
  183. guiContainer.appendChild(createToggleButton('Enable FPS Optimization', 'Disable FPS Optimization', optimizationEnabled, () => {
  184. optimizationEnabled = !optimizationEnabled;
  185. optimizationEnabled ? enableOptimization() : disableOptimization();
  186. return optimizationEnabled;
  187. }));
  188. guiContainer.appendChild(createToggleButton('Enable FX', 'Disable FX', fxOn, () => {
  189. fxOn = !fxOn;
  190. applyVisualEffects();
  191. return fxOn;
  192. }));
  193. guiContainer.appendChild(createToggleButton('Freeze on Death', 'Unfreeze on Death', isFrozen, () => {
  194. isFrozen = !isFrozen;
  195. return isFrozen;
  196. }));
  197. guiContainer.appendChild(createToggleButton('Enable Fast Mode', 'Disable Fast Mode', fastMode, () => {
  198. fastMode = !fastMode;
  199. if (fastMode) enableFastMode();
  200. return fastMode;
  201. }));
  202.  
  203. const helpBtn = document.createElement('button');
  204. helpBtn.innerText = 'Help';
  205. Object.assign(helpBtn.style, {
  206. backgroundColor: '#ffffff',
  207. color: '#000',
  208. padding: '10px',
  209. borderRadius: '5px',
  210. cursor: 'pointer',
  211. marginTop: '10px',
  212. width: '100%'
  213. });
  214. helpBtn.onclick = () => helpBox.style.display = helpBox.style.display === 'none' ? 'block' : 'none';
  215. guiContainer.appendChild(helpBtn);
  216. guiContainer.appendChild(helpBox);
  217. document.body.appendChild(guiContainer);
  218.  
  219. smallGui.addEventListener('click', () => {
  220. const isHidden = guiContainer.style.display === 'none';
  221. guiContainer.style.display = isHidden ? 'block' : 'none';
  222. helpBox.style.display = 'none';
  223. });
  224.  
  225. // Load saved position or default to bottom right
  226. const saved = loadPosition();
  227. if (saved) {
  228. smallGui.style.top = saved.y + 'px';
  229. smallGui.style.left = saved.x + 'px';
  230. guiContainer.style.top = saved.y + 60 + 'px';
  231. guiContainer.style.left = saved.x + 'px';
  232. } else {
  233. smallGui.style.bottom = '20px';
  234. smallGui.style.right = '20px';
  235. }
  236.  
  237. // Draggable
  238. let dragging = false, offsetX, offsetY;
  239. smallGui.addEventListener('mousedown', (e) => {
  240. dragging = true;
  241. offsetX = e.clientX - smallGui.offsetLeft;
  242. offsetY = e.clientY - smallGui.offsetTop;
  243. smallGui.style.cursor = 'grabbing';
  244. });
  245.  
  246. document.addEventListener('mousemove', (e) => {
  247. if (!dragging) return;
  248. const x = e.clientX - offsetX;
  249. const y = e.clientY - offsetY;
  250. smallGui.style.left = x + 'px';
  251. smallGui.style.top = y + 'px';
  252. smallGui.style.right = 'auto';
  253. smallGui.style.bottom = 'auto';
  254. guiContainer.style.left = x + 'px';
  255. guiContainer.style.top = y + 60 + 'px';
  256. });
  257.  
  258. document.addEventListener('mouseup', () => {
  259. if (dragging) {
  260. savePosition(parseInt(smallGui.style.left), parseInt(smallGui.style.top));
  261. }
  262. dragging = false;
  263. smallGui.style.cursor = 'grab';
  264. });
  265.  
  266. const observer = new MutationObserver(() => {
  267. const middleAd = document.querySelector('.middle, .middle-panel, .ad-middle');
  268. if (middleAd) middleAd.remove();
  269.  
  270. const inGame = document.querySelector('.player');
  271. if (inGame) {
  272. const savedPos = loadPosition();
  273. if (!savedPos) {
  274. smallGui.style.bottom = '20px';
  275. smallGui.style.right = '20px';
  276. guiContainer.style.bottom = '80px';
  277. guiContainer.style.right = '20px';
  278. }
  279. }
  280. });
  281.  
  282. observer.observe(document.body, { childList: true, subtree: true });
  283.  
  284. setInterval(() => {
  285. const dead = document.querySelector('.dead');
  286. if (dead && isFrozen) freezeOnDeath();
  287. }, 1000);
  288.  
  289. if (optimizationEnabled) enableOptimization();
  290. if (fxOn) applyVisualEffects();
  291. })();