Developer-like Shop Script + Antibush update!

Read in game instructions! + Antibush update!

Dovrai installare un'estensione come Tampermonkey, Greasemonkey o Violentmonkey per installare questo script.

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

Dovrai installare un'estensione come Tampermonkey o Violentmonkey per installare questo script.

Dovrai installare un'estensione come Tampermonkey o Userscripts per installare questo script.

Dovrai installare un'estensione come ad esempio Tampermonkey per installare questo script.

Dovrai installare un gestore di script utente per installare questo script.

(Ho già un gestore di script utente, lasciamelo installare!)

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione come ad esempio Stylus per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

Dovrai installare un'estensione per la gestione degli stili utente per installare questo stile.

(Ho già un gestore di stile utente, lasciamelo installare!)

// ==UserScript==
// @name         Developer-like Shop Script + Antibush update!
// @namespace    http://tampermonkey.net/
// @version      4.0
// @description  Read in game instructions! + Antibush update!
// @author       StarryGirl
// @match        *://*.modd.io/play/*
// @match        *://*.us.braains.io/*
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const originalTilesheet = "1763501136378_tilesheet_complete.png";
    const customTilesheet = "https://cache.modd.io/asset/spriteImage/1772476785111_image-1.png.png";

    const originalSrcDescriptor = Object.getOwnPropertyDescriptor(Image.prototype, 'src');

    Object.defineProperty(Image.prototype, 'src', {
        set: function(url) {
            if (url && url.includes(originalTilesheet)) {
                url = customTilesheet;
            }
            originalSrcDescriptor.set.call(this, url);
        },
        get: function() {
            return originalSrcDescriptor.get.call(this);
        },
        configurable: true,
        enumerable: true
    });

    const initShopScript = () => {
        let bKeyDisabled = false;
        let safetyPromptShown = false;

        const fontLink = document.createElement('link');
        fontLink.href = 'https://fonts.googleapis.com/css2?family=Lato:wght@400;700&display=swap';
        fontLink.rel = 'stylesheet';
        document.head.appendChild(fontLink);

        const shopItems = [
            { key: 'r', id: 'g2XpxVVdEp', name: 'Tonic Z-Potion', cost: 500 },
            { key: '2', id: '9jYPyEYzU4', name: 'Dynamite', cost: 750 },
            { key: '3', id: 'Z6cZdmeRd8', name: 'Grenade (x4)', cost: 750 },
            { key: '4', id: '7PnVjGFlfv', name: 'Stacked Dynamite', cost: 1000 },
            { key: '5', id: 'NUQnpXAIsR', name: 'Glock (x100)', cost: 1000 },
            { key: '6', id: 'QZadOkit0E', name: 'Crossbow (x75)', cost: 1000 },
            { key: '7', id: 'oI7IYepEHl', name: 'Spear', cost: 1000 },
            { key: '8', id: 'nl7XMFfFN8', name: 'Slingshot (x100)', cost: 2000 },
            { key: '9', id: '9w6WpNtbMG', name: 'Mystic Crowbar', cost: 3000 },
            { key: '0', id: 'oQOSkx7Oe6', name: 'Broom', cost: 5000, confirm: true },
            { key: '-', id: 'OX7kaD3N28', name: 'Rare Spear', cost: 7500, confirm: true },
            { key: '=', id: 'PyrFdp103w', name: 'Magic Cloak', cost: 10000, confirm: true }
        ];

        const style = document.createElement('style');
        style.innerHTML = `
            @keyframes pulsePop {
                0% { transform: scale(1); }
                35% { transform: scale(1.3); color: #4ade80; }
                70% { transform: scale(0.95); }
                100% { transform: scale(1); }
            }
            @keyframes springIn {
                0% { transform: translateX(-50%) scale(0.5); opacity: 0; }
                100% { transform: translateX(-50%) scale(1); opacity: 1; }
            }
            @keyframes springOut {
                0% { transform: translateX(-50%) scale(1); opacity: 1; }
                100% { transform: translateX(-50%) scale(0.5); opacity: 0; }
            }
            .pulse-active {
                animation: pulsePop 0.29s cubic-bezier(0.34, 1.56, 0.64, 1);
                display: inline-block;
                transform-origin: center;
            }
            .ui-base {
                position: fixed; left: 50%; transform: translateX(-50%);
                background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
                border-radius: 6px; font-family: 'Lato', sans-serif; z-index: 1000000;
                box-shadow: 0 10px 25px rgba(0,0,0,0.15);
                animation: springIn 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
            }
            .ui-exit { animation: springOut 0.2s ease-in forwards !important; }
            .error-popup { top: 25%; padding: 8px 16px; color: #b91c1c; font-weight: 700; font-size: 15px; display: flex; align-items: center; gap: 6px; pointer-events: none; }
            .confirm-btn {
                cursor: pointer; border: none; padding: 6px 14px; font-family: 'Lato', sans-serif; font-weight: 700; font-size: 13px;
                display: flex; align-items: center; gap: 6px; border-radius: 4px; color: white;
                transition: transform 0.2s cubic-bezier(0.2, 0, 0, 1), filter 0.2s;
            }
            .confirm-btn:hover { transform: scale(1.07); filter: brightness(1.05); }
            .confirm-btn:active { transform: scale(0.95); }
        `;
        document.head.appendChild(style);

        function triggerExit(element, callback) {
            element.classList.add('ui-exit');
            setTimeout(() => {
                element.remove();
                if(callback) callback();
            }, 180);
        }

        function showError() {
            if (document.querySelector('.error-popup')) return;
            const err = document.createElement('div');
            err.className = 'ui-base error-popup';
            err.innerHTML = `<span>⚠️</span> Juke-shop not active yet!`;
            document.body.appendChild(err);
            setTimeout(() => triggerExit(err), 1500);
        }

        function createSafetyLockUI() {
            if (document.getElementById('safety-overlay')) return;
            const overlay = document.createElement('div');
            overlay.id = 'safety-overlay';
            overlay.className = 'ui-base';
            Object.assign(overlay.style, {
                top: '20%', padding: '20px', pointerEvents: 'auto',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '12px', width: '450px'
            });

            overlay.innerHTML = `
                <div style="font-weight: 700; font-size: 18px; color: #1e293b; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; width: 100%; text-align: center;">
                    ⚠️ Juke-only shop loaded
                </div>
                <div style="font-size: 14px; color: #1e293b; text-align: left; width: 100%; line-height: 1.6;">
                    <div style="margin-bottom: 8px;">✅ Please confirm you have over 5,000 score.</div>
                    <div style="margin-bottom: 8px;">⚠️ The B key will be disabled to prevent opening any other shops!</div>
                    <div style="color: #64748b; font-size: 13px; font-style: italic;">
                        ⚠️ Confirming will disable B key, declining will keep your B key but there will be a risk of accidentally opening regular shop!
                    </div>
                </div>
                <div style="display: flex; gap: 15px; margin-top: 10px;">
                    <button id="safety-confirm" class="confirm-btn" style="background: #10b981; padding: 10px 25px;">Confirm</button>
                    <button id="safety-decline" class="confirm-btn" style="background: #ef4444; padding: 10px 25px;">Decline</button>
                </div>
            `;

            document.body.appendChild(overlay);
            document.getElementById('safety-confirm').onclick = () => { bKeyDisabled = true; triggerExit(overlay); };
            document.getElementById('safety-decline').onclick = () => { bKeyDisabled = false; triggerExit(overlay); };
        }

        function createConfirmBox(itemName, onConfirm) {
            if (document.getElementById('confirm-overlay')) return;
            const overlay = document.createElement('div');
            overlay.id = 'confirm-overlay';
            overlay.className = 'ui-base';
            Object.assign(overlay.style, {
                top: '15%', padding: '12px', pointerEvents: 'auto',
                display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px', width: '300px'
            });

            overlay.innerHTML = `
                <div style="font-weight: 700; font-size: 15px; color: #1e293b; padding: 6px;">💰 Expensive item! Confirm purchase?</div>
                <div style="font-size: 14px; color: #475569;">Item: <b style="color:#059669">${itemName}</b></div>
                <div style="display: flex; gap: 10px; margin-top: 5px;">
                    <button id="btn-confirm" class="confirm-btn" style="background: #10b981;">Confirm</button>
                    <button id="btn-cancel" class="confirm-btn" style="background: #ef4444;">Don't confirm</button>
                </div>
            `;

            document.body.appendChild(overlay);
            document.getElementById('btn-confirm').onclick = () => triggerExit(overlay, onConfirm);
            document.getElementById('btn-cancel').onclick = () => triggerExit(overlay);
        }

        function refreshUI() {
            const wrapper = document.getElementById('play-game-button-wrapper');
            const playBtn = document.getElementById('play-game-button');
            let anyActive = false;

            if (wrapper && playBtn) {
                if (!document.getElementById('script-guide-overlay')) wrapper.prepend(guideBox);
                if (playBtn.parentElement !== guideBox) guideBox.appendChild(playBtn);
            }

            shopItems.forEach(item => {
                const shopAction = document.getElementById(item.id);
                const uiElement = document.getElementById(`ui-item-${item.id}`);
                if (uiElement) {
                    if (shopAction) { uiElement.style.opacity = '1'; anyActive = true; }
                    else { uiElement.style.opacity = '0.35'; }
                }
            });

            if (anyActive && !safetyPromptShown) {
                safetyPromptShown = true;
                createSafetyLockUI();
            } else if (!anyActive) {
                safetyPromptShown = false;
            }

            statusHeader.innerText = anyActive ? "Juke-only shop loaded, have fun!" : "Waiting for Juke-only shop!";
            statusHeader.style.color = anyActive ? "#4ade80" : "#ffffff";
            statusHeader.style.opacity = anyActive ? "1" : "0.35";
        }

        const guideBox = document.createElement('div');
        guideBox.id = 'script-guide-overlay';
        Object.assign(guideBox.style, {
            background: 'rgba(255, 255, 255, 0.8)', backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)',
            color: '#1e293b', padding: '15px', fontFamily: '"Lato", sans-serif', borderRadius: '8px',
            marginBottom: '10px', display: 'flex', flexDirection: 'column', alignItems: 'center',
            width: '420px', zIndex: '9999', border: '1px solid rgba(255, 255, 255, 0.4)',
            boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)'
        });

        guideBox.innerHTML = `
            <div style="width: 100%;">
                <h2 style="margin:4px 0 10px 0; color:#059669; font-size:20px; font-weight:700; text-align:center;">Script usage guide:</h2>
                <ul style="font-size:14px; margin:0; padding-left:25px; color:#1e293b; line-height:1.7; font-weight:400;">
                    <li>Wait for a <b> Juke-only </b> round to spawn</li>
                    <li>Open <b>Juke-Only</b> wizard shop. <b>⚠️ MAKE SURE you have enough score</b>!</li>
                    <li><b> B </b> key will be disabled if confirmed to protect script state.</li>
                    <li>Pills cannot be bought; ask around or bot them in.</li>
                    <li>Don't abuse too hard, and have fun! 😊👌</li> <br>
                    <i> by StarryGirl ;)</i>
                </ul>
            </div>
        `;

        const bottomContainer = document.createElement('div');
        Object.assign(bottomContainer.style, { position: 'fixed', bottom: '20px', left: '50%', transform: 'translateX(-50%)', display: 'flex', flexDirection: 'column', alignItems: 'center', pointerEvents: 'none', zIndex: '999999' });

        const statusHeader = document.createElement('div');
        statusHeader.id = 'shop-status-text';
        Object.assign(statusHeader.style, { color: '#ffffff', fontFamily: '"Lato", sans-serif', fontSize: '18px', fontWeight: '700', marginBottom: '10px', textShadow: '2px 2px 4px rgba(0,0,0,0.8)', transition: 'all 0.3s ease', opacity: '0.35' });
        statusHeader.innerText = "Waiting for Juke-only shop!";

        const bottomUI = document.createElement('div');
        Object.assign(bottomUI.style, { backgroundColor: 'transparent', color: '#ffffff', fontFamily: '"Lato", sans-serif', fontSize: '16.25px', display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: '12px 25px', textShadow: '1px 1px 3px rgba(0,0,0,0.9)' });

        shopItems.forEach(item => {
            const itemRow = document.createElement('div');
            itemRow.id = `ui-item-${item.id}`;
            itemRow.style.transition = 'opacity 0.3s ease';
            itemRow.style.opacity = '0.35';
            itemRow.innerHTML = `<strong style="color: #4ade80;">[${item.key.toUpperCase()}]</strong> <span>${item.name}</span>`;
            bottomUI.appendChild(itemRow);
        });

        bottomContainer.appendChild(statusHeader);
        bottomContainer.appendChild(bottomUI);
        document.body.appendChild(bottomContainer);

        setInterval(refreshUI, 1000);

        document.addEventListener('keydown', (event) => {
            if (['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName) || document.activeElement.isContentEditable) return;
            const key = event.key.toLowerCase();

            if (key === 'b' && bKeyDisabled) {
                event.preventDefault();
                event.stopImmediatePropagation();
                return;
            }

            const item = shopItems.find(i => i.key === key);
            if (item) {
                const uiElement = document.getElementById(`ui-item-${item.id}`);
                if (uiElement) {
                    uiElement.classList.remove('pulse-active');
                    void uiElement.offsetWidth;
                    uiElement.classList.add('pulse-active');
                }
                const btn = document.getElementById(item.id);
                if (item.confirm) {
                    createConfirmBox(item.name, () => { if (btn) btn.click(); else showError(); });
                } else {
                    if (btn) btn.click(); else showError();
                }
            }
        }, true);
    };

    if (document.readyState === "loading") {
        document.addEventListener("DOMContentLoaded", initShopScript);
    } else {
        initShopScript();
    }

})();