SPNATI FULL CHEAT

cheat for spnati.net + config editor for online version

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         SPNATI FULL CHEAT
// @name:ru      SPNATI ПОЛНЫЙ ЧИТ
// @namespace    http://tampermonkey.net/
// @version      2026-04-18
// @description  cheat for spnati.net + config editor for online version
// @description:ru  чит для spnati.net + редактор confg-настроек для онлайн-версии
// @author       TOOM_TYM
// @match        https://*.spnati.net/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=spnati.net
// @grant        none
// @license      MIT

// ==/UserScript==




(function() {
    'use strict';
    // -- CONFIG EDITOR
    const fakeConfig = `
            <config>
                <debug>true</debug>
                <epilogues>true</epilogues>
                <epilogues-unlocked>true</epilogues-unlocked>
                <collectibles>true</collectibles>
                <collectibles-unlocked>true</collectibles-unlocked>

                <default-fill>default</default-fill>
                <custom-cards>true</custom-cards>
                <default-card-deck>default</default-card-deck>

                <alternate-costumes>true</alternate-costumes>
                <alternate-costume-sets>valentines</alternate-costume-sets>
                <alternate-costume-sets>april_fools</alternate-costume-sets>
                <alternate-costume-sets>easter</alternate-costume-sets>
                <alternate-costume-sets>summer</alternate-costume-sets>
                <alternate-costume-sets>halloween</alternate-costume-sets>
                <alternate-costume-sets>xmas</alternate-costume-sets>
                <alternate-costume-sets>all</alternate-costume-sets>


                <!-- <default-costume-set>summer</default-costume-set> че это -->

                <default-background>inventory</default-background>
                <resort>false</resort>
                <testing-max-age>31</testing-max-age>


                <include-status>testing</include-status>
                <include-status>offline</include-status>
                <include-status>incomplete</include-status>

                <commit>9a368f9e7d04ae3a1b866a84aa0171c76ad7f3e3</commit>
                <version-tag>v13.56.0-6-g9a368f9e7d</version-tag>
            </config>

        `;
    // -- CONFIG EDITOR






    // code of cheat
    const CONFIG = {
        title: "BY TOOM_TYM",
        elements: [
            { type: 'button', text: 'Globals,info', callback: () => Globals() },
            { type: 'button', text: 'ace-high straight', callback: () => ace() },
            {
                type: 'toggle',
                text: 'Chose Loser',
                id: 'loser_picker',
                default: false,
                callback: (active) => {
                    if (active) {
                        enableLoserPicker();
                    } else {
                        disableLoserPicker();
                    }
                }
            },
            {
                type: 'toggle',
                text: 'Card Peeking',
                id: 'always_reveal',
                default: false,
                callback: (active) => {
                    if (active) {
                        window.revealTimer = setInterval(() => {
                            const suitNames = ['spade', 'heart', 'diamo', 'clubs'];

                            for (let p = 1; p <= 4; p++) {
                                try {
                                    const player = players[p];
                                    if (!player || !player.hand || !player.hand.cards) continue;

                                    const container = document.getElementById(`opponent-card-area-${p}`);
                                    if (container) {
                                        container.classList.add('shown');
                                        container.style.width = "auto";
                                        container.style.whiteSpace = "nowrap";
                                    }

                                    player.hand.cards.forEach((card, i) => {
                                        const img = document.getElementById(`player-${p}-card-${i + 1}`);
                                        if (img && card) {
                                            const suitName = suitNames[card.suit];
                                            const rank = card.rank;
                                            const newSrc = `img/cards/default/${suitName}${rank}.svg`;
                                            if (img.getAttribute('src') !== newSrc) {
                                                img.src = newSrc;
                                            }
                                            img.alt = `${suitName}${rank}`
                                            img.style.margin = "0 1px";
                                            img.style.position = "static";
                                            img.style.width = "auto";
                                            img.style.display = "inline-block";
                                        }
                                    });
                                } catch (e) {
                                }
                            }
                        }, 500);
                    } else {
                        if (window.revealTimer) {
                            clearInterval(window.revealTimer);
                            window.revealTimer = null;
                        }
                    }
                }
            },

        ]
    };

    const style = document.createElement('style');
    style.innerHTML = `
        #gui-fab { position: fixed; top: 20px; right: 20px; width: 45px; height: 45px; background: #ff4b2b; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 20px; cursor: pointer; z-index: 1000000; box-shadow: 0 4px 10px rgba(0,0,0,0.3); user-select: none; transition: 0.3s; }
        #gui-m {
            position: fixed;
            top: 75px; /* Сразу под кнопкой */
            right: -300px; /* Спрятано за краем */
            width: 220px;
            background: rgba(26, 26, 26, 0.95);
            border-radius: 10px;
            padding: 15px;
            display: flex;
            flex-direction: column;
            z-index: 1000002;
            color: #fff;
            font-family: sans-serif;
            box-shadow: -5px 5px 20px rgba(0,0,0,0.4);
            transition: right 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            border: 1px solid #333;
        }
        #gui-m.active { right: 20px; }
        .g-title { text-align: center; font-size: 14px; font-weight: bold; margin-bottom: 10px; border-bottom: 1px solid #444; padding-bottom: 8px; color: #ff4b2b; }
        .g-btn { background: #333; border: none; color: #fff; padding: 10px; margin: 4px 0; border-radius: 5px; cursor: pointer; transition: 0.2s; width: 100%; font-size: 13px; }
        .g-btn:hover { background: #444; }
        .g-btn:active { background: #555; }
        .g-row { display: flex; justify-content: space-between; align-items: center; background: #222; padding: 8px; margin: 4px 0; border-radius: 5px; font-size: 13px; }
        .g-tog { position: relative; width: 34px; height: 18px; -webkit-appearance: none; background: #444; border-radius: 10px; outline: none; transition: 0.3s; cursor: pointer; }
        .g-tog:checked { background: #4caf50; }
        .g-tog:before { content: ''; position: absolute; width: 14px; height: 14px; border-radius: 50%; top: 2px; left: 2px; background: #fff; transition: 0.3s; }
        .g-tog:checked:before { left: 18px; }
        .g-close { background: #444; color: #bbb; margin-top: 8px; font-size: 11px; padding: 5px; }
    `;
    document.head.appendChild(style);

    const fab = document.createElement('div');
    fab.id = 'gui-fab';
    fab.innerHTML = '😈';

    const menu = document.createElement('div');
    menu.id = 'gui-m';

    let html = `<div class="g-title">${CONFIG.title}</div>`;
    CONFIG.elements.forEach((el, i) => {
        if (el.type === 'button') html += `<button class="g-btn" id="g-el-${i}">${el.text}</button>`;
        else if (el.type === 'toggle') html += `<div class="g-row"><span>${el.text}</span><input type="checkbox" class="g-tog" id="g-el-${i}" ${el.default ? 'checked' : ''}></div>`;
    });
    html += `<button class="g-btn g-close" id="g-close">HIDE</button>`;
    menu.innerHTML = html;

    document.body.appendChild(fab);
    document.body.appendChild(menu);

    function toggle() {
        menu.classList.toggle('active');
    }

    fab.onclick = toggle;
    document.getElementById('g-close').onclick = toggle;

    CONFIG.elements.forEach((el, i) => {
        const dom = document.getElementById(`g-el-${i}`);
        if (el.type === 'button') dom.onclick = () => el.callback();
        else dom.onchange = (e) => el.callback(e.target.checked);
    });

    function updateVisuals() {
        try {
            const cardElements = document.querySelectorAll('#player-game-card-area input.large-card-image');
            const suitNames = ['spade', 'heart', 'diamo', 'clubs'];
            cardElements.forEach((img, index) => {
                const card = players[0].hand.cards[index];
                if (card) {
                    img.src = `img/cards/default/${suitNames[card.suit]}${card.rank}.svg`;
                }
            });
        } catch(e) {}
    }


    function Globals(){
        alert(`
        -- unlocked everything
        -- removed wearing limit
        `)
    }
    function ace(){
        players[0].hand.cards = [14, 13, 12, 11, 10].map(function(n) {
            let randomSuit = Math.floor(Math.random() * 4);
            return new Card(randomSuit, n);
        });

        try {
            const cardElements = document.querySelectorAll('#player-game-card-area input.large-card-image');
            const hand = players[0].hand.cards;
            const suitNames = ['spade', 'heart', 'diamo', 'clubs'];

            if (cardElements.length === 0) {
                throw new Error("err");
            }

            cardElements.forEach((img, index) => {
                const card = hand[index];
                if (card) {
                    let suitName = suitNames[card.suit];
                    let rank = card.rank;
                    img.src = `img/cards/default/${suitName}${rank}.svg`;
                    if (typeof card.toString === 'function') {
                        img.alt = card.toString();
                    }
                }
            });
        } catch (guiError) {
            console.warn("visual error");
        }
    }
    function enableLoserPicker() {
        const labels = document.querySelectorAll('.bordered.name-label');

        labels.forEach((label, index) => {
            label.style.cursor = 'crosshair';
            label.onmouseenter = () => {
                label.style.outline = '3px solid red';
                label.style.backgroundColor = 'rgba(255, 0, 0, 0.2)';
            };

            label.onmouseleave = () => {
                label.style.outline = 'none';
                label.style.backgroundColor = '';
            };


            label.onclick = () => {
                let playerIndex = index - 4;
                if (playerIndex >= 0 && players[playerIndex]) {
                    const target = players[playerIndex];
                    players[playerIndex].hand.strength = -3
                    players[playerIndex].hand.cards = [7, 5, 4, 3, 2].map(function(n) {
                        let randomSuit = Math.floor(Math.random() * 4);
                        return new Card(randomSuit, n);
                    });
                }
            };
        });


    }

    function disableLoserPicker() {
        const labels = document.querySelectorAll('.bordered.name-label');
        labels.forEach(label => {
            label.style.outline = 'none';
            label.style.backgroundColor = '';
            label.style.cursor = 'default';
            label.onclick = null;
            label.onmouseenter = null;
            label.onmouseleave = null;
        });
    }
    const originalFetch = window.fetch;
    window.fetch = async function(...args) {
        const url = args[0];
        if (typeof url === 'string' && url.includes("config.xml")) {

            return new Response(fakeConfig, {
                status: 200,
                statusText: 'OK',
                headers: { 'Content-Type': 'text/xml' }
            });
        }
        return originalFetch.apply(this, args);
    };


    if (typeof window.validateTitleScreen === 'function') {
        window.validateTitleScreen = function() {
            // THIS IS MODIFED "validateTitleScreen" FUNCTION
            /* determine the player's name */
            var playerName = '';

            if ($nameField.val() != "") {
                playerName = $nameField.val();
            } else if (humanPlayer.gender == "male") {
                playerName = "Mister";
            } else if (humanPlayer.gender == "female") {
                playerName = 'Miss';
            }

            humanPlayer.first = playerName;
            humanPlayer.label = playerName;

            $gameLabels[HUMAN_PLAYER].text(humanPlayer.label);

            /* count clothing */
            var clothingItems = save.selectedClothing();
            console.log(clothingItems.length);


            /* dress the player */
            wearClothing();
            setPlayerTags();

            save.savePlayer();
            console.log(players[0]);

            setLocalDayOrNight();
            updateAllBehaviours(null, null, SELECTED);
            updateSelectionVisuals();

            Sentry.setTag("screen", "select-main");
            screenTransition($titleScreen, $selectScreen);

            updateAnnouncementDropdown();
            showAnnouncements();

            if (curResortEvent && !curResortEvent.resort.checkCharacterThreshold()) {
                curResortEvent.resort.setFlag(false);
            }

        };
    }
    const pinButtonToTop = () => {
        const modal = document.querySelector('.bordered.modal-dialog-surface');
        const footer = document.querySelector('.modal-footer');
        const selectBtn = document.getElementById('stripping-modal-button');
        if (modal && footer && selectBtn) {
            Object.assign(footer.style, {
                position: 'absolute',
                top: '40px',
                left: '0',
                right: '0',
                zIndex: '9999',
                display: 'flex',
                justifyContent: 'center',
                background: 'transparent',
                border: 'none',
                padding: '0',
                pointerEvents: 'none'
            });
            Object.assign(selectBtn.style, {
                pointerEvents: 'auto',
                boxShadow: '0 0 15px rgba(0,0,0,0.8)', // this just for make strip button avalible when you wearing more than 8 clothes
                width: '80%',
                maxWidth: '300px'
            });
            const body = document.querySelector('.modal-body');
            if (body) {
                body.style.paddingTop = '60px';
            }
        }
    };
    const observer = new MutationObserver(() => pinButtonToTop());
    observer.observe(document.body, { childList: true, subtree: true });
    pinButtonToTop();
})();