// ==UserScript== // @name 420's Shit Mod Menu (Unified Drag, Color + Size Picker, DOT OFFSET) // @version 10.0-CROSSHAIR-FIX // @description Drag menu+launcher together, color & size picker for crosshair dot, hide/close behaviors, no M key. // @match https://games.crazygames.com/en_US/bullet-force-multiplayer/* // @match https://www.multiplayerpiano.dev/* // @match http://localhost:48897/game // @match https://www.gamepix.com/play/bullet-force // @match https://www.miniplay.com/game/bullet-force-multiplayer // @match https://kbhgames.com/game/bullet-force // @match https://bullet-force.com/ // @match https://www.jopi.com/game/game/bullet-force/ // @match https://www.gogy.com/games/bullet-force // @match https://www.gameflare.com/online-game/bullet-force/ // @match https://www.silvergames.com/en/bullet-force // @match https://kour-io.com/bullet-force // @grant none // @run-at document-idle // @namespace https://greasyfork.org/users/1527535 // @downloadURL https://update.greasyfork.icu/scripts/552849/420%27s%20Shit%20Mod%20Menu%20%28Unified%20Drag%2C%20Color%20%2B%20Size%20Picker%2C%20DOT%20OFFSET%29.user.js // @updateURL https://update.greasyfork.icu/scripts/552849/420%27s%20Shit%20Mod%20Menu%20%28Unified%20Drag%2C%20Color%20%2B%20Size%20Picker%2C%20DOT%20OFFSET%29.meta.js // ==/UserScript== (function () { 'use strict'; // =========================== // SETTINGS (edit here) // =========================== // DO NOT CHANGE THESE CONSTANTS, THEY ARE USED FOR LOCAL STORAGE KEYS const LS_MODAL_LEFT = '420_modal_left'; const LS_MODAL_TOP = '420_modal_top'; const LS_MODAL_OPEN = '420_modal_open'; const LS_CROSSHAIR_ON = '420_crosshair_on'; const LS_CROSSHAIR_COLOR = '420_crosshair_color'; const LS_CROSSHAIR_SIZE = '420_crosshair_size'; const LS_CROSSHAIR_OFFSET_X = '420_crosshair_offset_x'; const LS_CROSSHAIR_OFFSET_Y = '420_crosshair_offset_y'; // Default values const DEFAULT_COLOR = '#ff0000'; // Default red const DEFAULT_SIZE = 5; // Default 5px size const DEFAULT_OFFSET = 0; // Default offset // Drag configuration const DRAG_THRESHOLD = 5; // Helper functions for Local Storage function writeLS(key, value) { try { localStorage.setItem(key, JSON.stringify(value)); } catch (e) { console.error('Local storage write failed for key:', key, e); } } function readLS(key, defaultValue) { try { const stored = localStorage.getItem(key); if (stored === null) return defaultValue; return JSON.parse(stored); } catch (e) { console.error('Local storage read failed for key:', key, e); return defaultValue; } } // =========================== // CROSSHAIR LOGIC // =========================== function createCrosshairIfNeeded() { let crosshair = document.getElementById('420-crosshair'); if (!crosshair) { crosshair = document.createElement('div'); crosshair.id = '420-crosshair'; // Base styles: fixed position, centered crosshair.style.cssText = ` position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 999999; pointer-events: none; `; document.body.appendChild(crosshair); } return crosshair; } function updateCrosshairStyle(color, size) { const crosshair = createCrosshairIfNeeded(); // Get stored values or use defaults const chColor = color || readLS(LS_CROSSHAIR_COLOR, DEFAULT_COLOR); const chSize = size || readLS(LS_CROSSHAIR_SIZE, DEFAULT_SIZE); const chOffsetX = readLS(LS_CROSSHAIR_OFFSET_X, DEFAULT_OFFSET); const chOffsetY = readLS(LS_CROSSHAIR_OFFSET_Y, DEFAULT_OFFSET); // Apply styles crosshair.style.width = `${chSize}px`; crosshair.style.height = `${chSize}px`; crosshair.style.borderRadius = '50%'; crosshair.style.backgroundColor = chColor; crosshair.style.transform = `translate(calc(-50% + ${chOffsetX}px), calc(-50% + ${chOffsetY}px))`; // Update visibility based on the toggle state if (readLS(LS_CROSSHAIR_ON, true)) { crosshair.style.display = 'block'; } else { crosshair.style.display = 'none'; } } function toggleCrosshair(isVisible) { const crosshair = createCrosshairIfNeeded(); crosshair.style.display = isVisible ? 'block' : 'none'; writeLS(LS_CROSSHAIR_ON, isVisible); } // =========================== // MODAL HTML GENERATION // =========================== function createModal() { const existingContainer = document.getElementById('420-modal-container'); if (existingContainer) return; const container = document.createElement('div'); container.id = '420-modal-container'; // Get initial position from LS or use defaults const left = readLS(LS_MODAL_LEFT, window.innerWidth / 2 - 200); const top = readLS(LS_MODAL_TOP, window.innerHeight / 2 - 150); const isOpen = readLS(LS_MODAL_OPEN, false); container.style.cssText = ` position: fixed; left: ${left}px; top: ${top}px; z-index: 1000000; user-select: none; display: ${isOpen ? 'block' : 'none'}; font-family: Arial, sans-serif; `; // The '420's Shit Mod Menu' Modal Structure container.innerHTML = `