// ==UserScript== // @name The definitive cco experience // @namespace http://tampermonkey.net/ // @version 1.0 // @description Wallpapers, themes, cb teams and chat features // @author ZSB // @match *://*.case-clicker.com/* // @require https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/pickr.min.js // @resource PICKR_CSS https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/themes/nano.min.css // @grant GM_addStyle // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_getResourceText // @connect workers.dev // @run-at document-body // ==/UserScript== (function() { 'use strict'; // ========================================================================= // === CONFIGURATION === // ========================================================================= const vpsDomain = 'https://walp.bobbyatthelobby.workers.dev'; const DEFAULT_THEME_CONFIG = { mainBackground: '#100d18', panelBackground: '#1a1527', primaryText: '#f4dfff', dimmedText: '#bba8d1', accentColor: '#79caff', usernameColor: '#ff8c00', canvasBackground: 'rgba(0, 0, 0, 0)', buttonGradientStart: '#4A3763', buttonGradientEnd: '#2C1D3D', buttonBorder: '#7a5a9b', buttonText: '#f4dfff', buttonHoverGlow: 'rgba(121, 202, 255, 0.5)' }; const THEME_LABELS = { mainBackground: 'Page Background', panelBackground: 'Panel & Card Background', primaryText: 'Accent & Chat text', dimmedText: 'Dimmed Text', accentColor: 'Primary Color', usernameColor: 'Username Color', canvasBackground: 'Plinko Background', buttonGradientStart: 'Button Gradient left', buttonGradientEnd: 'Button Gradient right', buttonBorder: 'Button Border', buttonText: 'Button Text', buttonHoverGlow: 'Button Hover Glow' }; const PANEL_IDS = ['wallpaper-panel', 'cb-teams-panel', 'theme-editor-panel', 'advanced-chat-panel']; // ========================================================================= // === DYNAMIC THEME & STYLE INJECTION === // ========================================================================= let currentTheme = { ...DEFAULT_THEME_CONFIG, ...GM_getValue('lastLoadedTheme', {}) }; function setCssVariable(key, value) { const cssVarName = '--' + key.replace(/([A-Z])/g, '-$1').toLowerCase(); document.documentElement.style.setProperty(cssVarName, value, 'important'); } function applyTheme(theme) { for (const [key, value] of Object.entries(theme)) { setCssVariable(key, value); } } applyTheme(currentTheme); GM_addStyle(GM_getResourceText("PICKR_CSS")); GM_addStyle(` :root { --main-background: ${DEFAULT_THEME_CONFIG.mainBackground}; --panel-background: ${DEFAULT_THEME_CONFIG.panelBackground}; --primary-text: ${DEFAULT_THEME_CONFIG.primaryText}; --dimmed-text: ${DEFAULT_THEME_CONFIG.dimmedText}; --accent-color: ${DEFAULT_THEME_CONFIG.accentColor}; --username-color: ${DEFAULT_THEME_CONFIG.usernameColor}; --canvas-background: ${DEFAULT_THEME_CONFIG.canvasBackground}; --button-gradient-start: ${DEFAULT_THEME_CONFIG.buttonGradientStart}; --button-gradient-end: ${DEFAULT_THEME_CONFIG.buttonGradientEnd}; --button-border: ${DEFAULT_THEME_CONFIG.buttonBorder}; --button-text: ${DEFAULT_THEME_CONFIG.buttonText}; --button-hover-glow: ${DEFAULT_THEME_CONFIG.buttonHoverGlow}; --mantine-color-orange-text: var(--username-color) !important; --mantine-color-dimmed: var(--dimmed-text) !important; } body { color: var(--primary-text) !important; } a { color: var(--accent-color) !important; } p[data-truncate="end"][style*="color: var(--mantine-color-orange-text)"] { color: var(--username-color) !important; } .text-gray-400, [data-mantine-color="dimmed"] { color: var(--dimmed-text) !important; } .userscript-btn, button, input:not([type=color]), select { background: linear-gradient(145deg, var(--button-gradient-start), var(--button-gradient-end)) !important; border: 1px solid var(--button-border) !important; color: var(--button-text) !important; box-shadow: 0 2px 5px rgba(0,0,0,0.3); transition: all 0.2s ease-in-out; font-weight: bold; border-radius: 4px; } .userscript-btn:hover, button:hover { transform: translateY(-1px); box-shadow: 0 0 15px 2px var(--button-hover-glow), 0 4px 8px rgba(0,0,0,0.4); filter: brightness(1.1); } body:not(.wallpaper-disabled) #__next, body:not(.wallpaper-disabled) .mantine-AppShell-main, body:not(.wallpaper-disabled) .mantine-AppShell-header, body:not(.wallpaper-disabled) .mantine-AppShell-navbar, body:not(.wallpaper-disabled) .mantine-AppShell-aside, body:not(.wallpaper-disabled) .mantine-Card-root, body:not(.wallpaper-disabled) .mantine-Paper-root { background: none !important; background-color: transparent !important; } body.wallpaper-disabled .mantine-AppShell-main { background-color: var(--main-background) !important; } body.wallpaper-disabled .mantine-Card-root, body.wallpaper-disabled .mantine-Paper-root, body.wallpaper-disabled .mantine-AppShell-header, body.wallpaper-disabled .mantine-AppShell-navbar, body.wallpaper-disabled .mantine-AppShell-aside { background-color: var(--panel-background) !important; } #plinko canvas[style*="background"] { background: var(--canvas-background) !important; } #plinko ~ .mantine-Group-root .mantine-Card-root { background-color: var(--panel-background) !important; } .floating-panel { position: fixed; z-index: 10000; font-family: 'Segoe UI', sans-serif; border: 1px solid rgba(255, 255, 255, 0.18); border-radius: 12px; box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); color: #f0f0f0; min-width: 240px; max-width: 90vw; min-height: 100px; max-height: 90vh; overflow: hidden; background: rgba(26, 21, 39, 0.85); backdrop-filter: blur(10px); display: flex; flex-direction: column; } .floating-panel.minimized { display: none !important; } .panel-header { padding: 12px 16px; background: rgba(255, 255, 255, 0.1); display: flex; justify-content: space-between; align-items: center; font-weight: bold; flex-shrink: 0; } .panel-header-text { cursor: move; flex-grow: 1; user-select: none; } .panel-minimize-button { cursor: pointer; font-weight: bold; font-size: 1.2em; user-select: none; } .panel-content { flex-grow: 1; overflow-y: auto; padding: 0; } .panel-resize-handle { position: absolute; bottom: 0; right: 0; width: 15px; height: 15px; cursor: se-resize; background: linear-gradient(135deg, transparent 50%, rgba(255,255,255,0.2) 50%); } .floating-panel.snapping { transition: outline 0.1s ease; outline: 2px solid var(--accent-color) !important; } .wallpaper-option { padding: 10px 14px; cursor: pointer; border-radius: 6px; font-size: 0.9em; margin-bottom: 4px; transition: background-color 0.2s ease; display: flex; justify-content: space-between; align-items: center; } .wallpaper-option:hover { background-color: rgba(121, 202, 255, 0.2); } .favorite-star { cursor: pointer; font-size: 1.2em; transition: color 0.2s, transform 0.2s; user-select: none; } .favorite-star:hover { transform: scale(1.2); } .favorite-star.favorited { color: #ffd700; } .special-option { border-top: 1px solid #333; margin-top: 4px; font-weight: bold; color: var(--accent-color); justify-content: center; } #team-value-sums { display: none; } #cb-teams-panel.enabled #team-value-sums { display: block; } #toggle-cb-button.on { border-color: #2ecc71 !important; box-shadow: inset 0 0 8px rgba(46, 204, 113, 0.5) !important; } #toggle-cb-button.off { filter: grayscale(50%); opacity: 0.8; } .wallpaper-engine-iframe { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; border: none; z-index: -9999; } .script-toolbar-button { display: inline-flex; align-items: center; justify-content: center; height: 30px; padding: 0 16px; font-size: var(--mantine-font-size-sm); margin-left: calc(1rem * var(--mantine-scale)) !important; border-radius: var(--mantine-radius-sm); cursor: pointer; } .script-toolbar-button span { margin-left: 8px; } .panel-content-inner { padding: 12px; } #theme-profile-manager { border-bottom: 1px solid #333; padding-bottom: 12px; margin-bottom: 12px; } #theme-profile-manager select, #theme-profile-manager input { width: 100%; box-sizing: border-box; margin-bottom: 8px; padding: 4px; } #theme-profile-manager select option { background: var(--panel-background) !important; color: var(--primary-text) !important; } #theme-profile-manager div { display: flex; gap: 8px; flex-wrap: wrap; } #theme-profile-manager button { flex-grow: 1; } .theme-editor-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; border-radius: 4px; padding: 2px 4px; transition: background-color 0.2s ease; } .theme-editor-row:hover { background-color: rgba(121, 202, 255, 0.1); } .theme-editor-row label { font-size: 0.9em; flex-shrink: 0; margin-right: 8px; } .pickr-swatch { width: 80px; height: 25px; border: 1px solid #555; border-radius: 4px; cursor: pointer; flex-shrink: 0; } .pcr-app { background: var(--panel-background) !important; border-radius: 8px !important; box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37) !important; z-index: 10003 !important; } .pcr-interaction input { color: var(--primary-text) !important; border-color: var(--button-border) !important; } .pcr-interaction .pcr-save { background: var(--button-gradient-start) !important; } .rainbow-mode .mantine-Text-root, .rainbow-mode a, .rainbow-mode p[data-truncate="end"][style*="color: var(--mantine-color-orange-text)"], .rainbow-mode [data-mantine-color="dimmed"] { background-image: linear-gradient(90deg, #ff00ff, #00ffff, #ffff00, #ff00ff) !important; -webkit-background-clip: text !important; background-clip: text !important; color: transparent !important; background-size: 200% 100% !important; animation: rainbow-scroll 3s linear infinite !important; } @keyframes rainbow-scroll { 0% { background-position: 200% 0; } 100% { background-position: 0 0; } } #theme-editor-toggles, .chat-settings-section { border-bottom: 1px solid #333; padding-bottom: 12px; margin-bottom: 12px; display: flex; flex-direction: column; gap: 8px; } .toggle-row, .setting-row { display: flex; align-items: center; justify-content: space-between; font-size: 0.9em; } .switch { position: relative; display: inline-block; width: 44px; height: 24px; flex-shrink: 0; } .switch input { opacity: 0; width: 0; height: 0; } .slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: #3e3850; transition: .3s; border-radius: 24px; } .slider:before { position: absolute; content: ""; height: 18px; width: 18px; left: 3px; bottom: 3px; background-color: white; transition: .3s; border-radius: 50%; } input:checked + .slider { background-color: var(--accent-color); } input:checked + .slider:before { transform: translateX(20px); } /* --- ADVANCED CHAT STYLES --- */ #master-chat-modal { /* The single modal container */ display: none; /* Hidden by default */ position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: rgba(0, 0, 0, 0.7); z-index: 10002; /* Highest priority */ justify-content: center; align-items: center; } #master-chat-modal-content { background: var(--panel-background); padding: 20px; border-radius: 12px; border: 1px solid var(--button-border); box-shadow: 0 5px 25px rgba(0,0,0,0.5); min-width: 250px; text-align: center; } #master-chat-modal-header { font-size: 1.2em; font-weight: bold; margin-bottom: 20px; color: var(--primary-text); } #master-chat-modal-header .username { color: var(--accent-color); } #master-chat-modal-body button { display: block; width: 100%; margin-bottom: 10px; padding: 10px; } .chat-keyword-highlight > div[class*="mantine-Paper-root"] { background: rgba(255, 215, 0, 0.15) !important; border-left: 3px solid #ffd700; } .chat-settings-list { list-style: none; padding: 0; margin: 0; max-height: 120px; overflow-y: auto; background: rgba(0,0,0,0.2); border-radius: 4px; padding: 5px; } .chat-settings-list li { display: flex; justify-content: space-between; align-items: center; padding: 4px 8px; font-size: 0.85em; } .chat-settings-list li:nth-child(even) { background-color: rgba(255,255,255,0.05); } .remove-item-btn { cursor: pointer; color: #ff6b6b; font-weight: bold; } .user-tag { font-size: 10px; padding: 1px 5px; border-radius: 8px; background-color: var(--accent-color); color: var(--panel-background); font-weight: bold; margin-left: 6px; text-shadow: none; display: inline-block; vertical-align: middle; } #tagged-users-list .tag-text { font-style: italic; background: rgba(255,255,255,0.1); padding: 2px 5px; border-radius: 4px; font-size: 0.9em; margin-left: 8px; } `); // ========================================================================= // === GLOBAL HELPERS === // ========================================================================= let activeWallpaperWindow = null; window.addEventListener('mousemove', (e) => { if (activeWallpaperWindow) activeWallpaperWindow.postMessage({ type: 'mousemove', x: e.clientX, y: e.clientY }, '*'); }); function getContrastingTextColor(hexColor) { if (!hexColor || hexColor.length < 4) return '#FFFFFF'; let r, g, b; if (hexColor.length === 4) { r = parseInt(hexColor[1] + hexColor[1], 16); g = parseInt(hexColor[2] + hexColor[2], 16); b = parseInt(hexColor[3] + hexColor[3], 16); } else { r = parseInt(hexColor.substr(1, 2), 16); g = parseInt(hexColor.substr(3, 2), 16); b = parseInt(hexColor.substr(5, 2), 16); } const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000; return (yiq >= 128) ? '#000000' : '#FFFFFF'; } function createDraggablePanel(id, headerText, innerHTML, defaultPos) { let container = document.getElementById(id); if (container) return { container, minimizeButton: container.querySelector('.panel-minimize-button'), contentArea: container.querySelector('.panel-content-inner') }; container = document.createElement('div'); container.id = id; container.className = 'floating-panel'; container.innerHTML = `
${headerText}
${innerHTML}
`; document.body.appendChild(container); const header = container.querySelector('.panel-header-text'); const minimizeButton = container.querySelector('.panel-minimize-button'); const contentArea = container.querySelector('.panel-content-inner'); const resizeHandle = container.querySelector('.panel-resize-handle'); let isDragging = false, isResizing = false; let offset = { x: 0, y: 0 }; let initialSize = { width: 0, height: 0 }; header.addEventListener('mousedown', (e) => { isDragging = true; offset = { x: e.clientX - container.offsetLeft, y: e.clientY - container.offsetTop }; }); resizeHandle.addEventListener('mousedown', (e) => { e.stopPropagation(); isResizing = true; offset = { x: e.clientX, y: e.clientY }; initialSize = { width: container.offsetWidth, height: container.offsetHeight }; }); document.addEventListener('mousemove', (e) => { if (isDragging) { let newLeft = e.clientX - offset.x; let newTop = e.clientY - offset.y; const snapThreshold = 20; let isSnapping = false; PANEL_IDS.forEach(otherId => { if (otherId === id) return; const otherPanel = document.getElementById(otherId); if (!otherPanel || otherPanel.classList.contains('minimized')) return; const otherRect = otherPanel.getBoundingClientRect(); const draggedRect = { left: newLeft, top: newTop, right: newLeft + container.offsetWidth, bottom: newTop + container.offsetHeight }; if (Math.abs(draggedRect.right - otherRect.left) < snapThreshold) { newLeft = otherRect.left - container.offsetWidth; isSnapping = true; } if (Math.abs(draggedRect.left - otherRect.right) < snapThreshold) { newLeft = otherRect.right; isSnapping = true; } if (Math.abs(draggedRect.left - otherRect.left) < snapThreshold) { newLeft = otherRect.left; isSnapping = true; } if (Math.abs(draggedRect.right - otherRect.right) < snapThreshold) { newLeft = otherRect.right - container.offsetWidth; isSnapping = true; } if (Math.abs(draggedRect.bottom - otherRect.top) < snapThreshold) { newTop = otherRect.top - container.offsetHeight; isSnapping = true; } if (Math.abs(draggedRect.top - otherRect.bottom) < snapThreshold) { newTop = otherRect.bottom; isSnapping = true; } if (Math.abs(draggedRect.top - otherRect.top) < snapThreshold) { newTop = otherRect.top; isSnapping = true; } if (Math.abs(draggedRect.bottom - otherRect.bottom) < snapThreshold) { newTop = otherRect.bottom - container.offsetHeight; isSnapping = true; } }); if (newLeft < snapThreshold) { newLeft = 0; isSnapping = true; } if (newTop < snapThreshold) { newTop = 0; isSnapping = true; } if (newLeft + container.offsetWidth > window.innerWidth - snapThreshold) { newLeft = window.innerWidth - container.offsetWidth; isSnapping = true; } if (newTop + container.offsetHeight > window.innerHeight - snapThreshold) { newTop = window.innerHeight - container.offsetHeight; isSnapping = true; } container.classList.toggle('snapping', isSnapping); container.style.left = `${newLeft}px`; container.style.top = `${newTop}px`; } if (isResizing) { const newWidth = initialSize.width + (e.clientX - offset.x); const newHeight = initialSize.height + (e.clientY - offset.y); container.style.width = `${newWidth}px`; container.style.height = `${newHeight}px`; } }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; container.classList.remove('snapping'); GM_setValue(`${id}Position`, { top: container.style.top, left: container.style.left }); } if (isResizing) { isResizing = false; GM_setValue(`${id}Dimensions`, { width: container.style.width, height: container.style.height }); } }); container.addEventListener('wheel', (e) => { e.preventDefault(); e.stopPropagation(); const scrollDirection = Math.sign(e.deltaY); const currentOpacity = parseFloat(container.style.opacity) || 1.0; let newOpacity = currentOpacity - (scrollDirection * 0.05); newOpacity = Math.max(0.2, Math.min(1, newOpacity)); container.style.opacity = newOpacity; GM_setValue(`${id}Opacity`, newOpacity); }, { passive: false }); const savedPos = GM_getValue(`${id}Position`, defaultPos); container.style.top = savedPos.top; container.style.left = savedPos.left; const savedDims = GM_getValue(`${id}Dimensions`); if (savedDims) { container.style.width = savedDims.width; container.style.height = savedDims.height; } const savedOpacity = GM_getValue(`${id}Opacity`, 1.0); container.style.opacity = savedOpacity; return { container, minimizeButton, contentArea }; } // ========================================================================= // === TOOLBAR SYNC & STATE MGMT === // ========================================================================= function syncToolbar() { const serverStatsButton = Array.from(document.querySelectorAll('button')).find(btn => btn.textContent.includes('Show Serverstats')); if (!serverStatsButton || !serverStatsButton.parentElement) return; const toolbar = serverStatsButton.parentElement; function createOrGetButton(id, text, onClick) { let btn = document.getElementById(id); if (!btn) { btn = document.createElement('button'); btn.id = id; btn.className = 'script-toolbar-button userscript-btn'; btn.innerHTML = text; btn.onclick = onClick; toolbar.appendChild(btn); } return btn; } const wpBtn = createOrGetButton('restore-wallpaper-btn', '🎨Wallpapers', () => { document.getElementById('wallpaper-panel')?.classList.remove('minimized'); GM_setValue('wallpaper-panelMinimized', false); syncToolbar(); }); const cbBtn = createOrGetButton('restore-cb-teams-btn', '📊CB Teams', () => { document.getElementById('cb-teams-panel')?.classList.remove('minimized'); GM_setValue('cb-teams-panelMinimized', false); syncToolbar(); }); const themeBtn = createOrGetButton('restore-theme-editor-btn', '🖌️Theme', () => { document.getElementById('theme-editor-panel')?.classList.remove('minimized'); GM_setValue('theme-editor-panelMinimized', false); syncToolbar(); }); const chatBtn = createOrGetButton('restore-advanced-chat-btn', '💬Chat', () => { document.getElementById('advanced-chat-panel')?.classList.remove('minimized'); GM_setValue('advanced-chat-panelMinimized', false); syncToolbar(); }); wpBtn.style.display = GM_getValue('wallpaper-panelMinimized', false) ? 'inline-flex' : 'none'; cbBtn.style.display = GM_getValue('cb-teams-panelMinimized', false) ? 'inline-flex' : 'none'; themeBtn.style.display = GM_getValue('theme-editor-panelMinimized', false) ? 'inline-flex' : 'none'; const chatPanelExists = !!document.getElementById('advanced-chat-panel'); if (chatPanelExists) { chatBtn.disabled = false; chatBtn.style.opacity = '1'; chatBtn.style.cursor = 'pointer'; chatBtn.title = 'Show Advanced Chat Settings'; chatBtn.style.display = GM_getValue('advanced-chat-panelMinimized', false) ? 'inline-flex' : 'none'; } else { chatBtn.disabled = true; chatBtn.style.opacity = '0.5'; chatBtn.style.cursor = 'not-allowed'; chatBtn.title = 'Chat settings are not available on this page.'; chatBtn.style.display = 'inline-flex'; } } // ========================================================================= // === WALLPAPER MODULE === // ========================================================================= function initWallpaperModule() { let dynamicWallpapers = {}; let favoriteWallpapers = GM_getValue('favoriteWallpapers', []); let currentView = 'all'; function loadWallpaper(wallpaperId) { if (wallpaperId === 'random') { const visibleIds = Array.from(contentArea.querySelectorAll('.wallpaper-option[data-id]:not(.special-option)')) .map(el => el.dataset.id) .filter(id => id !== 'none'); if (visibleIds.length > 0) { const randomId = visibleIds[Math.floor(Math.random() * visibleIds.length)]; loadWallpaper(randomId); } return; } const currentIframe = document.querySelector('.wallpaper-engine-iframe'); activeWallpaperWindow = null; if (wallpaperId === 'none') { if (currentIframe) currentIframe.remove(); document.body.classList.add('wallpaper-disabled'); GM_setValue('selectedWallpaper', 'none'); return; } const wallpaper = dynamicWallpapers[wallpaperId]; if (!wallpaper) return; GM_xmlhttpRequest({ method: 'GET', url: `${vpsDomain}/${wallpaper.folder}`, onload: function(response) { const newIframe = document.createElement('iframe'); newIframe.className = 'wallpaper-engine-iframe'; newIframe.style.opacity = '0'; newIframe.addEventListener('load', () => { if (currentIframe) currentIframe.remove(); document.body.classList.remove('wallpaper-disabled'); activeWallpaperWindow = newIframe.contentWindow; newIframe.style.transition = 'opacity 0.4s ease'; newIframe.style.opacity = '1'; }, { once: true }); const patchScript = `