// ==UserScript== // @name SLITHER.IO MOD MENU W/ CHAT - 6/17/2025 ZOOM, BOT MODE, PROFILES, CLANS, LEVELS, REP+, LINE & MORE!! // @namespace http://tampermonkey.net/ // @version VX7 // @description Ultimate Slither.io Mod Menu with Chat & Custom UI - Fixed chat toggle and simplify // @author GITHUB.COM/DXXTHLY - HTTPS://DSC.GG/143X by: dxxthly. & waynesg on Discord // @icon https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUNcRl2Rh40pZLhgffYGFDRLbYJ4qfMNwddQ&s.png // @match http://slither.io/ // @match https://slither.io/ // @match http://slither.com/io // @match https://slither.com/io // @grant none // @downloadURL https://update.greasyfork.icu/scripts/535770/SLITHERIO%20MOD%20MENU%20W%20CHAT%20-%206172025%20ZOOM%2C%20BOT%20MODE%2C%20PROFILES%2C%20CLANS%2C%20LEVELS%2C%20REP%2B%2C%20LINE%20%20MORE%21%21.user.js // @updateURL https://update.greasyfork.icu/scripts/535770/SLITHERIO%20MOD%20MENU%20W%20CHAT%20-%206172025%20ZOOM%2C%20BOT%20MODE%2C%20PROFILES%2C%20CLANS%2C%20LEVELS%2C%20REP%2B%2C%20LINE%20%20MORE%21%21.meta.js // ==/UserScript== (function () { 'use strict'; // --- Custom BG Patch (MUST be first!) --- window.__customBgUrlCurrent = 'https://slither.io/s2/bg54.jpg'; // Default if (!window.__customBgPatched) { window.__customBgPatched = true; const originalDrawImage = CanvasRenderingContext2D.prototype.drawImage; CanvasRenderingContext2D.prototype.drawImage = function(img, ...args) { if ( img && img.src && img.src.includes('bg54.jpg') && window.__customBgUrlCurrent ) { const customImg = new window.Image(); customImg.crossOrigin = "anonymous"; customImg.src = window.__customBgUrlCurrent; return originalDrawImage.call(this, customImg, ...args); } return originalDrawImage.apply(this, arguments); }; } // === CONFIG === const config = { menuPosition: 'right', defaultCircleRadius: 150, circleRadiusStep: 20, minCircleRadius: 50, maxCircleRadius: 300, deathSoundURL: 'https://audio.jukehost.co.uk/WwASzZ0a1wJDKubIcoZzin8J7kycCt5l.mp3', godModeVideoURL: 'https://youtu.be/ghAap5IWu1Y', defaultMenuName: 'DSC.GG/143X', defaultMenuColor: '#4CAF50', chatMaxMessages: 50, chatMaxMessageLength: 100, chatProfanityFilter: true, chatProfanityList: ['fuck', 'shit', 'asshole', 'bitch', 'cunt', 'nigger', 'fag', 'retard'] }; // === STATE === const state = { keybinds: JSON.parse(localStorage.getItem('modKeybinds')) || { toggleMenu: 'm', toggleKeybinds: '-', circleRestriction: 'k', circleSmaller: 'j', circleLarger: 'l', autoCircle: 'a', autoBoost: 'b', fpsDisplay: 'f', autoRespawn: 's', deathSound: 'v', showServer: 't', chatEnabled: '/', zoomIn: 'z', zoomOut: 'x', zoomReset: 'c', screenshot: 'p', github: 'g', discord: 'd', godMode: 'y', reddit: 'r' }, features: { circleRestriction: false, autoCircle: false, performanceMode: 1, deathSound: true, snakeTrail: false, snakeTrailColor: '#FFD700', fpsDisplay: false, autoBoost: false, showServer: false, autoRespawn: false, chatVisible: true, chatEnabled: true, chatProfanityFilter: config.chatProfanityFilter, chatFocus: false, keybindsEnabled: true }, menuVisible: true, zoomFactor: 1.0, circleRadius: config.defaultCircleRadius, fps: 0, fpsFrames: 0, fpsLastCheck: Date.now(), deathSound: new Audio(config.deathSoundURL), isInGame: false, boosting: false, autoCircleAngle: 0, ping: 0, server: '', lastSnakeAlive: true, boostingInterval: null, menuName: localStorage.getItem('modMenuName') || config.defaultMenuName, menuColor: localStorage.getItem('modMenuColor') || config.defaultMenuColor, showCustomization: sessionStorage.getItem('showCustomization') === 'false' ? false : true, simplified: sessionStorage.getItem('modMenuSimplified') === 'true', chatMessages: [], uiLayout: JSON.parse(localStorage.getItem('modMenuUILayout')) || { menu: { x: null, y: null, width: null, height: null }, chat: { x: 20, y: 100, width: 300, height: 200 }, minimap: { x: null, y: null, width: null, height: null } }, draggingElement: null, resizingElement: null, dragStartX: 0, dragStartY: 0, elementStartX: 0, elementStartY: 0, elementStartWidth: 0, elementStartHeight: 0 }; // Ensure all default keybinds are present in state.keybinds const defaultKeybinds = { toggleMenu: 'm', toggleKeybinds: '-', circleRestriction: 'k', circleSmaller: 'j', circleLarger: 'l', autoCircle: 'a', autoBoost: 'b', fpsDisplay: 'f', autoRespawn: 's', deathSound: 'v', showServer: 't', chatEnabled: 'enter', zoomIn: 'z', zoomOut: 'x', zoomReset: 'c', screenshot: 'p', github: 'g', discord: 'd', godMode: 'y', reddit: 'r' }; Object.entries(defaultKeybinds).forEach(([action, key]) => { if (!state.keybinds.hasOwnProperty(action)) { state.keybinds[action] = key; } }); function loadSavedServers() { try { return JSON.parse(localStorage.getItem('customServerList') || '[]'); } catch { return []; } } function saveServers(list) { localStorage.setItem('customServerList', JSON.stringify(list)); } function updateServerDropdown() { const selectSrv = document.getElementById('select-srv'); if (!selectSrv) return; selectSrv.innerHTML = ''; const servers = loadSavedServers(); servers.forEach((ip, i) => { const opt = document.createElement('option'); opt.value = ip; opt.text = `${i+1}. ${ip}`; selectSrv.appendChild(opt); }); } // update server ip loop wayne function updateServerIpLoop() { let ip = null, port = null; // Try to get the server IP and port from the game if (window.bso && window.bso.ip && window.bso.po) { ip = window.bso.ip; port = window.bso.po; } if (ip && port) { state.server = `${ip}:${port}`; } else { state.server = ''; } setTimeout(updateServerIpLoop, 1000); // Check every second } updateServerIpLoop(); // === VIP MEMBERS // DISCORD === const vipMembers = [ { uid: "crcOY9hoRrfayStCxMVm7Zdx2W92", name: "stevao" }, // first discord vip { uid: "DhGhICAZwkRa7wuMsyquM9a5uO92", name: "LUANBLAYNER" }, { uid: "VIP_UID_2", name: "AnotherVIP" } ]; function isVip(uid, name) { return vipMembers.some(vip => vip.uid === uid && vip.name.toLowerCase() === (name || '').toLowerCase() ); } function vipGlowStyle(name, color) { return `${name}`; } // The thingy for the chat to be in order let chatMessagesArray = []; // Server list let forcedServer = null; // { ip: "IP", port: "PORT" } // state variables let chatHistory = []; let autoCircleRAF = null; // ===== AUTO RESPAWN SYSTEM ===== let autoRespawnDead = false; let autoRespawnSpam = null; let deathCheckInterval = null; // dxxthly afk let afkOn = false; let afkInterval = null; // track real mouse cursor position let realMouseX = window.innerWidth / 2; let realMouseY = window.innerHeight / 2; document.addEventListener('mousemove', function(e) { realMouseX = e.clientX; realMouseY = e.clientY; }); function syncServerBoxWithMenu() { const box = document.getElementById('custom-server-box'); const nameSpan = document.getElementById('custom-server-box-name'); const serverListBtn = document.getElementById('server-list-btn'); if (!box || !nameSpan) return; nameSpan.textContent = state.menuName; nameSpan.style.color = state.menuColor; nameSpan.style.textShadow = `0 0 8px ${state.menuColor}, 0 0 16px ${state.menuColor}`; box.style.borderColor = state.menuColor; if (serverListBtn) { serverListBtn.style.background = state.menuColor; serverListBtn.style.boxShadow = `0 0 8px ${state.menuColor}66`; } } const zoomSteps = [ 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.275, 0.3, 0.325, 0.35, 0.375, 0.4, 0.425, 0.45, 0.475, 0.5, 0.525, 0.55, 0.575, 0.6, 0.625, 0.65, 0.675, 0.7, 0.725, 0.75, 0.775, 0.8, 0.825, 0.85, 0.875, 0.9, 0.925, 0.95, 0.975, 1.0, 1.025, 1.05, 1.075, 1.1, 1.125, 1.15, 1.175, 1.2, 1.225, 1.25, 1.275, 1.3, 1.325, 1.35, 1.375, 1.4, 1.425, 1.45, 1.475, 1.5, 1.525, 1.55, 1.575, 1.6, 1.625, 1.65, 1.675, 1.7, 1.725, 1.75, 1.775, 1.8, 1.825, 1.85, 1.875, 1.9, 1.925, 1.95, 1.975, 2.0, 2.25, 2.5, 2.75, 3.0, 3.25, 3.5, 3.75, 4.0, 4.25, 4.5, 4.75, 5.0, 5.25, 5.5, 5.75, 6.0, 6.25, 6.5, 6.75, 7.0, 7.25, 7.5, 7.75, 8.0, 8.25, 8.5, 8.75, 9.0, 9.25, 9.5, 9.75, 10.0 ]; function addServerBox() { const check = setInterval(() => { const login = document.getElementById('login'); const nickInput = document.getElementById('nick'); if (login && nickInput) { clearInterval(check); // Prevent duplicate if (document.getElementById('custom-server-box')) return; // Create the box DEN DEN DEN const box = document.createElement('div'); box.id = 'custom-server-box'; box.style.cssText = ` margin: 24px auto 0 auto; max-width: 340px; background: rgba(30,30,30,0.96); border: 2px solid #6bff66; border-radius: 18px; box-shadow: 0 0 12px #00ff0044; padding: 18px 18px 10px 18px; text-align: center; font-family: 'ink free', Arial, sans-serif; font-size: 1.1em; color: #fff; letter-spacing: 1px; font-weight: bold; position: relative; `; box.innerHTML = `
${state.menuName}
Server List `; box.style.borderColor = state.menuColor; // Insert the box into the DOM FIRST: let parent = nickInput.parentElement; if (parent && parent.nextSibling) { parent.parentNode.insertBefore(box, parent.nextSibling.nextSibling); } else { login.appendChild(box); } // call this pita updateServerDropdown(); // Dropdown selection fills the input const selectSrv = document.getElementById('select-srv'); selectSrv.onchange = function() { document.getElementById('server-ip').value = this.value; }; // Save button handler document.getElementById('save-ip-btn').onclick = function() { const ipInput = document.getElementById('server-ip'); if (!ipInput || !ipInput.value.trim()) return; const ip = ipInput.value.trim(); if (!ip.includes(':') || ip.split(':')[0].trim() === '' || ip.split(':')[1].trim() === '') { alert("Please enter a valid IP:Port (e.g., 15.204.212.200:444 or server.domain.com:444)"); return; } let servers = loadSavedServers(); // Check for duplicates (case insensitive, ignoring whitespace) const normalized = ip.toLowerCase().replace(/\s+/g, ''); const isDuplicate = servers.some(s => s.toLowerCase().replace(/\s+/g, '') === normalized); if (!isDuplicate) { servers.push(ip); saveServers(servers); updateServerDropdown(); if (selectSrv) selectSrv.value = ip; } else { alert("This server is already in your list!"); } }; document.getElementById('connect-btn').onclick = function() { const ipInput = document.getElementById('server-ip'); if (!ipInput || !ipInput.value.trim()) return; const ip = ipInput.value.trim(); const parts = ip.split(':'); const ipPart = parts[0]; const portPart = parts[1] || "444"; // Save for persistence and Play Again forcedServer = { ip: ipPart, port: portPart }; localStorage.setItem('forcedServer', JSON.stringify(forcedServer)); // Use forceServer if available (most reliable, like your friend's mod) if (typeof window.forceServer === "function") { window.forceServer(ipPart, portPart); } // Set Slither.io variables (extra safety) window.forcing = true; if (!window.bso) window.bso = {}; window.bso.ip = ipPart; window.bso.po = portPart; // Always call connect() if (typeof window.connect === "function") { window.connect(); } // Simulate Play button click to trigger game start if needed const playBtn = document.getElementById('playh') || document.querySelector('.btn.btn-primary.btn-play-guest'); if (playBtn) playBtn.click(); // Optionally start checking connection status cause if she dont like u she dont like u if (typeof connectionStatus === "function") setTimeout(connectionStatus, 1000); }; } }, 100); } addServerBox(); let retry = 0; function connectionStatus() { if (!window.connecting || retry == 10) { window.forcing = false; retry = 0; return; } retry++; setTimeout(connectionStatus, 1000); } // Death detection function autoRespawnCheck() { if (!state.features.autoRespawn) { autoRespawnDead = false; stopAutoRespawnSpam(); return; } // Enhanced death detection const isDead = ( (window.snake && !window.snake.alive) || (window.dead_mtm !== undefined && window.dead_mtm !== -1) || (document.getElementById('died')?.style.display !== 'none') || (document.querySelector('.playagain')?.offsetParent !== null) ); if (isDead && !autoRespawnDead) { autoRespawnDead = true; startAutoRespawnSpam(); } else if (!isDead && autoRespawnDead) { autoRespawnDead = false; stopAutoRespawnSpam(); } } // Spam logic function startAutoRespawnSpam() { if (autoRespawnSpam) return; attemptAutoRespawn(); // Immediate attempt autoRespawnSpam = setInterval(attemptAutoRespawn, 50); } function attemptAutoRespawn() { if (!autoRespawnDead || !state.features.autoRespawn) { stopAutoRespawnSpam(); return; } // Handle nickname input const nickInput = document.getElementById('nick'); if (nickInput && !nickInput.value.trim()) { nickInput.value = localStorage.getItem("nickname") || "Anon"; nickInput.dispatchEvent(new Event('input', { bubbles: true })); } if (nickInput) nickInput.focus(); // Send Enter key document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true })); } function stopAutoRespawnSpam() { if (autoRespawnSpam) { clearInterval(autoRespawnSpam); autoRespawnSpam = null; } } // Toggle functions function enableAutoRespawn() { if (!deathCheckInterval) { deathCheckInterval = setInterval(autoRespawnCheck, 100); } } function disableAutoRespawn() { if (deathCheckInterval) { clearInterval(deathCheckInterval); deathCheckInterval = null; } autoRespawnDead = false; stopAutoRespawnSpam(); } // Initialize if enabled if (state.features.autoRespawn) enableAutoRespawn(); // Prime audio on ANY user interaction const primeAudio = () => { state.deathSound.volume = 0.01; state.deathSound.play().then(() => { state.deathSound.pause(); state.deathSound.currentTime = 0; state.deathSound.volume = 1; }).catch(console.error); document.removeEventListener('click', primeAudio); document.removeEventListener('keydown', primeAudio); }; document.addEventListener('click', primeAudio); document.addEventListener('keydown', primeAudio); // popup css fadein ish modern lookish menu? const style = document.createElement('style'); style.textContent = ` .profile-popup { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%) scale(1); min-width: 270px; max-width: 90vw; background: var(--menu-color, #4CAF50); color: #fff; border-radius: 16px; box-shadow: 0 8px 32px rgba(0,0,0,0.25), 0 2px 8px rgba(0,0,0,0.14); padding: 24px 32px 18px 32px; z-index: 99999; font-family: inherit; font-size: 1.08em; animation: fadeInProfile 0.21s cubic-bezier(.42,0,1,1); display: flex; flex-direction: column; align-items: center; } @keyframes fadeInProfile { from { opacity: 0; transform: translate(-50%, -60%) scale(0.95);} to { opacity: 1; transform: translate(-50%, -50%) scale(1);} } .profile-popup .close-btn { position: absolute; top: 10px; right: 16px; background: none; border: none; color: #fff; font-size: 1.5em; cursor: pointer; opacity: 0.7; transition: opacity 0.15s; } .profile-popup .close-btn:hover { opacity: 1; } .profile-popup .avatar { width: 64px; height: 64px; border-radius: 50%; background: #222; margin-bottom: 14px; object-fit: cover; border: 2px solid #fff; } .profile-popup .status-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: middle; } `; document.head.appendChild(style); // === Helper: Hex to RGBA === function hexToRgba(hex, alpha = 1) { let c = hex.replace('#', ''); if (c.length === 3) c = c[0]+c[0]+c[1]+c[1]+c[2]+c[2]; const num = parseInt(c, 16); return `rgba(${(num>>16)&255},${(num>>8)&255},${num&255},${alpha})`; } let lastChatMessageTime = 0; const chatCooldown = 7000; // Editing time will disable your messages from being sent to others // === Profanity Filter === function filterProfanity(text) { if (!state.features.chatProfanityFilter) return text; return text.split(/\b/).map(word => { const lowerWord = word.toLowerCase(); if (config.chatProfanityList.some(profanity => lowerWord.includes(profanity))) { return '*'.repeat(word.length); } return word; }).join(''); } function replaceLinksWithDiscord(text) { const urlRegex = /https?:\/\/[^\s]+|www\.[^\s]+/gi; return text.replace(urlRegex, 'https://dsc.gg/143X'); } document.addEventListener('pointerdown', function primeDeathSound() { state.deathSound.volume = 1; state.deathSound.play().catch(()=>{}); state.deathSound.pause(); state.deathSound.currentTime = 0; document.removeEventListener('pointerdown', primeDeathSound); }); function primeDeathSound() { state.deathSound.volume = 0; state.deathSound.play().catch(()=>{}); state.deathSound.pause(); state.deathSound.currentTime = 0; state.deathSound.volume = 1; document.removeEventListener('pointerdown', primeDeathSound); document.removeEventListener('keydown', primeDeathSound); } document.addEventListener('pointerdown', primeDeathSound); document.addEventListener('keydown', primeDeathSound); // === CHAT SYSTEM === function createChatSystem() { const chatContainer = document.createElement('div'); chatContainer.id = 'mod-menu-chat-container'; chatContainer.style.position = 'fixed'; chatContainer.style.left = `${state.uiLayout.chat.x}px`; chatContainer.style.top = `${state.uiLayout.chat.y}px`; chatContainer.style.width = `${state.uiLayout.chat.width}px`; chatContainer.style.height = `${state.uiLayout.chat.height}px`; chatContainer.style.zIndex = '9999'; chatContainer.style.display = state.features.chatVisible ? 'flex' : 'none'; chatContainer.style.flexDirection = 'column'; chatContainer.style.overflow = 'hidden'; chatContainer.style.userSelect = 'none'; // Chat tabs const chatTabs = document.createElement('div'); chatTabs.style.display = 'flex'; chatTabs.style.borderBottom = `1px solid ${hexToRgba(state.menuColor, 0.3)}`; const chatTab = document.createElement('div'); chatTab.textContent = '143X Chat'; chatTab.style.flex = '1'; chatTab.style.padding = '8px'; chatTab.style.textAlign = 'center'; chatTab.style.cursor = 'pointer'; chatTab.style.background = hexToRgba(state.menuColor, 0.2); chatTab.style.fontWeight = 'bold'; chatTab.style.color = '#fff'; chatTab.onclick = () => { document.getElementById('mod-menu-chat-body').style.display = 'flex'; document.getElementById('mod-menu-online-users').style.display = 'none'; chatTab.style.background = hexToRgba(state.menuColor, 0.2); usersTab.style.background = 'transparent'; }; const usersTab = document.createElement('div'); usersTab.textContent = 'Online Users'; usersTab.style.flex = '1'; usersTab.style.padding = '8px'; usersTab.style.textAlign = 'center'; usersTab.style.cursor = 'pointer'; usersTab.style.background = 'transparent'; usersTab.style.color = '#fff'; usersTab.onclick = () => { document.getElementById('mod-menu-chat-body').style.display = 'none'; document.getElementById('mod-menu-online-users').style.display = 'flex'; chatTab.style.background = 'transparent'; usersTab.style.background = hexToRgba(state.menuColor, 0.2); // No manual updateOnlineUsers() call! }; chatTabs.appendChild(chatTab); chatTabs.appendChild(usersTab); chatContainer.appendChild(chatTabs); // Chat header const chatHeader = document.createElement('div'); chatHeader.style.padding = '8px 12px'; chatHeader.style.background = hexToRgba(state.menuColor, 0.2); chatHeader.style.display = 'flex'; chatHeader.style.justifyContent = 'space-between'; chatHeader.style.alignItems = 'center'; chatHeader.style.cursor = 'move'; chatHeader.dataset.draggable = 'true'; const chatToggle = document.createElement('div'); chatToggle.textContent = '✖'; // Unicode X chatToggle.style.cursor = 'pointer'; chatToggle.style.fontSize = '18px'; chatToggle.style.padding = '0 5px'; chatToggle.title = state.features.chatVisible ? 'Hide chat' : 'Show chat'; chatToggle.onclick = () => { toggleChatVisible(); // or toggleChatDisplay() }; chatHeader.appendChild(chatToggle); chatContainer.appendChild(chatHeader); // Main chat area const chatArea = document.createElement('div'); chatArea.style.flex = '1'; chatArea.style.display = 'flex'; chatArea.style.flexDirection = 'column'; chatArea.style.overflow = 'hidden'; chatArea.style.background = 'rgba(17, 17, 17, 0.85)'; chatArea.style.borderRadius = '0 0 10px 10px'; chatArea.style.border = `2px solid ${state.menuColor}`; chatArea.style.borderTop = 'none'; // Chat messages const chatBody = document.createElement('div'); chatBody.id = 'mod-menu-chat-body'; chatBody.style.flex = '1'; chatBody.style.padding = '8px 12px'; chatBody.style.overflowY = 'auto'; chatBody.style.display = 'flex'; chatBody.style.flexDirection = 'column'; chatArea.appendChild(chatBody); // Online users list const onlineUsers = document.createElement('div'); onlineUsers.id = 'mod-menu-online-users'; onlineUsers.style.flex = '1'; onlineUsers.style.padding = '8px 12px'; onlineUsers.style.overflowY = 'auto'; onlineUsers.style.display = 'none'; onlineUsers.style.flexDirection = 'column'; onlineUsers.innerHTML = '
Loading users...
'; chatArea.appendChild(onlineUsers); // Chat input const chatInput = document.createElement('input'); chatInput.id = 'mod-menu-chat-input'; chatInput.type = 'text'; chatInput.placeholder = 'Press "/" to start typing...'; chatInput.style.width = '100%'; chatInput.style.padding = '8px 12px'; chatInput.style.border = 'none'; chatInput.style.borderTop = `1px solid ${hexToRgba(state.menuColor, 0.3)}`; chatInput.style.background = 'rgba(255,255,255,0.1)'; chatInput.style.color = '#fff'; chatInput.style.outline = 'none'; chatInput.style.display = 'block'; chatArea.appendChild(chatInput); chatContainer.appendChild(chatArea); // Resize handle const resizeHandle = document.createElement('div'); resizeHandle.style.position = 'absolute'; resizeHandle.style.right = '0'; resizeHandle.style.bottom = '0'; resizeHandle.style.width = '15px'; resizeHandle.style.height = '15px'; resizeHandle.style.cursor = 'nwse-resize'; resizeHandle.style.backgroundColor = hexToRgba(state.menuColor, 0.5); resizeHandle.style.display = 'block'; resizeHandle.dataset.resizable = 'true'; chatContainer.appendChild(resizeHandle); document.body.appendChild(chatContainer); // Make draggable and resizable makeDraggable(chatContainer, chatHeader); makeResizable(chatContainer, resizeHandle); } // sync chatbox color function syncChatBoxWithMenu() { const chatContainer = document.getElementById('mod-menu-chat-container'); if (!chatContainer) return; // Tabs const chatTabs = chatContainer.querySelector('div'); if (chatTabs) chatTabs.style.borderBottom = `1px solid ${hexToRgba(state.menuColor, 0.3)}`; // Tab backgrounds const chatTab = chatTabs?.children?.[0]; const usersTab = chatTabs?.children?.[1]; if (chatTab && chatTab.style.background) chatTab.style.background = hexToRgba(state.menuColor, 0.2); if (usersTab && usersTab.style.background) usersTab.style.background = 'transparent'; // active tab will update on click // Header const chatHeader = chatContainer.querySelector('div:nth-child(2)'); if (chatHeader) chatHeader.style.background = hexToRgba(state.menuColor, 0.2); // Chat area border const chatArea = chatContainer.querySelector('div:nth-child(3)'); if (chatArea) { chatArea.style.border = `2px solid ${state.menuColor}`; chatArea.style.borderTop = 'none'; } // Resize handle const resizeHandle = chatContainer.querySelector('div[style*="cursor: nwse-resize"]'); if (resizeHandle) resizeHandle.style.backgroundColor = hexToRgba(state.menuColor, 0.5); // Chat input const chatInput = document.getElementById('mod-menu-chat-input'); if (chatInput) chatInput.style.borderTop = `1px solid ${hexToRgba(state.menuColor, 0.3)}`; } // Place these helpers OUTSIDE (above) your loadFirebaseChat function: function filterProfanity(text) { const profanityList = [ 'fuck', 'shit', 'asshole', 'bitch', 'cunt', 'nigg3r', 'faggot', 'nigger', 'fag', 'retard', 'whore', 'slut', 'dick', 'douche', 'prick', 'pussy', 'cock', 'bollocks', 'arsehole', 'twat', 'jerkoff', 'motherfucker', 'dumbass', 'dumbfuck', 'crap', 'bollock', 'bugger', 'git', 'wanker', 'arse', 'clit', 'cum', 'blowjob', 'handjob', 'shitface', 'dickhead', 'tosser', 'knob', 'knobhead', 'pillock', 'tosspot', 'twatface', 'cumshot', 'fucked', 'fucking', 'shite', 'bastard', 'slag', 'minger', 'gash', 'bint', 'minge', 'prick', 'shithead', 'wank', 'shitbag' ]; return text.split(/\b/).map(word => { const lowerWord = word.toLowerCase(); if (profanityList.some(profanity => lowerWord.includes(profanity))) { return '*'.repeat(word.length); } return word; }).join(''); } function replaceLinksWithDiscord(text) { const urlRegex = /https?:\/\/[^\s]+|www\.[^\s]+/gi; return text.replace(urlRegex, 'https://dsc.gg/143X'); } function rainbowTextStyle(name) { const rainbowColors = ["#ef3550","#f48fb1","#7e57c2","#2196f3","#26c6da","#43a047","#eeff41","#f9a825","#ff5722"]; return name.split('').map((char, i) => `${char}` ).join(''); } function loadFirebaseChat() { // Load Firebase scripts const script1 = document.createElement('script'); script1.src = 'https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js'; script1.onload = () => { const script2 = document.createElement('script'); script2.src = 'https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js'; script2.onload = () => { const script3 = document.createElement('script'); script3.src = 'https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js'; script3.onload = () => { const firebaseConfig = { apiKey: "AIzaSyCtTloqGNdhmI3Xt0ta11vF0MQJHiKpO7Q", authDomain: "chatforslither.firebaseapp.com", databaseURL: "https://chatforslither-default-rtdb.firebaseio.com", projectId: "chatforslither", storageBucket: "chatforslither.appspot.com", messagingSenderId: "1045559625491", appId: "1:1045559625491:web:79eb8200eb87edac00bce6" }; if (!firebase.apps.length) firebase.initializeApp(firebaseConfig); const auth = firebase.auth(); auth.signInAnonymously().then(async (userCredential) => { const uid = userCredential.user.uid; const nickname = localStorage.getItem("nickname") || "Anon"; const userRef = firebase.database().ref("onlineUsers/" + uid); // Set user as online userRef.onDisconnect().remove(); userRef.set({ name: nickname, uid: uid, lastActive: Date.now(), chatNameColor: localStorage.getItem("chatNameColor") || "#FFD700" }); setInterval(() => { userRef.update({ lastActive: Date.now() }); }, 30000); // --- ONLINE USERS LISTENER (This part was okay) --- firebase.database().ref("onlineUsers").on("value", snapshot => { const users = snapshot.val() || {}; const onlineUsersEl = document.getElementById('mod-menu-online-users'); if (onlineUsersEl) { const now = Date.now(); const usersList = Object.entries(users) .filter(([_, user]) => now - (user.lastActive || 0) < 300000) .map(([userUid, user]) => `
${filterProfanity(user.name)} ${userUid === uid ? '(You)' : ''}
`).join(''); onlineUsersEl.innerHTML = usersList || '
No users online
'; } }); // --- CHAT MESSAGE LISTENER (The Corrected Part) --- const chatBody = document.getElementById('mod-menu-chat-body'); firebase.database().ref("slitherChat") .orderByChild("time") .limitToLast(config.chatMaxMessages) // Get the most recent messages .on("child_added", (snapshot) => { // This listens for each message one by one if (!chatBody) return; const msg = snapshot.val(); if (!msg || !msg.name || !msg.text) return; // Skip malformed messages // Remove the oldest message if the chat is full while (chatBody.children.length >= config.chatMaxMessages) { chatBody.removeChild(chatBody.firstChild); } const el = document.createElement('div'); el.style.marginBottom = '5px'; el.style.wordBreak = 'break-word'; el.style.background = 'rgba(40,40,40,0.93)'; el.style.padding = '6px 10px'; el.style.borderRadius = '7px'; el.style.color = '#fff'; el.style.fontFamily = 'inherit'; // Correctly determine name style let nameHtml; const userColor = msg.chatNameColor || '#FFD700'; const displayName = filterProfanity(msg.name || 'Anon'); if ((msg.uid === "CiOpgh1RLBg3l5oXn0SAho66Po93" && displayName.toLowerCase() === "dxxthly") || (msg.uid === "P75eMwh756Rb6h1W6iqQfHN2Dm92" && displayName.toLowerCase() === "wayne")) { nameHtml = rainbowTextStyle(displayName); } else if (isVip(msg.uid, displayName)) { nameHtml = vipGlowStyle(displayName, userColor); } else { nameHtml = displayName; } el.innerHTML = `${nameHtml}: ${filterProfanity(msg.text)}`; chatBody.appendChild(el); chatBody.scrollTop = chatBody.scrollHeight; // Always scroll to the newest message }); // --- CHAT INPUT HANDLER (This should be correct now) --- const chatInput = document.getElementById('mod-menu-chat-input'); chatInput.addEventListener('keydown', function (e) { if (e.key === 'Enter' && chatInput.value.trim()) { if (!auth.currentUser) return; // Safety check firebase.database().ref("slitherChat").push({ uid: auth.currentUser.uid, name: nickname, // Use the nickname variable from the outer scope text: filterProfanity(chatInput.value.trim()), time: Date.now(), chatNameColor: localStorage.getItem("chatNameColor") || "#FFD700" }); chatInput.value = ''; chatInput.blur(); } }); }); }; document.head.appendChild(script3); }; document.head.appendChild(script2); }; document.head.appendChild(script1); } function createTrailOverlayCanvas() { let overlay = document.getElementById('snake-trail-overlay'); if (overlay) { overlay.style.display = 'block'; // <-- Always show overlay when trail is ON return overlay; } const gameCanvas = document.querySelector('canvas'); if (!gameCanvas) return null; overlay = document.createElement('canvas'); overlay.id = 'snake-trail-overlay'; overlay.style.position = 'fixed'; overlay.style.left = gameCanvas.style.left || '0px'; overlay.style.top = gameCanvas.style.top || '0px'; overlay.style.pointerEvents = 'none'; overlay.style.zIndex = '9000'; overlay.width = window.innerWidth; overlay.height = window.innerHeight; overlay.style.display = 'block'; // <-- Make sure it's visible when created document.body.appendChild(overlay); // Adjust overlay size on resize window.addEventListener('resize', () => { overlay.width = window.innerWidth; overlay.height = window.innerHeight; }); return overlay; } function toggleChatVisible() { state.features.chatVisible = !state.features.chatVisible; const chatContainer = document.getElementById('mod-menu-chat-container'); if (chatContainer) { chatContainer.style.display = state.features.chatVisible ? 'flex' : 'none'; } updateMenu(); } function addChatMessage(message) { if (state.chatMessages.length >= config.chatMaxMessages) { state.chatMessages.shift(); } state.chatMessages.push(message); updateChatDisplay(); } function updateChatDisplay() { const chatBody = document.getElementById('mod-menu-chat-body'); if (chatBody) { chatBody.innerHTML = state.chatMessages.map(msg => `
${msg}
` ).reverse().join(''); } } // === UI DRAGGING & RESIZING === function makeDraggable(element, handle) { handle.addEventListener('mousedown', function(e) { if (e.target.dataset.draggable !== 'true') return; e.preventDefault(); state.draggingElement = element; state.dragStartX = e.clientX; state.dragStartY = e.clientY; state.elementStartX = parseInt(element.style.left, 10) || 0; state.elementStartY = parseInt(element.style.top, 10) || 0; }); } function makeResizable(element, handle) { handle.addEventListener('mousedown', function(e) { if (e.target.dataset.resizable !== 'true') return; e.preventDefault(); state.resizingElement = element; state.dragStartX = e.clientX; state.dragStartY = e.clientY; state.elementStartWidth = parseInt(element.style.width, 10) || 300; state.elementStartHeight = parseInt(element.style.height, 10) || 200; }); } document.addEventListener('mousemove', function(e) { if (state.draggingElement) { const dx = e.clientX - state.dragStartX; const dy = e.clientY - state.dragStartY; const newX = state.elementStartX + dx; const newY = state.elementStartY + dy; state.draggingElement.style.left = `${newX}px`; state.draggingElement.style.top = `${newY}px`; // Update UI layout in state if (state.draggingElement.id === 'mod-menu') { state.uiLayout.menu.x = newX; state.uiLayout.menu.y = newY; } else if (state.draggingElement.id === 'mod-menu-chat') { state.uiLayout.chat.x = newX; state.uiLayout.chat.y = newY; } } if (state.resizingElement) { const dx = e.clientX - state.dragStartX; const dy = e.clientY - state.dragStartY; const newWidth = Math.max(200, state.elementStartWidth + dx); const newHeight = Math.max(150, state.elementStartHeight + dy); state.resizingElement.style.width = `${newWidth}px`; state.resizingElement.style.height = `${newHeight}px`; // Update UI layout in state if (state.resizingElement.id === 'mod-menu') { state.uiLayout.menu.width = newWidth; state.uiLayout.menu.height = newHeight; } else if (state.resizingElement.id === 'mod-menu-chat') { state.uiLayout.chat.width = newWidth; state.uiLayout.chat.height = newHeight; } } }); document.addEventListener('mouseup', function() { if (state.draggingElement || state.resizingElement) { // Save layout to localStorage localStorage.setItem('modMenuUILayout', JSON.stringify(state.uiLayout)); } state.draggingElement = null; state.resizingElement = null; }); // === MENU CREATION === const menu = document.createElement('div'); menu.id = 'mod-menu'; menu.style.position = 'fixed'; menu.style.top = state.uiLayout.menu.y !== null ? `${state.uiLayout.menu.y}px` : '50px'; menu.style.left = state.uiLayout.menu.x !== null ? `${state.uiLayout.menu.x}px` : (config.menuPosition === 'left' ? '50px' : (config.menuPosition === 'center' ? '50%' : 'auto')); if (config.menuPosition === 'center' && state.uiLayout.menu.x === null) { menu.style.transform = 'translateX(-50%)'; } menu.style.right = state.uiLayout.menu.x !== null ? 'auto' : (config.menuPosition === 'right' ? '50px' : 'auto'); menu.style.background = 'rgba(17, 17, 17, 0.92)'; menu.style.border = `2px solid ${state.menuColor}`; menu.style.borderRadius = '10px'; menu.style.padding = '20px'; menu.style.zIndex = '9999'; menu.style.color = '#fff'; menu.style.fontFamily = 'Arial, sans-serif'; menu.style.fontSize = '14px'; menu.style.width = state.uiLayout.menu.width !== null ? `${state.uiLayout.menu.width}px` : '500px'; menu.style.boxShadow = '0 0 15px rgba(0,0,0,0.7)'; menu.style.backdropFilter = 'blur(5px)'; menu.style.transition = 'all 0.3s ease'; menu.style.userSelect = "text"; document.body.appendChild(menu); // (modal injection): if (!document.getElementById('keybind-modal-overlay')) { const modal = document.createElement('div'); modal.innerHTML = ` `; document.body.appendChild(modal.firstElementChild); } // Make menu draggable via header const menuHeader = document.createElement('div'); menuHeader.style.padding = '8px 12px'; menuHeader.style.margin = '-20px -20px 10px -20px'; menuHeader.style.background = hexToRgba(state.menuColor, 0.2); menuHeader.style.borderBottom = `1px solid ${hexToRgba(state.menuColor, 0.3)}`; menuHeader.style.cursor = 'move'; menuHeader.dataset.draggable = 'true'; menu.insertBefore(menuHeader, menu.firstChild); // FPS display const fpsDisplay = document.createElement('div'); fpsDisplay.id = 'fps-display'; fpsDisplay.style.position = 'fixed'; fpsDisplay.style.bottom = '10px'; fpsDisplay.style.right = '10px'; fpsDisplay.style.color = '#fff'; fpsDisplay.style.fontFamily = 'Arial, sans-serif'; fpsDisplay.style.fontSize = '14px'; fpsDisplay.style.zIndex = '9999'; fpsDisplay.style.display = 'none'; fpsDisplay.style.background = 'rgba(0,0,0,0.5)'; fpsDisplay.style.padding = '5px 10px'; fpsDisplay.style.borderRadius = '5px'; document.body.appendChild(fpsDisplay); // Ping display const pingDisplay = document.createElement('div'); pingDisplay.id = 'ping-display'; pingDisplay.style.position = 'fixed'; pingDisplay.style.bottom = '35px'; pingDisplay.style.right = '10px'; pingDisplay.style.color = '#fff'; pingDisplay.style.fontFamily = 'Arial, sans-serif'; pingDisplay.style.fontSize = '14px'; pingDisplay.style.zIndex = '9999'; pingDisplay.style.display = 'block'; pingDisplay.style.background = 'rgba(0,0,0,0.5)'; pingDisplay.style.padding = '5px 10px'; pingDisplay.style.borderRadius = '5px'; document.body.appendChild(pingDisplay); // Circle restriction visual const circleVisual = document.createElement('div'); circleVisual.id = 'circle-visual'; circleVisual.style.position = 'fixed'; circleVisual.style.border = `2px dashed ${hexToRgba(state.menuColor, 0.7)}`; circleVisual.style.borderRadius = '50%'; circleVisual.style.pointerEvents = 'none'; circleVisual.style.transform = 'translate(-50%, -50%)'; circleVisual.style.zIndex = '9998'; circleVisual.style.display = 'none'; circleVisual.style.transition = 'all 0.2s ease'; document.body.appendChild(circleVisual); // Chat overlay const chatOverlay = document.createElement('div'); chatOverlay.id = 'mod-menu-chat-overlay'; chatOverlay.style.position = 'fixed'; chatOverlay.style.left = '50%'; chatOverlay.style.top = '50%'; chatOverlay.style.transform = 'translate(-50%, -50%)'; chatOverlay.style.background = 'rgba(0,0,0,0.8)'; chatOverlay.style.border = `2px solid ${state.menuColor}`; chatOverlay.style.borderRadius = '10px'; chatOverlay.style.padding = '20px'; chatOverlay.style.zIndex = '10000'; chatOverlay.style.color = '#fff'; chatOverlay.style.fontFamily = 'Arial, sans-serif'; chatOverlay.style.fontSize = '18px'; chatOverlay.style.textAlign = 'center'; chatOverlay.style.display = 'none'; chatOverlay.style.boxShadow = '0 0 20px rgba(0,0,0,0.9)'; chatOverlay.textContent = 'Chat feature is currently being updated'; document.body.appendChild(chatOverlay); async function promptForUniqueNickname() { let nickname; while (true) { nickname = prompt("Enter a nickname for chat:"); if (!nickname) nickname = "Anon"; nickname = filterProfanity(nickname.trim()); if (!nickname || nickname.trim().length === 0) nickname = "Anon"; // Check Firebase for duplicate let exists = false; try { // Wait for Firebase to load if (typeof firebase === "undefined" || !firebase.database) { alert("Chat not loaded yet, please wait..."); return null; } const snapshot = await firebase.database().ref("onlineUsers/" + encodeURIComponent(nickname)).once('value'); exists = snapshot.exists(); } catch (e) { exists = false; // fallback: allow if error } if (exists) { alert("That nickname is already in use. Please choose another."); } else { break; } } localStorage.setItem("nickname", nickname); return nickname; } (async function ensureUniqueNickname() { if (!localStorage.getItem("nickname")) { await promptForUniqueNickname(); } else { const nickname = localStorage.getItem("nickname"); if (typeof firebase !== "undefined" && firebase.database) { const snapshot = await firebase.database().ref("onlineUsers/" + encodeURIComponent(nickname)).once('value'); if (snapshot.exists()) { alert("That nickname is already in use. Please choose another."); await promptForUniqueNickname(); } } } // Only now create the chat system and load Firebase chat createChatSystem(); loadFirebaseChat(); })(); function updateMenu() { menu.style.border = `2px solid ${state.menuColor}`; const color = state.menuColor; circleVisual.style.border = `2px dashed ${hexToRgba(state.menuColor, 0.7)}`; const arrow = state.showCustomization ? '▼' : '▶'; // simple minded like the women i date if (state.simplified) { menu.style.width = state.uiLayout.menu.width !== null ? `${state.uiLayout.menu.width}px` : '320px'; menu.innerHTML = `

${state.menuName}

vXII
Status
Perf Mode: Low (Simplified)
Zoom: ${Math.round(100 / state.zoomFactor)}%
FPS: ${state.fps} (Optimized)
Server: ${state.features.showServer ? (state.server || 'N/A') : 'Hidden'}
Chat: ${state.features.chatVisible ? 'ON' : 'OFF'}
Keybinds: ${state.features.keybindsEnabled ? 'ON' : 'OFF'}
${/* Keep footer */ ''} `; // Add these lines to force performance mode when simplified if (state.features.performanceMode !== 1) { state.features.performanceMode = 1; applyPerformanceMode(); } setTimeout(() => { const btn = document.getElementById('default-menu-btn'); if (btn) { btn.onclick = () => { state.simplified = false; sessionStorage.setItem('modMenuSimplified', 'false'); menu.style.width = state.uiLayout.menu.width !== null ? `${state.uiLayout.menu.width}px` : '460px'; // Restore previous performance mode when exiting simplified state.features.performanceMode = localStorage.getItem('prevPerformanceMode') || 2; applyPerformanceMode(); updateMenu(); }; } }, 0); return; } menu.style.width = state.uiLayout.menu.width !== null ? `${state.uiLayout.menu.width}px` : '460px'; // --- Menu Customization --- let menuHtml = `

${state.menuName}

vXII
${arrow} Menu Customization
`; menuHtml += `

MOVEMENT

${state.keybinds.circleRestriction.toUpperCase()}: Circle Restriction: ${state.features.circleRestriction ? 'ON' : 'OFF'}

${state.keybinds.circleSmaller.toUpperCase()}/${state.keybinds.circleLarger.toUpperCase()}: Circle Size: ${state.circleRadius}px

${state.keybinds.autoCircle.toUpperCase()}: Bot Movement (right): ${state.features.autoCircle ? 'ON' : 'OFF'}

${state.keybinds.autoBoost.toUpperCase()}: Auto Boost: ${state.features.autoBoost ? 'ON' : 'OFF'}

ZOOM

${state.keybinds.zoomIn.toUpperCase()}: Zoom In

${state.keybinds.zoomOut.toUpperCase()}: Zoom Out

${state.keybinds.zoomReset.toUpperCase()}: Reset Zoom

MODS

${(state.keybinds.autoRespawn || 'S').toUpperCase()}: Auto Respawn: ${state.features.autoRespawn ? 'ON' : 'OFF'}

VISUALS

1-3: Performance Mode ${['Low: Minimal','Medium: Balanced','High: Quality'][state.features.performanceMode-1] || 'Off'}

${state.keybinds.fpsDisplay.toUpperCase()}: FPS Display: ${state.features.fpsDisplay ? 'ON' : 'OFF'}

${state.keybinds.deathSound.toUpperCase()}: Death Sound: ${state.features.deathSound ? 'ON' : 'OFF'}

${state.keybinds.showServer.toUpperCase()}: Show Server IP: ${state.features.showServer ? 'ON' : 'OFF'}

LINKS

${state.keybinds.github.toUpperCase()}: GitHub

${state.keybinds.discord.toUpperCase()}: Discord

${state.keybinds.godMode.toUpperCase()}: GodMode

${state.keybinds.reddit ? state.keybinds.reddit.toUpperCase() : 'R'}: Reddit

`; menuHtml += `

STATUS

Game State: ${state.isInGame ? 'In Game' : 'Menu'}

Zoom: ${Math.round(100 / state.zoomFactor)}%

FPS: ${state.fps}

Keybinds: ${state.features.keybindsEnabled ? 'ON' : 'OFF'}

EXTRA

Server: ${state.features.showServer ? (state.server || 'N/A') : 'Hidden'}

(Developers will NEVER ask for money in the chat. Beware of Scammers.)
Press ${state.keybinds.toggleMenu.toUpperCase()} to hide/show menu | DSC.GG/143X | ${state.keybinds.screenshot.toUpperCase()} Screenshot
Made by: dxxthly. & waynesg on Discord
`; menu.innerHTML = menuHtml; const afkBtn = document.getElementById('afk-btn'); const afkStatus = document.getElementById('afk-status'); function setAfk(on) { afkOn = on; if (afkStatus) { afkStatus.textContent = afkOn ? 'ON' : 'OFF'; afkStatus.style.color = afkOn ? 'lime' : 'red'; } if (afkOn) { if (afkInterval) return; afkInterval = setInterval(() => { if (!state.isInGame) return; // Randomly pick left or right const keys = ['ArrowLeft', 'ArrowRight']; const key = keys[Math.floor(Math.random() * 2)]; // Randomly decide to press or release const type = Math.random() > 0.5 ? 'keydown' : 'keyup'; const evt = new KeyboardEvent(type, { key: key, code: key, keyCode: key === 'ArrowLeft' ? 37 : 39, which: key === 'ArrowLeft' ? 37 : 39, bubbles: true }); document.dispatchEvent(evt); }, Math.random() * 400 + 200); // random interval between 200ms and 600ms } else { if (afkInterval) clearInterval(afkInterval); afkInterval = null; // Release both keys just in case ['ArrowLeft', 'ArrowRight'].forEach(key => { const evt = new KeyboardEvent('keyup', { key: key, code: key, keyCode: key === 'ArrowLeft' ? 37 : 39, which: key === 'ArrowLeft' ? 37 : 39, bubbles: true }); document.dispatchEvent(evt); }); } } if (afkBtn) { afkBtn.onclick = () => setAfk(!afkOn); } const nameInput = document.getElementById('mod-menu-name-input'); const colorInput = document.getElementById('mod-menu-color-input'); if (nameInput) { nameInput.addEventListener('input', syncServerBoxWithMenu); } if (colorInput) { colorInput.addEventListener('input', syncServerBoxWithMenu); } const setBgBlackBtn = document.getElementById('set-bg-black-btn'); if (setBgBlackBtn) { setBgBlackBtn.onclick = () => { window.__customBgUrlCurrent = 'https://upload.wikimedia.org/wikipedia/commons/6/68/Solid_black.png'; document.body.style.background = `url("${window.__customBgUrlCurrent}") center/cover no-repeat fixed`; document.querySelectorAll('canvas').forEach(c => { c.style.background = `url("${window.__customBgUrlCurrent}") center/cover`; }); // Optionally, save to localStorage if you want it to persist.. maybe not.. maybe so.. probably localStorage.setItem('customBgBlack', 'true'); window.dispatchEvent(new Event('resize')); }; } const customizationToggle = document.getElementById('customization-toggle'); if (customizationToggle) { customizationToggle.onclick = () => { state.showCustomization = !state.showCustomization; sessionStorage.setItem('showCustomization', state.showCustomization ? 'true' : 'false'); updateMenu(); }; } const trailToggleBtn = document.getElementById('trail-toggle-btn'); if (trailToggleBtn) { trailToggleBtn.onclick = () => { state.features.snakeTrail = !state.features.snakeTrail; if (!state.features.snakeTrail) { state.snakeTrailPoints = []; clearTrailOverlay(); // <--- Add this line to that stupid button thing! } updateMenu(); }; } const trailColorInput = document.getElementById('trail-color-input'); if (trailColorInput) { trailColorInput.oninput = e => { state.features.snakeTrailColor = trailColorInput.value; updateMenu(); }; } const chatToggleBtn = document.getElementById('chat-toggle-btn'); if (chatToggleBtn) { chatToggleBtn.onclick = toggleChatVisible; } const donateBtn = document.getElementById('donate-btn'); if (donateBtn) { donateBtn.onclick = () => { window.open( "https://www.paypal.com/donate/?business=SC3RFTW5QDZJ4&no_recurring=0¤cy_code=USD", "_blank", "toolbar=no,scrollbars=yes,resizable=yes,top=200,left=200,width=520,height=700" ); }; } const changeNickBtn = document.getElementById('change-nickname-btn'); if (changeNickBtn) { changeNickBtn.onclick = async () => { // Remove old nickname localStorage.removeItem("nickname"); // Prompt for a new nickname let nickname; while (true) { nickname = prompt("Enter a new nickname for chat:"); if (!nickname) nickname = "Anon"; nickname = filterProfanity(nickname.trim()); if (!nickname || nickname.trim().length === 0) nickname = "Anon"; break; } localStorage.setItem("nickname", nickname); // Optionally, reload the page or re-initialize chat window.location.reload(); }; } const chatNameColorInput = document.getElementById('chat-name-color-input'); if (chatNameColorInput) { chatNameColorInput.oninput = (e) => { localStorage.setItem('chatNameColor', chatNameColorInput.value); updateMenu(); }; } setTimeout(() => { // Find where dude set up the simplify button: const simplifyBtn = document.getElementById('simplify-menu-btn'); if (simplifyBtn) { simplifyBtn.onclick = () => { // Store current perf mode before changing localStorage.setItem('prevPerformanceMode', state.features.performanceMode); state.simplified = true; state.features.performanceMode = 1; // Force low performance applyPerformanceMode(); sessionStorage.setItem('modMenuSimplified', 'true'); updateMenu(); }; } const nameInput = document.getElementById('mod-menu-name-input'); const nameBtn = document.getElementById('mod-menu-name-btn'); const colorInput = document.getElementById('mod-menu-color-input'); if (nameBtn && nameInput) { nameBtn.onclick = () => { const val = nameInput.value.trim(); if (val.length > 0) { state.menuName = val; localStorage.setItem('modMenuName', val); updateMenu(); } }; nameInput.onkeydown = (e) => { if (e.key === 'Enter') nameBtn.click(); }; } if (colorInput) { colorInput.oninput = (e) => { state.menuColor = colorInput.value; localStorage.setItem('modMenuColor', colorInput.value); syncServerBoxWithMenu(); syncChatBoxWithMenu(); updateMenu(); }; } // --- Keybinds Button Logic --- const keybindsBtn = document.getElementById('open-keybinds-menu-btn'); if (keybindsBtn) keybindsBtn.onclick = showKeybindsMenu; // --- Test Ping Button Logic (Full Menu) --- const testPingBtn = document.getElementById('test-ping-btn'); if (testPingBtn) { testPingBtn.onclick = () => { const resultSpan = document.getElementById('test-ping-result'); resultSpan.textContent = '...'; const start = Date.now(); fetch('https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png', {mode:'no-cors'}).then(() => { const ms = Date.now() - start; resultSpan.textContent = `${ms} ms`; }).catch(() => { resultSpan.textContent = 'Error'; }); }; } // --- Test Ping Button Logic (Simplified Menu) --- const testPingBtnSimple = document.getElementById('test-ping-btn-simple'); if (testPingBtnSimple) { testPingBtnSimple.onclick = () => { const resultSpan = document.getElementById('test-ping-result-simple'); resultSpan.textContent = '...'; const start = Date.now(); fetch('https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png', {mode:'no-cors'}).then(() => { const ms = Date.now() - start; resultSpan.textContent = `${ms} ms`; }).catch(() => { resultSpan.textContent = 'Error'; }); }; } }, 0); syncServerBoxWithMenu(); syncChatBoxWithMenu(); } let lastWheelTime = 0; document.addEventListener('wheel', function(e) { const now = Date.now(); if (now - lastWheelTime < 100) return; // Throttle: 1 event per 100ms lastWheelTime = now; if (!state.features.keybindsEnabled) return; if (document.activeElement && ( document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA' || document.activeElement.isContentEditable )) return; if (!state.isInGame) return; const binds = state.keybinds; let curr = state.zoomFactor; let idx = zoomSteps.findIndex(z => Math.abs(z - curr) < 1e-5); if (idx === -1) { idx = zoomSteps.reduce((best, z, i) => Math.abs(z - curr) < Math.abs(zoomSteps[best] - curr) ? i : best, 0); } if (e.deltaY < 0 && binds.zoomIn === "wheelup") { if (idx > 0) idx--; state.zoomFactor = zoomSteps[idx]; updateMenu(); e.preventDefault(); } else if (e.deltaY > 0 && binds.zoomOut === "wheeldown") { if (idx < zoomSteps.length - 1) idx++; state.zoomFactor = zoomSteps[idx]; updateMenu(); e.preventDefault(); } }, { passive: false }); (function() { const overlay = document.getElementById('keybind-modal-overlay'); if (!overlay) return; const actionEl = document.getElementById('keybind-modal-action'); const cancelBtn = document.getElementById('keybind-modal-cancel'); let pendingAction = null; window.openKeybindModal = function(action) { pendingAction = action; actionEl.textContent = `Action: ${action}`; overlay.style.display = 'flex'; setTimeout(() => { document.addEventListener('keydown', keyListener, true); document.addEventListener('wheel', keyListener, true); // update this }, 100); }; function closeModal() { overlay.style.display = 'none'; document.removeEventListener('keydown', keyListener, true); document.removeEventListener('wheel', keyListener, true); // update this pendingAction = null; } function keyListener(e) { if (!pendingAction) return; e.preventDefault(); // support for mouse wheel note: never doing this again if (e.type === "wheel") { state.keybinds[pendingAction] = e.deltaY < 0 ? "wheelup" : "wheeldown"; localStorage.setItem('modKeybinds', JSON.stringify(state.keybinds)); updateMenu(); closeModal(); return; } state.keybinds[pendingAction] = e.key.toLowerCase(); localStorage.setItem('modKeybinds', JSON.stringify(state.keybinds)); updateMenu(); closeModal(); } cancelBtn.onclick = closeModal; overlay.onclick = function(e) { if (e.target === overlay) closeModal(); }; })(); function displayKey(key) { if (key === "wheelup") return "Wheel Up"; if (key === "wheeldown") return "Wheel Down"; return key.toUpperCase(); } function showKeybindsMenu() { const color = state.menuColor; menu.innerHTML = `

Keybinds

${Object.entries(state.keybinds).map(([action, key]) => ` `).join('')}
Action Key
${action} ${key.toUpperCase()}
Click "Set" to rebind a key. Press "-" to disable keybinds.
`; setTimeout(() => { document.getElementById('back-to-main-menu-btn').onclick = updateMenu; document.querySelectorAll('.set-keybind-btn').forEach(btn => { btn.onclick = () => openKeybindModal(btn.dataset.action); }); }, 0); } const chatToggleBtn = document.getElementById('chat-toggle-btn'); if (chatToggleBtn) { chatToggleBtn.onclick = () => { state.features.chatVisible = !state.features.chatVisible; const chatContainer = document.getElementById('mod-menu-chat-container'); if (chatContainer) { chatContainer.style.display = state.features.chatVisible ? 'flex' : 'none'; } updateMenu(); }; } // === GAME STATE DETECTION === function checkGameState() { const gameCanvas = document.querySelector('canvas'); const loginForm = document.getElementById('login'); state.isInGame = !!(gameCanvas && gameCanvas.style.display !== 'none' && (!loginForm || loginForm.style.display === 'none')); setTimeout(checkGameState, 1000); } checkGameState(); // === CIRCLE RESTRICTION VISUAL === function drawCircleRestriction() { if (state.features.circleRestriction && state.isInGame) { const centerX = window.innerWidth / 2; const centerY = window.innerHeight / 2; circleVisual.style.left = `${centerX}px`; circleVisual.style.top = `${centerY}px`; circleVisual.style.width = `${state.circleRadius * 2}px`; circleVisual.style.height = `${state.circleRadius * 2}px`; circleVisual.style.display = 'block'; } else { circleVisual.style.display = 'none'; } requestAnimationFrame(drawCircleRestriction); } drawCircleRestriction(); // === KEYBINDS (Customizable) === document.addEventListener('keydown', function (e) { const key = e.key.toLowerCase(); const binds = state.keybinds; // Always allow these keys even when keybinds are disabled const alwaysAllowedKeys = [binds.toggleMenu, binds.toggleKeybinds]; if (!state.features.keybindsEnabled && !alwaysAllowedKeys.includes(key)) { return; } if (document.activeElement && ( document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA' || document.activeElement.isContentEditable )) return; if (key === binds.chatEnabled && state.features.chatVisible) { const chatInput = document.getElementById('mod-menu-chat-input'); if (chatInput && document.activeElement !== chatInput) { chatInput.focus(); e.preventDefault(); return; } } switch (key) { case binds.toggleMenu: state.menuVisible = !state.menuVisible; menu.style.display = state.menuVisible ? 'block' : 'none'; break; case binds.toggleKeybinds: state.features.keybindsEnabled = !state.features.keybindsEnabled; updateMenu(); break; case binds.circleRestriction: state.features.circleRestriction = !state.features.circleRestriction; updateMenu(); break; case binds.circleSmaller: state.circleRadius = Math.max(config.minCircleRadius, state.circleRadius - config.circleRadiusStep); updateMenu(); break; case binds.circleLarger: state.circleRadius = Math.min(config.maxCircleRadius, state.circleRadius + config.circleRadiusStep); updateMenu(); break; case binds.autoCircle: state.features.autoCircle = !state.features.autoCircle; if (state.features.autoCircle && !autoCircleRAF) { autoCircleRAF = requestAnimationFrame(autoCircle); } else if (autoCircleRAF) { cancelAnimationFrame(autoCircleRAF); autoCircleRAF = null; } updateMenu(); break; case binds.autoBoost: state.features.autoBoost = !state.features.autoBoost; updateMenu(); break; case binds.fpsDisplay: state.features.fpsDisplay = !state.features.fpsDisplay; fpsDisplay.style.display = state.features.fpsDisplay ? 'block' : 'none'; updateMenu(); break; case binds.deathSound: state.features.deathSound = !state.features.deathSound; updateMenu(); break; case binds.showServer: state.features.showServer = !state.features.showServer; updateMenu(); break; case binds.zoomIn: { let curr = state.zoomFactor; let idx = zoomSteps.findIndex(z => Math.abs(z - curr) < 1e-5); if (idx === -1) { idx = zoomSteps.reduce((best, z, i) => Math.abs(z - curr) < Math.abs(zoomSteps[best] - curr) ? i : best, 0); } if (idx > 0) idx--; state.zoomFactor = zoomSteps[idx]; updateMenu(); } break; case binds.zoomOut: { let curr = state.zoomFactor; let idx = zoomSteps.findIndex(z => Math.abs(z - curr) < 1e-5); if (idx === -1) { idx = zoomSteps.reduce((best, z, i) => Math.abs(z - curr) < Math.abs(zoomSteps[best] - curr) ? i : best, 0); } if (idx < zoomSteps.length - 1) idx++; state.zoomFactor = zoomSteps[idx]; updateMenu(); } break; case binds.zoomReset: state.zoomFactor = 1.0; updateMenu(); break; case binds.autoRespawn: state.features.autoRespawn = !state.features.autoRespawn; if (state.features.autoRespawn) { enableAutoRespawn(); } else { disableAutoRespawn(); } updateMenu(); break; case binds.screenshot: if (state.isInGame) { try { const canvas = document.querySelector('canvas'); if (canvas) { const dataURL = canvas.toDataURL(); const link = document.createElement('a'); link.href = dataURL; link.download = `slither_screenshot_${Date.now()}.png`; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } catch (err) { alert('Screenshot failed: ' + err); } } break; case binds.github: window.open('https://github.com/dxxthly', '_blank'); break; case binds.discord: window.open('https://dsc.gg/143x', '_blank'); break; case binds.godMode: window.open(config.godModeVideoURL, '_blank'); break; case binds.reddit: window.open('https://www.reddit.com/r/Slitherio/', '_blank'); break; case '1': state.features.performanceMode = 1; applyPerformanceMode(); break; case '2': state.features.performanceMode = 2; applyPerformanceMode(); break; case '3': state.features.performanceMode = 3; applyPerformanceMode(); break; } }); // Force connection if she don't like you- make her like you function applyForcedServer() { try { const saved = localStorage.getItem('forcedServer'); if (!saved) return; const server = JSON.parse(saved); if (!server.ip || !server.port) return; // Apply the forced server window.forcing = true; if (!window.bso) window.bso = {}; window.bso.ip = server.ip; window.bso.po = server.port; } catch (e) { console.error("Error applying forced server:", e); } } function patchPlayButtons() { // Main Play button const playBtn = document.getElementById('playh') || document.querySelector('.btn.btn-primary.btn-play-guest'); if (playBtn && !playBtn._patched) { playBtn._patched = true; playBtn.addEventListener('click', () => { setTimeout(applyForcedServer, 0); }); } // Play Again button(s) document.querySelectorAll('.btn.btn-primary.btn-play-again, #play-again').forEach(btn => { if (btn && !btn._patched) { btn._patched = true; btn.addEventListener('click', () => { setTimeout(applyForcedServer, 0); }); } }); } // Check every second to patch buttons as they appear setInterval(patchPlayButtons, 1000); // Apply on page load applyForcedServer(); // === AUTO CIRCLE === function autoCircle() { if (!state.features.autoCircle || !state.isInGame) { autoCircleRAF = null; return; } try { // Increment angle for continuous spinning state.autoCircleAngle += 0.025; // Use consistent window center const centerX = window.innerWidth / 2; const centerY = window.innerHeight / 2; // Use a radius that works well for snake movement const radius = Math.min(Math.max(state.circleRadius, 80), 180); // Calculate position on circle const moveX = centerX + Math.cos(state.autoCircleAngle) * radius; const moveY = centerY + Math.sin(state.autoCircleAngle) * radius; // Move the mouse const canvas = document.querySelector('canvas'); if (canvas) { const event = new MouseEvent('mousemove', { clientX: moveX, clientY: moveY, bubbles: true }); canvas.dispatchEvent(event); } } catch (err) { // Don't let errors break the animation loop } // CRITICAL: Always request next frame while feature is enabled or it be breaking if (state.features.autoCircle) { autoCircleRAF = requestAnimationFrame(autoCircle); } } function drawSnakeTrail() { if (!state.features.snakeTrail || !state.snakeTrailPoints.length) return; const overlay = createTrailOverlayCanvas(); if (!overlay) return; const ctx = overlay.getContext('2d'); ctx.clearRect(0, 0, overlay.width, overlay.height); // Define maximum trail age in milliseconds const TRAIL_MAX_AGE = 1500; // 1.5 seconds const now = Date.now(); // Access Slither.io's actual camera variables - shoutout to my sponsors const viewX = window.snake ? window.snake.xx || 0 : 0; const viewY = window.snake ? window.snake.yy || 0 : 0; const viewZoom = window.gsc || 1; const screenCenterX = window.innerWidth / 2; const screenCenterY = window.innerHeight / 2; ctx.save(); ctx.lineJoin = 'round'; ctx.lineCap = 'round'; ctx.lineWidth = 8; ctx.shadowBlur = 12; ctx.shadowColor = state.features.snakeTrailColor; // Draw each segment separately with its own alpha for (let i = 1; i < state.snakeTrailPoints.length; i++) { const p1 = state.snakeTrailPoints[i-1]; const p2 = state.snakeTrailPoints[i]; // Calculate age of this segment (average of two points) const age = now - ((p1.time + p2.time) / 2); const alpha = Math.max(0, 1 - age / TRAIL_MAX_AGE); // 1 (new) → 0 (old) // Convert both points to screen coordinates const deltaX1 = p1.x - viewX; const deltaY1 = p1.y - viewY; const screenX1 = screenCenterX + deltaX1 * viewZoom; const screenY1 = screenCenterY + deltaY1 * viewZoom; const deltaX2 = p2.x - viewX; const deltaY2 = p2.y - viewY; const screenX2 = screenCenterX + deltaX2 * viewZoom; const screenY2 = screenCenterY + deltaY2 * viewZoom; // Set alpha for this segment ctx.strokeStyle = hexToRgba(state.features.snakeTrailColor, alpha * 0.7); // Draw this segment ctx.beginPath(); ctx.moveTo(screenX1, screenY1); ctx.lineTo(screenX2, screenY2); ctx.stroke(); } ctx.restore(); } // === AUTO BOOST === function autoBoost() { if (!state.features.autoBoost || !state.isInGame) { if (state.boosting) { state.boosting = false; if (typeof window.setAcceleration === 'function') window.setAcceleration(0); document.dispatchEvent(new KeyboardEvent('keyup', { key: ' ' })); } return; } if (!state.boosting) { state.boosting = true; if (typeof window.setAcceleration === 'function') window.setAcceleration(1); document.dispatchEvent(new KeyboardEvent('keydown', { key: ' ' })); } } function autoBoostLoop() { autoBoost(); setTimeout(autoBoostLoop, 100); } autoBoostLoop(); // === FPS COUNTER === function fpsCounter() { state.fpsFrames++; const now = Date.now(); if (now - state.fpsLastCheck >= 1000) { state.fps = state.fpsFrames; state.fpsFrames = 0; state.fpsLastCheck = now; if (state.features.fpsDisplay) { fpsDisplay.textContent = `FPS: ${state.fps}`; } } requestAnimationFrame(fpsCounter); } fpsCounter(); // === DEATH SOUND === function deathSoundObserver() { let lastAlive = true; setInterval(async () => { if (!state.features.deathSound) return; // Check death status using multiple methods because waynes gay const isDead = (window.snake && !window.snake.alive) || (document.getElementById('died')?.style.display !== 'none'); if (lastAlive && isDead) { try { state.deathSound.currentTime = 0; await state.deathSound.play(); } catch (err) { // Fallback: Create new audio instance const fallbackAudio = new Audio(config.deathSoundURL); fallbackAudio.play().catch(() => { console.log('Audio playback blocked. Click the game first!'); }); } } lastAlive = !isDead; }, 100); } state.deathSound.preload = 'auto'; state.deathSound.load(); state.deathSound.addEventListener('ended', () => { state.deathSound.currentTime = 0; }); deathSoundObserver(); // === PERFORMANCE MODES === function applyPerformanceMode() { if (typeof window !== "undefined") { switch (state.features.performanceMode) { case 1: window.want_quality = 0; window.high_quality = false; window.render_mode = 1; break; case 2: window.want_quality = 1; window.high_quality = false; window.render_mode = 2; break; case 3: window.want_quality = 2; window.high_quality = true; window.render_mode = 2; break; default: break; } } updateMenu(); } applyPerformanceMode(); // === ZOOM LOCK === function zoomLockLoop() { if (typeof window.gsc !== 'undefined') { window.gsc = state.zoomFactor; } requestAnimationFrame(zoomLockLoop); } zoomLockLoop(); // === PING DISPLAY === function pingLoop() { let ping = 0; if (window.lagging && typeof window.lagging === "number") { ping = Math.round(window.lagging); } else if (window.lag && typeof window.lag === "number") { ping = Math.round(window.lag); } state.ping = ping; pingDisplay.textContent = `Ping: ${ping} ms`; const pingValue = document.getElementById("ping-value"); if (pingValue) pingValue.textContent = `${ping} ms`; setTimeout(pingLoop, 500); } pingLoop(); // === SCREENSHOT BUTTON (P) === document.addEventListener('keydown', function (e) { if (e.key.toLowerCase() === 'p' && state.isInGame) { try { const canvas = document.querySelector('canvas'); if (canvas) { const dataURL = canvas.toDataURL(); const link = document.createElement('a'); link.href = dataURL; link.download = `slither_screenshot_${Date.now()}.png`; document.body.appendChild(link); link.click(); document.body.removeChild(link); } } catch (err) { alert('Screenshot failed: ' + err); } } }); function clearTrailOverlay() { const overlay = document.getElementById('snake-trail-overlay'); if (overlay) { const ctx = overlay.getContext('2d'); ctx.clearRect(0, 0, overlay.width, overlay.height); overlay.style.display = 'none'; // <--- Hide the overlay when trail is off } } // === INITIAL MENU VISIBILITY === menu.style.display = state.menuVisible ? 'block' : 'none'; // === INITIAL FPS DISPLAY === fpsDisplay.style.display = state.features.fpsDisplay ? 'block' : 'none'; // === INITIAL PING DISPLAY === pingDisplay.style.display = 'block'; // === INITIAL CIRCLE VISUAL COLOR === circleVisual.style.border = `2px dashed ${hexToRgba(state.menuColor, 0.7)}`; function snakeTrailAnimationLoop() { requestAnimationFrame(snakeTrailAnimationLoop); drawSnakeTrail(); } snakeTrailAnimationLoop(); setInterval(() => { if (!state.features.snakeTrail) { state.snakeTrailPoints = []; return; } // Get mouse screen position const mouseX = realMouseX; const mouseY = realMouseY; // Convert screen position to world (game) coordinates const viewX = window.snake ? window.snake.xx || 0 : 0; const viewY = window.snake ? window.snake.yy || 0 : 0; const viewZoom = window.gsc || 1; const screenCenterX = window.innerWidth / 2; const screenCenterY = window.innerHeight / 2; // This formula converts screen (mouse) to world coordinates const worldX = viewX + (mouseX - screenCenterX) / viewZoom; const worldY = viewY + (mouseY - screenCenterY) / viewZoom; if ( state.snakeTrailPoints.length === 0 || Math.abs(state.snakeTrailPoints[state.snakeTrailPoints.length-1].x - worldX) > 1 || Math.abs(state.snakeTrailPoints[state.snakeTrailPoints.length-1].y - worldY) > 1 ) { state.snakeTrailPoints.push({ x: worldX, y: worldY, time: Date.now() }); // Limit trail length if (state.snakeTrailPoints.length > 100) state.snakeTrailPoints.shift(); } }, 30); document.addEventListener('click', async function(e) { const chatUserSpan = e.target.closest('.chat-username'); if (!chatUserSpan) { document.getElementById('profile-popup')?.remove(); return; } document.getElementById('profile-popup')?.remove(); const uid = chatUserSpan.dataset.uid; const username = chatUserSpan.textContent; // Get menu color from state const menuColor = state.menuColor || '#4CAF50'; // Fetch online status from Firebase let isOnline = false; try { const onlineSnap = await firebase.database().ref("onlineUsers/" + uid).once('value'); isOnline = !!(onlineSnap.exists() && onlineSnap.val() && onlineSnap.val().name); } catch { isOnline = false; } // Optionally, use a default avatar or generate one: const avatarUrl = `https://api.dicebear.com/7.x/identicon/svg?seed=${encodeURIComponent(uid)}`; // Build the popup const popup = document.createElement('div'); popup.className = 'profile-popup'; popup.id = 'profile-popup'; popup.style.setProperty('--menu-color', menuColor); popup.innerHTML = ` Avatar
${username}
${isOnline ? 'Online' : 'Offline'}
UID: ${uid}
`; document.body.appendChild(popup); // Close logic popup.querySelector('.close-btn').onclick = () => popup.remove(); popup.onclick = e => e.stopPropagation(); // Prevent click-through // Remove popup on outside click or ESC setTimeout(() => { document.addEventListener('click', function handler(ev) { if (!popup.contains(ev.target)) { popup.remove(); document.removeEventListener('click', handler, true); } }, true); document.addEventListener('keydown', function handler(ev) { if (ev.key === "Escape") { popup.remove(); document.removeEventListener('keydown', handler, true); } }, true); }, 0); }); const popupKey = 'vix7UpdatePopupSeen'; // Check if the user has already seen the popup if (localStorage.getItem(popupKey) === 'true') { return; // Don't show it again if they've already closed it } // --- Create the visual elements --- const overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0, 0, 0, 0.8); z-index: 100000; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; `; const popup = document.createElement('div'); popup.style.cssText = ` background: #28282e; color: #e8e8e8; padding: 30px 40px; border-radius: 12px; border: 2px solid #e91e63; box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5); text-align: center; max-width: 550px; line-height: 1.7; `; popup.innerHTML = `

Update Required!

The newest version of the mod menu is on our Discord.

Go to DSC.GG/143X to download now.

Be sure to read the Greasy Fork post for instructions.

`; overlay.appendChild(popup); document.body.appendChild(overlay); // --- Add functionality to the close button --- const closeButton = document.getElementById('update-popup-close-btn'); if (closeButton) { closeButton.onclick = function() { // Set the flag in localStorage so it doesn't show again localStorage.setItem(popupKey, 'true'); overlay.remove(); }; } })();