Bonk.io Skin Sclee

Better Skin Editor

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Bonk.io Skin Sclee
// @namespace    http://tampermonkey.net/
// @version      2.0
// @description  Better Skin Editor
// @author       Silly One
// @match        https://*.bonk.io/*
// @match        https://*.bonkisback.io/*
// @run-at       document-start
// @grant        none
// @license      MIT
// ==/UserScript==

const injectorName = "Skin Sclee";

function injector(src) {
    const style = document.createElement('style');
    style.type = 'text/css';
    style.innerHTML = `
        #skineditor_reset, #skineditor_undo, #skineditor_redo,
        #skineditor_move, #skineditor_rotate,
        #skineditor_scale, #skineditor_flipX, #skineditor_flipY,
        #skineditor_invertcolors,
        #skineditor_loadbutton, #skineditor_randombutton {
            position: absolute;
            width: 25px;
            height: 25px;
            line-height: 30px;
        }

        #skineditor_reset { top: 45px; left: 15px; }
        #skineditor_undo { top: 45px; left: 45px; }
        #skineditor_redo { top: 45px; left: 75px; }
        #skineditor_move { top: 75px; right: 15px; }
        #skineditor_rotate { top: 105px; right: 15px; }
        #skineditor_inputrotate { position: absolute; top: 105px; left: -33px; width: 42px; height: 25px; }
        #skineditor_scale { top: 135px; right: 15px; }
        #skineditor_inputscale { position: absolute; top: 135px; left: -33px; width: 42px; height: 25px; }
        #skineditor_flipX { top: 165px; right: 15px; }
        #skineditor_flipY { top: 195px; right: 15px; }
        #skineditor_invertcolors { top: 255px; left: 15px; }
        #skineditor_loadbutton { bottom: -30px; right: 30px; width: 100px; height: 30px; }
        #skineditor_inputload { position: absolute; bottom: -60px; right: 30px; width: 100px; height: 30px; }
        #skineditor_randombutton { bottom: -90px; right: 30px; width: 100px; height: 30px; }
        #skineditor_checkbox { bottom: -90px; right: 0px; width: 20px; height: 20px; }
    `;
    document.head.appendChild(style);

    let newSrc = src;

    const GetSkinOnEdit = /O7P\[6]\[j1y\[1]\[642]]\(t\$e\[61]\[j1y\[1]\[1014]]\[O7P\[2]]\);/;
    newSrc = newSrc.replace(GetSkinOnEdit, `
    O7P[6][j1y[1][642]](t$e[61][j1y[1][1014]][O7P[2]]);
    t$e[61]["avatar"] = t$e[61][j1y[1][1014]][O7P[2]];
    `);
    const EditSkin = /u6B\(k7V\.w65\(2781\),s*N7I\[1]\)\;\};/;
    newSrc = newSrc.replace(EditSkin, `
    inputload.value = JSON.stringify(N7I[1]);
    u6B(k7V.w65(2781), N7I[1]);
    };

    let skineditor_previewbox_skincontainer = document.getElementById("skineditor_previewbox_skincontainer");

    let resetButton = document.createElement("div");
    resetButton.id = "skineditor_reset";
    resetButton.className = "brownButton brownButton_classic buttonShadow";
    resetButton.textContent = "⭮";
    document.getElementById("skineditor_previewbox").appendChild(resetButton);

    let undoButton = document.createElement("div");
    undoButton.id = "skineditor_undo";
    undoButton.className = "brownButton brownButton_classic buttonShadow";
    undoButton.textContent = "⤺";
    document.getElementById("skineditor_previewbox").appendChild(undoButton);

    let redoButton = document.createElement("div");
    redoButton.id = "skineditor_redo";
    redoButton.className = "brownButton brownButton_classic buttonShadow";
    redoButton.textContent = "⤻";
    document.getElementById("skineditor_previewbox").appendChild(redoButton);

    let buttonMove = document.createElement("div");
    buttonMove.id = "skineditor_move";
    buttonMove.className = "brownButton brownButton_classic buttonShadow";
    buttonMove.textContent = "↔";
    document.getElementById("skineditor_previewbox").appendChild(buttonMove);

    let buttonRotate = document.createElement("div");
    buttonRotate.id = "skineditor_rotate";
    buttonRotate.className = "brownButton brownButton_classic buttonShadow";
    buttonRotate.textContent = "⟳";
    document.getElementById("skineditor_previewbox").appendChild(buttonRotate);

    let rotateInputField = document.createElement("input");
    rotateInputField.id = "skineditor_inputrotate";
    rotateInputField.type = "text";
    rotateInputField.placeholder = "Angle";
    document.getElementById("skineditor_propertiesbox").appendChild(rotateInputField);

    let buttonScale = document.createElement("div");
    buttonScale.id = "skineditor_scale";
    buttonScale.className = "brownButton brownButton_classic buttonShadow";
    buttonScale.textContent = "⤢";
    document.getElementById("skineditor_previewbox").appendChild(buttonScale);

    let scaleInputField = document.createElement("input");
    scaleInputField.id = "skineditor_inputscale";
    scaleInputField.type = "text";
    scaleInputField.placeholder = "Scale";
    document.getElementById("skineditor_propertiesbox").appendChild(scaleInputField);

    let flipXButton = document.createElement("div");
    flipXButton.id = "skineditor_flipX";
    flipXButton.className = "brownButton brownButton_classic buttonShadow";
    flipXButton.textContent = "⭾";
    document.getElementById("skineditor_previewbox").appendChild(flipXButton);

    let flipYButton = document.createElement("div");
    flipYButton.id = "skineditor_flipY";
    flipYButton.className = "brownButton brownButton_classic buttonShadow";
    flipYButton.textContent = "⭿";
    document.getElementById("skineditor_previewbox").appendChild(flipYButton);

    let invertColors = document.createElement("div");
    invertColors.id = "skineditor_invertcolors";
    invertColors.className = "brownButton brownButton_classic buttonShadow";
    invertColors.textContent = "☯";
    document.getElementById("skineditor_previewbox").appendChild(invertColors);

    let butload = document.createElement("div");
    butload.id = "skineditor_loadbutton";
    butload.className = "brownButton brownButton_classic buttonShadow";
    butload.textContent = "Load";
    t$e[61].setButtonSounds([butload]);
    document.getElementById("skineditor_previewbox").appendChild(butload);

    let inputload = document.createElement("input");
    inputload.id = "skineditor_inputload";
    inputload.type = "text";
    document.getElementById("skineditor_previewbox").appendChild(inputload);
    inputload.value = '{"layers":[],"bc":0}';

    let butrandom = document.createElement("div");
    butrandom.id = "skineditor_randombutton";
    butrandom.className = "brownButton brownButton_classic buttonShadow";
    butrandom.textContent = "Random";
    t$e[61].setButtonSounds([butrandom]);
    document.getElementById("skineditor_previewbox").appendChild(butrandom);

    let avatarbefore;

    function updateAvatar() {
        let previewUpdater = new C_();
        previewUpdater.completeRedraw(N7I[1]);
    }

    function initializeAvatar() {
        let avatar = new t$e[80]();
        avatar.fromObject(N7I[1]);
        N7I[1] = avatar;
        updateAvatar();
        saveState();
    }

    document.getElementById('skinmanager_edit').addEventListener('click', function() {
    let avatar = new t$e[80]();
    avatar.fromObject(t$e[61]["allAvatars"][t$e[61]["activeAvatarNumber"]]);
    inputload.value = JSON.stringify(t$e[61]["allAvatars"][t$e[61]["activeAvatarNumber"]]);
    avatarbefore = avatar;
    setTimeout(function() {
        initializeAvatar();
        }, 300);
    });

    let history = [];
    let historyIndex = -1;

    function saveState() {
        history = history.slice(0, historyIndex + 1);
        history.push(JSON.stringify(N7I[1].layers));
        historyIndex++;
    }

    resetButton.onclick = function() {
        N7I[1] = avatarbefore;
        initializeAvatar();
    };

    undoButton.onclick = function() {
        undo();
    };

    function undo() {
        if (historyIndex > 0) {
            historyIndex--;
            N7I[1].layers = JSON.parse(history[historyIndex]);
            updateAvatar();
        }
    }

    redoButton.onclick = function() {
        redo();
    };

    function redo() {
        if (historyIndex < history.length - 1) {
            historyIndex++;
            N7I[1].layers = JSON.parse(history[historyIndex]);
            updateAvatar();
        }
    }

    let initialDistance, initialMousePos, initialLayerData = [];
    let activeButton = null;

    function debounce(func, wait) {
        let timeout;
        return function() {
            clearTimeout(timeout);
            timeout = setTimeout(func, wait);
        };
    }

    const debounceUpdate = debounce(() => S_z(), 300);

    function onMouseUp() {
        document.removeEventListener('mousemove', onMouseMove);
        document.removeEventListener('mouseup', onMouseUp);
        activeButton = null;
        debounceUpdate();
    }

    function onMouseMove(e) {
        let layers = N7I[1].layers;
        if (activeButton === 'scale') {
            let containerRect = skineditor_previewbox_skincontainer.getBoundingClientRect();
            let cursorDistance = Math.sqrt(Math.pow(e.clientX - (containerRect.left + containerRect.width / 2), 2) + Math.pow(e.clientY - (containerRect.top + containerRect.height / 2), 2));
            let scaleChange = cursorDistance / initialDistance;
            layers.forEach((layer, index) => {
                layer.scale = initialLayerData[index].scale * scaleChange;
                layer.x = initialLayerData[index].x * scaleChange;
                layer.y = initialLayerData[index].y * scaleChange;
            });
        }
        if (activeButton === 'move') {
            let deltaX = e.clientX - initialMousePos.x;
            let deltaY = e.clientY - initialMousePos.y;
            layers.forEach((layer, index) => {
                layer.x = initialLayerData[index].x + deltaX * 0.1;
                layer.y = initialLayerData[index].y + deltaY * 0.1;
            });
        }
        if (activeButton === 'rotate') {
            let containerRect = skineditor_previewbox_skincontainer.getBoundingClientRect();
            let centerX = containerRect.left + containerRect.width / 2;
            let centerY = containerRect.top + containerRect.height / 2;
            let angleChange = Math.atan2(e.clientY - centerY, e.clientX - centerX) * (180 / Math.PI);
            layers.forEach((layer, index) => {
                let initialAngle = initialLayerData[index].angle;
                layer.angle = initialAngle + angleChange;

                let initialX = initialLayerData[index].x;
                let initialY = initialLayerData[index].y;
                let radius = Math.sqrt(Math.pow(initialX, 2) + Math.pow(initialY, 2));
                let initialAngleRadians = Math.atan2(initialY, initialX);
                let newAngleRadians = initialAngleRadians + (angleChange * Math.PI / 180);
                layer.x = radius * Math.cos(newAngleRadians);
                layer.y = radius * Math.sin(newAngleRadians);
            });
        }
        updateAvatar();
    }

    buttonMove.addEventListener('mousedown', (e) => {
        activeButton = 'move';
        initialMousePos = { x: e.clientX, y: e.clientY };
        initialLayerData = N7I[1].layers.map(layer => ({
            x: layer.x,
            y: layer.y,
            scale: layer.scale,
            angle: layer.angle
        }));
        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
        saveState();
    });

    buttonRotate.onclick = function() {
        let rotateAngle = parseFloat(rotateInputField.value) || 22.5;
        let layers = N7I[1].layers;

        let containerRect = skineditor_previewbox_skincontainer.getBoundingClientRect();
        let centerX = containerRect.left + containerRect.width / 2;
        let centerY = containerRect.top + containerRect.height / 2;

        layers.forEach((layer, index) => {
            layer.angle += rotateAngle;
            let initialX = layer.x;
            let initialY = layer.y;
            let radius = Math.sqrt(Math.pow(initialX, 2) + Math.pow(initialY, 2));
            let initialAngleRadians = Math.atan2(initialY, initialX);
            let newAngleRadians = initialAngleRadians + (rotateAngle * Math.PI / 180);
            layer.x = radius * Math.cos(newAngleRadians);
            layer.y = radius * Math.sin(newAngleRadians);
        });

        updateAvatar();
        saveState();
    };

    buttonRotate.addEventListener('mousedown', (e) => {
        activeButton = 'rotate';
        initialMousePos = { x: e.clientX, y: e.clientY };
        initialLayerData = N7I[1].layers.map(layer => ({
            x: layer.x,
            y: layer.y,
            scale: layer.scale,
            angle: layer.angle
        }));
        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
        saveState();
    });

    buttonScale.onclick = function() {
        let scaleInputValue = parseFloat(scaleInputField.value);
        let scaleFactor = parseFloat(scaleInputField.value) || 2;
        let layers = N7I[1].layers;
        layers.forEach((layer, index) => {
            layer.scale *= scaleFactor;
            layer.x *= scaleFactor;
            layer.y *= scaleFactor;
        });

        updateAvatar();
        saveState();
    };

    buttonScale.addEventListener('mousedown', (e) => {
        activeButton = 'scale';
        let containerRect = skineditor_previewbox_skincontainer.getBoundingClientRect();
        initialDistance = Math.sqrt(Math.pow(e.clientX - (containerRect.left + containerRect.width / 2), 2) + Math.pow(e.clientY - (containerRect.top + containerRect.height / 2), 2));
        initialMousePos = { x: e.clientX, y: e.clientY };
        initialLayerData = N7I[1].layers.map(layer => ({
            x: layer.x,
            y: layer.y,
            scale: layer.scale,
            angle: layer.angle
        }));
        document.addEventListener('mousemove', onMouseMove);
        document.addEventListener('mouseup', onMouseUp);
        saveState();
    });

    flipXButton.onclick = function() {
        N7I[1].layers.forEach(layer => {
            layer.flipX = !layer.flipX;
            layer.x = -layer.x;
            layer.angle = -layer.angle;
        });
        updateAvatar();
        saveState();
    };

    flipYButton.onclick = function() {
        N7I[1].layers.forEach(layer => {
            layer.flipY = !layer.flipY;
            layer.y = -layer.y;
            layer.angle = -layer.angle;
        });
        updateAvatar();
        saveState();
    };

    function invertColor(color) {
        return 0xFFFFFF - color;
    }

    invertColors.onclick = function() {
        let layers = N7I[1].layers;
        layers.forEach(layer => {
            layer.color = invertColor(layer.color);
        });
        N7I[1].bc = invertColor(N7I[1].bc);
        updateAvatar();
        S_z()
    };

    butload.onclick = function() {
        let parsedData = JSON.parse(inputload.value);
        let avatar = new t$e[80]();
        avatar.fromObject(parsedData);
        N7I[1] = avatar;
        console.log("N7I[1] after load:", N7I[1]);
        updateAvatar();
        S_z()
    };

    inputload.onchange = function() {
        try {
            let parsedData = JSON.parse(inputload.value);
            let avatar = new t$e[80]();
            avatar.fromObject(parsedData);
            N7I[1] = avatar;
            inputload.value = JSON.stringify(N7I[1]);
            console.log("Avatar updated from input:", N7I[1]);
        } catch (error) {
            console.error("Invalid JSON in input field:", error);
        }
    };
    inputload.onkeydown = function(event) {
    if (event.key === 'Enter' && inputload.value.trim() === '') {
        inputload.value = '{"layers":[],"bc":0}';
        }
    };

    function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
    }

    function getRandomFloat(min, max) {
    return Math.random() * (max - min) + min;
    }

    function getRandomBool() {
        return Math.random() < 0.5;
    }

    function getRandomLayer() {
        return {
            id: getRandomInt(1, 115), // 1, 115
            scale: getRandomFloat(0, 2),
            angle: getRandomFloat(0, 360),
            x: getRandomFloat(-25, 25),
            y: getRandomFloat(-25, 25),
            flipX: getRandomBool(),
            flipY: getRandomBool(),
            color: getRandomInt(0, 16777215) // 0, 16777215
        };
    }

    function generateRandomAvatar() {
        let layers = [];
        let numLayers = getRandomInt(16, 16);
        for (let i = 0; i < numLayers; i++) {
            layers.push(getRandomLayer());
        }
        return { layers: layers, bc: getRandomInt(0, 16777215) };
    }

    let autoAvatarCheckbox = document.createElement("input");
    autoAvatarCheckbox.type = "checkbox";
    autoAvatarCheckbox.id = "skineditor_checkbox";
    document.getElementById("skineditor_previewbox").appendChild(autoAvatarCheckbox);
    function setRandomAvatar() {
        let randomAvatar = generateRandomAvatar();
        let avatar = new t$e[80]();
        avatar.fromObject(randomAvatar);
        t$e[61].avatar = avatar;
        console.log("New random avatar set:", randomAvatar);
        initializeAvatar();
    }

    let avatarInterval;
    autoAvatarCheckbox.onchange = function() {
        if (autoAvatarCheckbox.checked) {
            console.log("Auto avatar change is enabled.");
            avatarInterval = setInterval(setRandomAvatar, 2000);
        } else {
            console.log("Auto avatar change is disabled.");
            clearInterval(avatarInterval);
        }
    };

    butrandom.onclick = function() {
        let randomAvatar = generateRandomAvatar();
        inputload.value = JSON.stringify(randomAvatar);
        let parsedData = JSON.parse(inputload.value);
        let avatar = new t$e[80]();
        avatar.fromObject(parsedData);
        console.log("Random avatar generated:", randomAvatar);
        N7I[1] = avatar;
        updateAvatar();
    };
    `);
    if (src === newSrc) throw "Injection failed!";
    console.log(injectorName + " injector run");
    return newSrc;
}

if (!window.bonkCodeInjectors) window.bonkCodeInjectors = [];
window.bonkCodeInjectors.push(bonkCode => {
    try {
        return injector(bonkCode);
    } catch (error) {
        alert(`Whoops! ${injectorName} was unable to load.`);
        throw error;
    }
});

console.log(injectorName + " injector loaded");