Developer-like Shop Script + Antibush update!

Read in game instructions! + Antibush update!

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==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();
    }

})();