RBX Customize

Customize Roblox with animated backgrounds and fonts.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         RBX Customize
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Customize Roblox with animated backgrounds and fonts.
// @author       Find
// @match        https://*.roblox.com/*
// @grant        GM_setValue
// @grant        GM_getValue
// @run-at       document-end
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    const config = {
        preset: 'matrix',
        transparency: 0.2,
        fontName: '',
        btnPos: { top: 'auto', bottom: '20px', left: 'auto', right: '20px' },
        firstTime: true
    };

    let settings = { ...config, ...GM_getValue('rbx_custom_settings', {}) };
    if (!settings.btnPos) settings.btnPos = config.btnPos;

    let loopId = null;

    const ui = {
        btn: null,
        panel: null,
        overlay: null,
        loader: null
    };

    function start() {
        if (document.getElementById('rbx-custom-btn')) return;

        buildBtn();
        buildMenu();
        render();

        new MutationObserver(() => {
            if (document.body && !document.getElementById('rbx-custom-btn')) {
                start();
            }
        }).observe(document.body, { childList: true, subtree: true });
    }

    function buildBtn() {
        ui.btn = document.createElement('div');
        ui.btn.id = 'rbx-custom-btn';
        ui.btn.innerText = 'RBX Customize';

        Object.assign(ui.btn.style, {
            position: 'fixed',
            zIndex: '10001',
            background: '#111',
            color: '#00ffaa',
            border: '2px solid #00ffaa',
            borderRadius: '8px',
            cursor: 'pointer',
            fontFamily: 'sans-serif',
            fontWeight: 'bold',
            boxShadow: '0 0 10px rgba(0, 255, 170, 0.3)',
            transition: 'transform 0.1s, top 0.3s, left 0.3s, right 0.3s, bottom 0.3s',
            userSelect: 'none',
            textAlign: 'center',
            fontSize: '14px',
            width: '120px',
            height: '40px',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            boxSizing: 'border-box',
            ...settings.btnPos
        });

        document.body.appendChild(ui.btn);
        initDrag(ui.btn);

        if (settings.firstTime) {
            tooltip();
            settings.firstTime = false;
            GM_setValue('rbx_custom_settings', settings);
        }
    }

    function buildMenu() {
        ui.panel = document.createElement('div');
        ui.panel.id = 'rbx-custom-panel';

        Object.assign(ui.panel.style, {
            position: 'fixed',
            top: '50%', left: '50%',
            transform: 'translate(-50%, -50%)',
            zIndex: '10002',
            background: 'rgba(10, 10, 10, 0.95)',
            color: 'white',
            padding: '20px',
            borderRadius: '12px',
            border: '1px solid #333',
            display: 'none',
            width: '280px',
            fontFamily: 'sans-serif',
            backdropFilter: 'blur(15px)',
            boxShadow: '0 10px 30px rgba(0,0,0,0.8)'
        });

        ui.panel.innerHTML = `
            <h3 style="margin:0 0 10px 0; border-bottom:1px solid #333; padding-bottom:10px; color:#00ffaa; font-size:16px;">RBX Customize</h3>
            <div style="font-size:10px; color:#888; margin-bottom:15px; margin-top:-5px;">Click and hold the RBX customize button to drag it.</div>
            <div style="margin-bottom: 15px;">
                <label style="font-weight:bold; color:#aaa; font-size:11px;">ANIMATION</label>
                <select id="presetSelect" style="width:100%; margin-top:5px; padding:10px; background:#222; color:#fff; border:1px solid #444; border-radius: 4px; cursor:pointer;">
                    <option value="matrix" ${settings.preset === 'matrix' ? 'selected' : ''}>💻 Matrix Rain</option>
                    <option value="fireworks" ${settings.preset === 'fireworks' ? 'selected' : ''}>🎆 Fireworks</option>
                    <option value="storm" ${settings.preset === 'storm' ? 'selected' : ''}>⚡ Thunderstorm</option>
                    <option value="neural" ${settings.preset === 'neural' ? 'selected' : ''}>🧠 Neural Link</option>
                    <option value="snow" ${settings.preset === 'snow' ? 'selected' : ''}>❄️ Night Snow</option>
                </select>
            </div>
            <div style="margin-bottom: 15px;">
                <label style="font-weight:bold; color:#aaa; font-size:11px;">FONT (Google Fonts)</label>
                <input type="text" id="fontInput" value="${settings.fontName}" placeholder="e.g. Orbitron" style="width: 100%; padding: 8px; margin-top:5px; background: #222; color: #fff; border: 1px solid #444; border-radius: 4px;">
            </div>
            <div style="margin-bottom: 20px;">
                 <label style="font-weight:bold; font-size:11px; color:#aaa;">TRANSPARENCY</label>
                 <input type="range" id="transparencyInput" min="0" max="1" step="0.05" value="${settings.transparency}" style="width: 100%; margin-top:5px;">
            </div>
            <div style="display:flex; gap: 10px;">
                <button id="saveBtn" style="flex:1; padding: 10px; background: #00ffaa; color: #000; border: none; border-radius: 6px; font-weight: bold; cursor: pointer;">APPLY</button>
                <button id="closeBtn" style="padding: 10px 15px; background: #333; color: #fff; border: none; border-radius: 6px; cursor: pointer;">X</button>
            </div>
        `;

        document.body.appendChild(ui.panel);

        document.getElementById('closeBtn').onclick = () => ui.panel.style.display = 'none';

        document.getElementById('saveBtn').onclick = () => {
            const btn = document.getElementById('saveBtn');
            settings.preset = document.getElementById('presetSelect').value;
            settings.transparency = document.getElementById('transparencyInput').value;
            settings.fontName = document.getElementById('fontInput').value.trim();
            settings.btnPos = {
                top: ui.btn.style.top, bottom: ui.btn.style.bottom,
                left: ui.btn.style.left, right: ui.btn.style.right
            };

            GM_setValue('rbx_custom_settings', settings);
            render();

            btn.innerText = "SAVED!";
            setTimeout(() => btn.innerText = "APPLY", 2000);
        };
    }

    function buildLoader() {
        if (ui.loader) ui.loader.remove();

        ui.loader = document.createElement('div');
        ui.loader.id = 'rbx-drag-loader';
        Object.assign(ui.loader.style, {
            position: 'absolute', top: '50%', left: '50%',
            transform: 'translate(-50%, -50%)',
            width: '24px', height: '24px',
            display: 'none', pointerEvents: 'none'
        });

        ui.loader.innerHTML = `
            <svg width="24" height="24" viewBox="0 0 24 24" style="transform: rotate(-90deg);">
                <circle cx="12" cy="12" r="10" stroke="rgba(255,255,255,0.2)" stroke-width="3" fill="none"></circle>
                <circle id="rbx-progress-ring" cx="12" cy="12" r="10" stroke="#ffffff" stroke-width="3" fill="none"
                 stroke-dasharray="63" stroke-dashoffset="63" style="transition: stroke-dashoffset 0.05s linear;"></circle>
            </svg>
        `;

        ui.btn.appendChild(ui.loader);
    }

    function initDrag(el) {
        let dragging = false;
        let holding = false;
        let t1 = null;
        let t2 = null;
        let start = { x: 0, y: 0 };
        let offset = { l: 0, t: 0 };
        let time = 0;

        buildLoader();

        el.onmousedown = (e) => {
            if (e.button !== 0) return;

            const ring = document.getElementById('rbx-progress-ring');
            if (ring) {
                ring.style.transition = 'none';
                ring.style.strokeDashoffset = '63';
                void ring.offsetWidth;
                ring.style.transition = 'stroke-dashoffset 0.05s linear';
            }

            holding = true;
            start = { x: e.clientX, y: e.clientY };
            const rect = el.getBoundingClientRect();
            offset = { l: rect.left, t: rect.top };
            time = Date.now();

            t1 = setTimeout(() => {
                if (!holding) return;

                ui.loader.style.display = 'block';
                el.style.color = 'transparent';

                t2 = setInterval(() => {
                    if (!holding) {
                         clearInterval(t2);
                         return;
                    }
                    const diff = Date.now() - time;
                    const pct = Math.min(100, Math.max(0, ((diff - 200) / 800) * 100));

                    if (ring) {
                        const val = 63 - (63 * pct / 100);
                        ring.style.strokeDashoffset = val;
                    }

                    if (pct >= 100) {
                        clearInterval(t2);
                        dragging = true;
                        ui.panel.style.display = 'none';
                        el.style.transition = 'none';
                        el.style.cursor = 'move';
                        ui.loader.style.display = 'none';
                        el.style.color = '#00ffaa';
                        overlay(true);
                        const t = document.getElementById('rbx-drag-tip');
                        if(t) t.remove();
                    }
                }, 16);

            }, 200);
        };

        document.onmousemove = (e) => {
            if (!dragging) return;
            el.style.left = (offset.l + (e.clientX - start.x)) + 'px';
            el.style.top = (offset.t + (e.clientY - start.y)) + 'px';
            el.style.right = 'auto';
            el.style.bottom = 'auto';
        };

        document.onmouseup = () => {
            if (t1) clearTimeout(t1);
            if (t2) clearInterval(t2);

            if (ui.loader) ui.loader.style.display = 'none';
            ui.btn.style.color = '#00ffaa';

            if (dragging) {
                dragging = false;
                holding = false;
                overlay(false);
                el.style.transition = 'top 0.3s, left 0.3s, right 0.3s, bottom 0.3s';
                el.style.cursor = 'pointer';
                snap(el);
            }
            else if (holding) {
                holding = false;
                ui.panel.style.display = ui.panel.style.display === 'none' ? 'block' : 'none';
            }
        };
    }

    function overlay(active) {
        if (active) {
            ui.overlay = document.createElement('div');
            Object.assign(ui.overlay.style, {
                position: 'fixed', top: 0, left: 0, width: '100%', height: '100%',
                background: 'rgba(0, 0, 0, 0.7)',
                zIndex: '10000', pointerEvents: 'none'
            });

            const zones = [
                { top: '20px', left: '20px' },
                { top: '20px', right: '20px' },
                { bottom: '20px', left: '20px' },
                { bottom: '20px', right: '20px' }
            ];

            zones.forEach(pos => {
                const z = document.createElement('div');
                Object.assign(z.style, {
                    position: 'absolute', width: '120px', height: '40px',
                    border: '2px dashed rgba(255,255,255,0.5)',
                    borderRadius: '8px', boxSizing: 'border-box',
                    ...pos
                });
                ui.overlay.appendChild(z);
            });

            document.body.appendChild(ui.overlay);
        } else {
            if (ui.overlay) ui.overlay.remove();
        }
    }

    function snap(el) {
        const r = el.getBoundingClientRect();
        const w = window.innerWidth;
        const h = window.innerHeight;

        const d = [
            Math.hypot(r.left, r.top),
            Math.hypot(w - r.right, r.top),
            Math.hypot(r.left, h - r.bottom),
            Math.hypot(w - r.right, h - r.bottom)
        ];

        const m = Math.min(...d);
        let p = {};

        if (m === d[0]) p = { top: '20px', left: '20px', bottom: 'auto', right: 'auto' };
        else if (m === d[1]) p = { top: '20px', right: '20px', bottom: 'auto', left: 'auto' };
        else if (m === d[2]) p = { bottom: '20px', left: '20px', top: 'auto', right: 'auto' };
        else p = { bottom: '20px', right: '20px', top: 'auto', left: 'auto' };

        Object.assign(el.style, p);
        settings.btnPos = p;
        GM_setValue('rbx_custom_settings', settings);
    }

    function tooltip() {
        const t = document.createElement('div');
        t.id = 'rbx-drag-tip';
        t.innerText = 'Drag me!';
        Object.assign(t.style, {
            position: 'absolute', top: '-45px', left: '50%', transform: 'translateX(-50%)',
            background: 'white', color: 'black', padding: '8px 12px', borderRadius: '6px',
            fontSize: '14px', fontWeight: 'bold', pointerEvents: 'none', whiteSpace: 'nowrap',
            boxShadow: '0 2px 10px rgba(0,0,0,0.5)'
        });

        const a = document.createElement('div');
        Object.assign(a.style, {
            position: 'absolute', bottom: '-5px', left: '50%', marginLeft: '-5px',
            borderLeft: '5px solid transparent', borderRight: '5px solid transparent',
            borderTop: '5px solid white'
        });

        t.appendChild(a);
        ui.btn.appendChild(t);
        setTimeout(() => { if(t) t.remove(); }, 5000);
    }

    function render() {
        if (loopId) clearInterval(loopId);
        const old = document.getElementById('rbx-canvas');
        if (old) old.remove();

        switch (settings.preset) {
            case 'matrix': matrix(); break;
            case 'fireworks': fireworks(); break;
            case 'storm': storm(); break;
            case 'neural': neural(); break;
            case 'snow': snow(); break;
        }

        const fid = 'rbx-font-link';
        let fl = document.getElementById(fid);
        if (fl) fl.remove();

        let fcss = '';
        if (settings.fontName) {
            fl = document.createElement('link');
            fl.id = fid;
            fl.rel = 'stylesheet';
            fl.href = `https://fonts.googleapis.com/css2?family=${settings.fontName.replace(/ /g, '+')}&display=swap`;
            document.head.appendChild(fl);
            fcss = `* { font-family: '${settings.fontName}', sans-serif !important; }`;
        }

        const sid = 'rbx-injected-css';
        let st = document.getElementById(sid);
        if (!st) {
            st = document.createElement('style');
            st.id = sid;
            document.head.appendChild(st);
        }

        st.innerHTML = `
            ${fcss}
            body, .dark-theme, .light-theme, .container-main, #Container { background: transparent !important; background-image: none !important; }
            .content, .container-footer, .footer, .rbx-header, #wrap.wrap,
            .game-home-page-container, .section-content, .rbx-tab-content,
            .profile-header, .rbx-left-col, .rbx-right-col, .rbx-game-status,
            .chat-container, .chat-main, .dialog-container, .navbar-search {
                background-color: rgba(20, 20, 20, ${settings.transparency}) !important; border: none !important; box-shadow: none !important;
            }
            .text-footer-nav, .text-copyright, .text-link, h1, h2, h3, p, div { color: #fff !important; text-shadow: 1px 1px 2px rgba(0,0,0,0.8); }
            .rbx-header { backdrop-filter: blur(5px); background-color: rgba(0, 0, 0, 0.6) !important; }
            .ad-container, .gutter-ads, #Skyscraper-Adp-Right, #Skyscraper-Adp-Left { display: none !important; }
        `;
    }

    function canvas(c) {
        const el = document.createElement('canvas');
        el.id = 'rbx-canvas';
        Object.assign(el.style, { position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', zIndex: '-1', background: c });
        el.width = window.innerWidth;
        el.height = window.innerHeight;
        document.body.appendChild(el);
        return el;
    }

    function matrix() {
        const c = canvas('black');
        const ctx = c.getContext('2d');
        const set = 'アァカサタナハマヤャラワガザダバパイィキシチニヒミリBg0123456789'.split('');
        const arr = Array(Math.floor(c.width / 16)).fill(1);

        loopId = setInterval(() => {
            ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
            ctx.fillRect(0, 0, c.width, c.height);
            ctx.fillStyle = '#0F0';
            ctx.font = '16px monospace';

            arr.forEach((y, i) => {
                const t = set[Math.floor(Math.random() * set.length)];
                ctx.fillText(t, i * 16, y * 16);
                if (y * 16 > c.height && Math.random() > 0.975) arr[i] = 0;
                arr[i]++;
            });
        }, 33);
    }

    function fireworks() {
        const c = canvas('#050505');
        const ctx = c.getContext('2d');
        let f = [], p = [];

        loopId = setInterval(() => {
            ctx.globalCompositeOperation = 'source-over';
            ctx.fillStyle = 'rgba(0, 0, 0, 0.3)';
            ctx.fillRect(0, 0, c.width, c.height);
            ctx.globalCompositeOperation = 'lighter';

            if (Math.random() < 0.04) {
                f.push({ x: Math.random() * c.width, y: c.height, tx: Math.random() * c.width, ty: Math.random() * c.height / 2, h: Math.random() * 360 });
            }

            for (let i = f.length - 1; i >= 0; i--) {
                let r = f[i];
                r.x += (r.tx - r.x) / 15;
                r.y += (r.ty - r.y) / 15;
                ctx.beginPath(); ctx.arc(r.x, r.y, 3, 0, Math.PI * 2);
                ctx.fillStyle = `hsl(${r.h}, 100%, 50%)`; ctx.fill();
                if (Math.hypot(r.tx - r.x, r.ty - r.y) < 15) {
                    for(let j=0; j<40; j++) p.push({ x: r.x, y: r.y, vx: Math.cos(j*10)*Math.random()*6, vy: Math.sin(j*10)*Math.random()*6, h: r.h, a: 1 });
                    f.splice(i, 1);
                }
            }

            for (let i = p.length - 1; i >= 0; i--) {
                let pt = p[i];
                pt.x += pt.vx; pt.y += pt.vy; pt.vy += 0.08; pt.a -= 0.08;
                if (pt.a <= 0) p.splice(i, 1);
                else { ctx.beginPath(); ctx.arc(pt.x, pt.y, 2, 0, Math.PI * 2); ctx.fillStyle = `hsla(${pt.h}, 100%, 50%, ${pt.a})`; ctx.fill(); }
            }
        }, 25);
    }

    function storm() {
        const c = canvas('#050505');
        const ctx = c.getContext('2d');
        const r = Array(300).fill().map(() => ({ x: Math.random()*c.width, y: Math.random()*c.height, l: Math.random()*20+10, v: Math.random()*10+10 }));
        let fl = { on: false, op: 0, s: [] };

        loopId = setInterval(() => {
            if (fl.op > 0) {
                ctx.fillStyle = `rgba(20, 20, 30, ${fl.op * 0.3})`;
                ctx.fillRect(0,0,c.width, c.height);
                fl.op -= 0.05;
            } else {
                ctx.fillStyle = 'rgba(5, 5, 5, 0.4)';
                ctx.fillRect(0,0,c.width, c.height);
                if (Math.random() > 0.985) {
                    fl.on = true; fl.op = 1;
                    let sx = Math.random() * c.width, sy = 0;
                    fl.s = [{x:sx, y:sy}];
                    while(sy < c.height) { sx += (Math.random()-0.5)*50; sy += Math.random()*20+10; fl.s.push({x:sx, y:sy}); }
                } else fl.on = false;
            }

            if (fl.on || fl.op > 0.5) {
                ctx.beginPath(); ctx.strokeStyle = `rgba(255, 255, 255, ${fl.op})`; ctx.lineWidth = 2;
                ctx.shadowBlur = 15; ctx.shadowColor = "white";
                fl.s.forEach((pt, i) => i === 0 ? ctx.moveTo(pt.x, pt.y) : ctx.lineTo(pt.x, pt.y));
                ctx.stroke(); ctx.shadowBlur = 0;
            }

            ctx.strokeStyle = 'rgba(174, 194, 224, 0.5)'; ctx.lineWidth = 1; ctx.beginPath();
            r.forEach(d => {
                ctx.moveTo(d.x, d.y); ctx.lineTo(d.x, d.y + d.l);
                d.y += d.v;
                if (d.y > c.height) { d.y = -20; d.x = Math.random() * c.width; }
            });
            ctx.stroke();
        }, 30);
    }

    function neural() {
        const c = canvas('#111');
        const ctx = c.getContext('2d');
        const pt = Array(80).fill().map(() => ({ x: Math.random()*c.width, y: Math.random()*c.height, vx: (Math.random()-0.5)*2, vy: (Math.random()-0.5)*2 }));

        loopId = setInterval(() => {
            ctx.clearRect(0, 0, c.width, c.height);
            ctx.fillStyle = '#00ffaa'; ctx.strokeStyle = '#00ffaa';

            pt.forEach((p, i) => {
                p.x += p.vx; p.y += p.vy;
                if (p.x < 0 || p.x > c.width) p.vx *= -1;
                if (p.y < 0 || p.y > c.height) p.vy *= -1;
                ctx.beginPath(); ctx.arc(p.x, p.y, 3, 0, Math.PI*2); ctx.fill();

                for (let j = i + 1; j < pt.length; j++) {
                    let p2 = pt[j];
                    let d = Math.hypot(p.x - p2.x, p.y - p2.y);
                    if (d < 150) {
                        ctx.beginPath(); ctx.lineWidth = 1 - (d/150);
                        ctx.moveTo(p.x, p.y); ctx.lineTo(p2.x, p2.y); ctx.stroke();
                    }
                }
            });
        }, 30);
    }

    function snow() {
        const c = canvas('radial-gradient(ellipse at bottom, #1b2735 0%, #090a0f 100%)');
        const ctx = c.getContext('2d');
        const fl = Array(100).fill().map(() => ({ x: Math.random()*c.width, y: Math.random()*c.height, r: Math.random()*3+1, d: Math.random()*100 }));

        loopId = setInterval(() => {
            ctx.clearRect(0, 0, c.width, c.height);
            ctx.fillStyle = "white"; ctx.beginPath();
            fl.forEach(f => {
                ctx.moveTo(f.x, f.y); ctx.arc(f.x, f.y, f.r, 0, Math.PI*2, true);
                f.y += Math.cos(f.d) + 1 + f.r/2;
                f.x += Math.sin(f.d) * 2;
                if (f.x > c.width + 5 || f.x < -5 || f.y > c.height) { f.x = Math.random()*c.width; f.y = -10; }
            });
            ctx.fill();
        }, 33);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', start);
    } else {
        start();
    }

})();