Dolphinware

Free Krunker.io cheats

이 스크립트를 설치하려면 Tampermonkey, Greasemonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램을 설치해야 합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Violentmonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey 또는 Userscripts와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 Tampermonkey와 같은 확장 프로그램이 필요합니다.

이 스크립트를 설치하려면 유저 스크립트 관리자 확장 프로그램이 필요합니다.

(이미 유저 스크립트 관리자가 설치되어 있습니다. 설치를 진행합니다!)

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 Stylus와 같은 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

이 스타일을 설치하려면 유저 스타일 관리자 확장 프로그램이 필요합니다.

(이미 유저 스타일 관리자가 설치되어 있습니다. 설치를 진행합니다!)

// ==UserScript==
// @name         Dolphinware
// @namespace    http://tampermonkey.net/
// @version      1.8
// @description  Free Krunker.io cheats
// @author       Frojy
// @match        *://krunker.io/*
// @exclude      *://krunker.io/social*
// @exclude      *://krunker.io/editor*
// @icon         https://www.google.com/s2/favicons?domain=krunker.io
// @grant        none
// @run-at       document-start
// @license      MIT
// @require      https://unpkg.com/[email protected]/build/three.min.js
// ==/UserScript==

const THREE = window.THREE;
delete window.THREE;

const settings = {
    aimbotEnabled: true,
    aimbotOnRightMouse: false,
    aimbotSmoothing: 0.1,
    aimbotFov: 150,
    wallCheck: true,
    fovCircleEnabled: true,
    fovCircleHidden: false,
    fovCircleColor: '#66b3ff',
    espEnabled: true,
    espColor: '#66b3ff'
};

const keyToSetting = {
    KeyB: 'aimbotEnabled',
    KeyL: 'aimbotOnRightMouse',
    KeyV: 'espEnabled'
};

const displayNames = {
    aimbotEnabled: 'Aimbot',
    aimbotOnRightMouse: 'ADS Aimbot',
    espEnabled: 'ESP'
};

let scene;

const x = {
    window: window,
    document: document,
    querySelector: document.querySelector,
    consoleLog: console.log,
    ArrayPrototype: Array.prototype,
    ArrayPush: Array.prototype.push,
    setTimeout: window.setTimeout,
    requestAnimationFrame: window.requestAnimationFrame
};

x.consoleLog('Waiting to inject...');

const proxied = function (object) {
    try {
        if (typeof object === 'object' &&
            typeof object.parent === 'object' &&
            object.parent.type === 'Scene' &&
            object.parent.name === 'Main') {

            x.consoleLog('Found Scene!');
            scene = object.parent;
            x.ArrayPrototype.push = x.ArrayPush;
        }
    } catch (error) {}

    return x.ArrayPush.apply(this, arguments);
}

const tempVector = new THREE.Vector3();
const tempVector2 = new THREE.Vector3();
const tempObject = new THREE.Object3D();
tempObject.rotation.order = 'YXZ';
const raycaster = new THREE.Raycaster();

const geometry = new THREE.EdgesGeometry(new THREE.BoxGeometry(5, 15, 5).translate(0, 7.5, 0));

const material = new THREE.RawShaderMaterial({
    uniforms: {
        uColor: { value: new THREE.Color(settings.espColor) }
    },

    vertexShader: `
        precision mediump float;
        attribute vec3 position;
        uniform mat4 projectionMatrix;
        uniform mat4 modelViewMatrix;
        void main() {
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `,
    fragmentShader: `
        precision mediump float;
        uniform vec3 uColor;
        void main() {
            gl_FragColor = vec4(uColor, 1.0);
        }
    `
});

Object.defineProperty(settings, 'espColor', {
    get() {
        return this.__espColor;
    },
    set(value) {
        this.__espColor = value;
        material.uniforms.uColor.value.set(value);
    }
});
settings.__espColor = settings.espColor;

const line = new THREE.LineSegments(new THREE.BufferGeometry(), material);
material.depthTest = false;
material.depthWrite = false;
material.transparent = true;
line.frustumCulled = false;

const linePositions = new THREE.BufferAttribute(new Float32Array(100 * 2 * 3), 3);
line.geometry.setAttribute('position', linePositions);

let injectTimer = null;

function animate() {
    x.requestAnimationFrame.call(x.window, animate);

    if (!scene && !injectTimer) {
        const el = x.querySelector.call(x.document, '#loadingBg');
        if (el && el.style.display === 'none') {
            x.consoleLog('Inject timer started!');
            injectTimer = x.setTimeout.call(x.window, () => {
                x.consoleLog('Injected!');
                x.ArrayPrototype.push = proxied;
            }, 2e3);
        }
    }

    if (!scene || !scene.children) return;

    const players = [];
    const colliders = [];
    let myPlayer;

    for (let i = 0; i < scene.children.length; i++) {
        const child = scene.children[i];

        if (child.type === 'Object3D') {
            try {
                if (child.children[0].children[0].type === 'PerspectiveCamera') {
                    myPlayer = child;
                } else {
                    players.push(child);
                }
            } catch (err) {}
        } else if (child.type === 'Mesh' || child.type === 'Group') {
            colliders.push(child);
        }
    }

    if (!myPlayer) {
        x.consoleLog('Player not found, finding new scene.');
        x.ArrayPrototype.push = proxied;
        return;
    }

    let counter = 0;
    let targetPlayer;
    let minDistance = Infinity;

    tempObject.matrix.copy(myPlayer.matrix).invert();
    const screenCenterX = window.innerWidth / 2;
    const screenCenterY = window.innerHeight / 2;
    const camera = myPlayer.children[0].children[0];

    for (let i = 0; i < players.length; i++) {
        const player = players[i];

        if (!player.box) {
            const box = new THREE.LineSegments(geometry, material);
            box.frustumCulled = false;
            player.add(box);
            player.box = box;
        }

        if (player.position.x === myPlayer.position.x && player.position.z === myPlayer.position.z) {
            player.box.visible = false;
            if (line.parent !== player) player.add(line);
            continue;
        }

        linePositions.setXYZ(counter++, 0, 10, -5);

        tempVector.copy(player.position);
        tempVector.y += 9;
        tempVector.applyMatrix4(tempObject.matrix);

        linePositions.setXYZ(counter++, tempVector.x, tempVector.y, tempVector.z);

        player.visible = settings.espEnabled || player.visible;
        player.box.visible = settings.espEnabled;

        if (settings.aimbotEnabled) {
            tempVector.setScalar(0);
            player.children[0].children[0].localToWorld(tempVector);

            const vectorProjected = tempVector.clone();
            vectorProjected.project(camera);

            const screenX = (vectorProjected.x * 0.5 + 0.5) * window.innerWidth;
            const screenY = (-(vectorProjected.y * 0.5) + 0.5) * window.innerHeight;

            if (vectorProjected.z < 1) {
                const distToCenter = Math.hypot(screenX - screenCenterX, screenY - screenCenterY);
                if (distToCenter <= settings.aimbotFov) {
                    if (settings.wallCheck) {
                        tempVector2.setScalar(0);
                        myPlayer.children[0].children[0].localToWorld(tempVector2);

                        const direction = new THREE.Vector3().subVectors(tempVector, tempVector2);
                        const distanceToPlayer = direction.length();
                        direction.normalize();

                        raycaster.set(tempVector2, direction);
                        raycaster.far = distanceToPlayer;

                        const intersects = raycaster.intersectObjects(colliders, true);
                        if (intersects.length > 0) {
                            continue;
                        }
                    }

                    const distance = player.position.distanceTo(myPlayer.position);
                    if (distance < minDistance) {
                        targetPlayer = player;
                        minDistance = distance;
                    }
                }
            }
        }
    }

    linePositions.needsUpdate = true;
    line.geometry.setDrawRange(0, counter);
    line.visible = false;

    if (!settings.aimbotEnabled || (settings.aimbotOnRightMouse && !rightMouseDown) || !targetPlayer) return;

    tempVector.setScalar(0);
    targetPlayer.children[0].children[0].localToWorld(tempVector);

    tempObject.position.copy(myPlayer.position);
    tempObject.lookAt(tempVector);

    const targetX = -tempObject.rotation.x;
    const targetY = tempObject.rotation.y + Math.PI;

    myPlayer.children[0].rotation.x += (targetX - myPlayer.children[0].rotation.x) * settings.aimbotSmoothing;

    let diffY = targetY - myPlayer.rotation.y;
    diffY = Math.atan2(Math.sin(diffY), Math.cos(diffY));
    myPlayer.rotation.y += diffY * settings.aimbotSmoothing;
}

const el = document.createElement('div');

el.innerHTML = `<style>
.dialog {
    position: absolute;
    left: 50%;
    top: 50%;
    padding: 18px;
    background: rgba(0, 0, 0, 0.85);
    border: 2px solid rgba(255, 255, 255, 0.15);
    color: #fff;
    transform: translate(-50%, -50%);
    text-align: center;
    z-index: 999999;
    border-radius: 10px;
    font-family: monospace;
}
.close {
    position: absolute;
    right: 10px;
    top: 10px;
    width: 20px;
    height: 20px;
    opacity: 0.6;
    cursor: pointer;
}
.close:before, .close:after {
    content: '';
    position: absolute;
    left: 50%;
    top: 50%;
    width: 100%;
    height: 2px;
    background: #fff;
}
.close:before { transform: translate(-50%, -50%) rotate(45deg); }
.close:after { transform: translate(-50%, -50%) rotate(-45deg); }
.msg {
    position: absolute;
    left: 10px;
    bottom: 10px;
    color: #fff;
    background: rgba(0, 0, 0, 0.6);
    font-weight: bolder;
    padding: 12px;
    animation: msg 0.5s forwards, msg 0.5s reverse forwards 3s;
    z-index: 999999;
    pointer-events: none;
    border-radius: 8px;
}
@keyframes msg {
    from { transform: translate(-120%, 0); }
    to { transform: none; }
}
.zui {
    position: fixed;
    right: 10px;
    top: 10px;
    z-index: 999;
    width: 230px;
    user-select: none;
    font-family: monospace;
}
.zui-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: rgba(0,0,0,0.75);
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid rgba(255,255,255,0.15);
    cursor: grab;
}
.zui-header span {
    font-size: 14px;
    font-weight: bold;
    color: #6cc7ff;
}
.zui-content {
    margin-top: 8px;
    background: rgba(0,0,0,0.55);
    border-radius: 8px;
    overflow: hidden;
}
.zui-item {
    display: flex;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid rgba(255,255,255,0.1);
    cursor: pointer;
}
.zui-item:last-child { border-bottom: none; }
.zui-item:hover { background: rgba(255,255,255,0.06); }
.zui-item-value {
    font-weight: bold;
}
#fovCircleElement {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    border: 2px solid ${settings.fovCircleColor};
    border-radius: 50%;
    pointer-events: none;
    z-index: 99998;
    display: block;
}
</style>
<div class="msg" style="display: none;"></div>
<div id="fovCircleElement" style="width: ${settings.aimbotFov * 2}px; height: ${settings.aimbotFov * 2}px;"></div>
</div>`;

const msgEl = el.querySelector('.msg');
const dialogEl = el.querySelector('.dialog');
const fovCircleEl = el.querySelector('#fovCircleElement');
const gui = createGUI();

window.addEventListener('DOMContentLoaded', function () {
    while (el.children.length > 0) {
        document.body.appendChild(el.children[0]);
    }
    document.body.appendChild(gui);
});

let rightMouseDown = false;

function handleMouse(event) {
    if (event.button === 2) {
        rightMouseDown = event.type === 'pointerdown';
    }
}

window.addEventListener('pointerdown', handleMouse);
window.addEventListener('pointerup', handleMouse);

window.addEventListener('keyup', function (event) {
    if (document.activeElement && document.activeElement.value !== undefined) return;

    if (keyToSetting[event.code]) {
        toggleSetting(keyToSetting[event.code]);
    }

    switch (event.code) {
        case 'Slash':
            toggleElementVisibility(gui);
            break;
        case 'KeyH':
            gui.style.display = gui.style.display === 'none' ? '' : 'none';
            dialogEl.style.display = gui.style.display === 'none' ? 'none' : '';
            break;
    }
});

function toggleElementVisibility(el) {
    el.style.display = el.style.display === '' ? 'none' : '';
}

function showMsg(name, bool) {
    msgEl.innerText = name + ': ' + (bool ? 'ON' : 'OFF');
    msgEl.style.display = 'none';
    void msgEl.offsetWidth;
    msgEl.style.display = '';
}

animate();

function createGUI() {
    const guiEl = fromHtml(`<div class="zui">
        <div class="zui-header">
            <span>Dolphinware [v1.8]</span>
        </div>
        <div class="zui-content"></div>
    </div>`);

    const headerEl = guiEl.querySelector('.zui-header');
    const contentEl = guiEl.querySelector('.zui-content');
    const headerStatusEl = guiEl.querySelector('.zui-item-value');

    let isDragging = false;
    let dragOffsetX = 0;
    let dragOffsetY = 0;

    headerEl.onpointerdown = function (e) {
        isDragging = true;
        headerEl.setPointerCapture(e.pointerId);

        const rect = guiEl.getBoundingClientRect();
        dragOffsetX = e.clientX - rect.left;
        dragOffsetY = e.clientY - rect.top;

        headerEl.style.cursor = "grabbing";
    };

    headerEl.onpointermove = function (e) {
        if (!isDragging) return;
        guiEl.style.left = `${e.clientX - dragOffsetX}px`;
        guiEl.style.top = `${e.clientY - dragOffsetY}px`;
        guiEl.style.transform = "";
    };

    headerEl.onpointerup = function () {
        isDragging = false;
        headerEl.style.cursor = "grab";
    };

    headerEl.onpointercancel = function () {
        isDragging = false;
        headerEl.style.cursor = "grab";
    };

    headerEl.onclick = function () {
        const isHidden = contentEl.style.display === 'none';
        contentEl.style.display = isHidden ? '' : 'none';
        headerStatusEl.innerText = isHidden ? '[close]' : '[open]';
    }

    const aimbotItem = fromHtml(`
    <div class="zui-item" style="flex-direction:column;">
        <div style="display:flex;justify-content:space-between;align-items:center;width:100%;">
            <span id="aimbotMainToggle" style="flex-grow:1;color:#636363;">[B] Aimbot</span>
            <span id="aimbotValue" style="margin-right:10px;font-weight:bold;"></span>
            <span id="aimbotArrow" style="cursor:pointer;padding:0 4px;color:#6cc7ff;">▼</span>
        </div>
        <div id="aimbotDropdown" style="display:none;margin-top:8px;flex-direction:column;gap:8px;width:100%;cursor:default;">
            <div id="adsItem" style="display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-top:1px solid rgba(255,255,255,0.05);cursor:pointer;color:#636363;">
                <span>[L] ADS Aimbot</span>
                <span id="adsValue" style="font-weight:bold;"></span>
            </div>
            <div id="wallCheckItem" style="display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-top:1px solid rgba(255,255,255,0.05);cursor:pointer;color:#636363">
                <span>Wall Check</span>
                <span id="wallCheckValue" style="font-weight:bold;"></span>
            </div>
            <div style="display:flex;flex-direction:column;gap:4px;padding-top:4px;border-top:1px solid rgba(255,255,255,0.05);" onclick="event.stopPropagation();">
                <div style="display:flex;justify-content:space-between;color:#898989;font-size:11px;">
                    <span>Smoothing</span>
                    <span id="smooth-val">${settings.aimbotSmoothing}</span>
                </div>
                <input type="range" id="smooth-slider" min="0.01" max="1" step="0.01" value="${settings.aimbotSmoothing}" style="width:100%;cursor:pointer;accent-color:#6cc7ff;">
            </div>
            <div style="display:flex;flex-direction:column;gap:4px;padding-top:4px;border-top:1px solid rgba(255,255,255,0.05);" onclick="event.stopPropagation();">
                <div style="display:flex;justify-content:space-between;color:#898989;font-size:11px;">
                    <span>FOV Radius</span>
                    <span id="fov-val">${settings.aimbotFov}px</span>
                </div>
                <input type="range" id="fov-slider" min="50" max="600" step="10" value="${settings.aimbotFov}" style="width:100%;cursor:pointer;accent-color:#6cc7ff;">
            </div>
            <div id="fovCircleToggleItem" style="display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-top:1px solid rgba(255,255,255,0.05);cursor:pointer;color:#636363">
                <span>FOV Circle</span>
                <span id="fovCircleValue" style="font-weight:bold;"></span>
            </div>
            <div id="fovCircleHiddenItem" style="display:flex;justify-content:space-between;align-items:center;padding:4px 0;border-top:1px solid rgba(255,255,255,0.05);cursor:pointer;color:#636363">
                <span>Hidden Circle</span>
                <span id="fovCircleHiddenValue" style="font-weight:bold;"></span>
            </div>
            <div style="display:flex;flex-direction:column;gap:6px;padding-top:4px;border-top:1px solid rgba(255,255,255,0.05);" onclick="event.stopPropagation();">
                <span style="color:#898989;font-size:11px;">Circle Color</span>
                <input type="color" id="fovColorInput" value="${settings.fovCircleColor}" style="width:100%;height:28px;border:none;cursor:pointer;">
            </div>
        </div>
    </div>
    `);

    const aimbotMainToggle = aimbotItem.querySelector('#aimbotMainToggle');
    const aimbotValue = aimbotItem.querySelector('#aimbotValue');
    const aimbotArrow = aimbotItem.querySelector('#aimbotArrow');
    const aimbotDropdown = aimbotItem.querySelector('#aimbotDropdown');
    const adsItem = aimbotItem.querySelector('#adsItem');
    const adsValue = aimbotItem.querySelector('#adsValue');
    const wallCheckItem = aimbotItem.querySelector('#wallCheckItem');
    const wallCheckValue = aimbotItem.querySelector('#wallCheckValue');
    const smoothSlider = aimbotItem.querySelector('#smooth-slider');
    const smoothValDisplay = aimbotItem.querySelector('#smooth-val');
    const fovSlider = aimbotItem.querySelector('#fov-slider');
    const fovValDisplay = aimbotItem.querySelector('#fov-val');
    const fovCircleToggleItem = aimbotItem.querySelector('#fovCircleToggleItem');
    const fovCircleValue = aimbotItem.querySelector('#fovCircleValue');
    const fovCircleHiddenItem = aimbotItem.querySelector('#fovCircleHiddenItem');
    const fovCircleHiddenValue = aimbotItem.querySelector('#fovCircleHiddenValue');
    const fovColorInput = aimbotItem.querySelector('#fovColorInput');

    function updateAimbotUI() {
        aimbotValue.innerText = settings.aimbotEnabled ? "ON" : "OFF";
        aimbotValue.style.color = settings.aimbotEnabled ? "lime" : "red";
    }

    function updateAdsUI() {
        adsValue.innerText = settings.aimbotOnRightMouse ? "ON" : "OFF";
        adsValue.style.color = settings.aimbotOnRightMouse ? "lime" : "red";
    }

    function updateWallCheckUI() {
        wallCheckValue.innerText = settings.wallCheck ? "ON" : "OFF";
        wallCheckValue.style.color = settings.wallCheck ? "lime" : "red";
    }

    function updateFovCircleUI() {
        fovCircleValue.innerText = settings.fovCircleEnabled ? "ON" : "OFF";
        fovCircleValue.style.color = settings.fovCircleEnabled ? "lime" : "red";
        updateCircleVisibility();
    }

    function updateFovCircleHiddenUI() {
        fovCircleHiddenValue.innerText = settings.fovCircleHidden ? "ON" : "OFF";
        fovCircleHiddenValue.style.color = settings.fovCircleHidden ? "lime" : "red";
        updateCircleVisibility();
    }

    function updateCircleVisibility() {
        if (!fovCircleEl) return;
        if (!settings.fovCircleEnabled || settings.fovCircleHidden) {
            fovCircleEl.style.display = 'none';
        } else {
            fovCircleEl.style.display = 'block';
        }
    }

    aimbotMainToggle.onclick = function () {
        settings.aimbotEnabled = !settings.aimbotEnabled;
        showMsg('Aimbot', settings.aimbotEnabled);
    };
    aimbotValue.onclick = aimbotMainToggle.onclick;

    aimbotArrow.onclick = function (e) {
        e.stopPropagation();
        const isHidden = aimbotDropdown.style.display === 'none';
        aimbotDropdown.style.display = isHidden ? 'flex' : 'none';
        aimbotArrow.innerText = isHidden ? '▲' : '▼';
    };

    adsItem.onclick = function () {
        settings.aimbotOnRightMouse = !settings.aimbotOnRightMouse;
        showMsg('ADS Aimbot', settings.aimbotOnRightMouse);
    };

    wallCheckItem.onclick = function () {
        settings.wallCheck = !settings.wallCheck;
        showMsg('Wall Check', settings.wallCheck);
    };

    smoothSlider.oninput = function (e) {
        settings.aimbotSmoothing = parseFloat(e.target.value);
        smoothValDisplay.innerText = settings.aimbotSmoothing;
    };

    fovSlider.oninput = function (e) {
        settings.aimbotFov = parseInt(e.target.value);
        fovValDisplay.innerText = settings.aimbotFov + 'px';
        if (fovCircleEl) {
            fovCircleEl.style.width = (settings.aimbotFov * 2) + 'px';
            fovCircleEl.style.height = (settings.aimbotFov * 2) + 'px';
        }
    };

    fovCircleToggleItem.onclick = function () {
        settings.fovCircleEnabled = !settings.fovCircleEnabled;
        showMsg('FOV Circle', settings.fovCircleEnabled);
    };

    fovCircleHiddenItem.onclick = function () {
        settings.fovCircleHidden = !settings.fovCircleHidden;
        showMsg('Hidden Circle', settings.fovCircleHidden);
    };

    fovColorInput.oninput = function (e) {
        settings.fovCircleColor = e.target.value;
        if (fovCircleEl) {
            fovCircleEl.style.borderColor = settings.fovCircleColor;
        }
    };

const initialAimbot = settings.aimbotEnabled;
const initialADS = settings.aimbotOnRightMouse;
const initialWallCheck = settings.wallCheck;
const initialFovCircle = settings.fovCircleEnabled;
const initialFovHidden = settings.fovCircleHidden;

Object.defineProperty(settings, "aimbotEnabled", {
    get() { return this.__aimbotEnabled; },
    set(v) {
        this.__aimbotEnabled = v;
        updateAimbotUI();
    }
});
settings.__aimbotEnabled = initialAimbot;

Object.defineProperty(settings, "aimbotOnRightMouse", {
    get() { return this.__aimbotOnRightMouse; },
    set(v) {
        this.__aimbotOnRightMouse = v;
        updateAdsUI();
    }
});
settings.__aimbotOnRightMouse = initialADS;

Object.defineProperty(settings, "wallCheck", {
    get() { return this.__wallCheck; },
    set(v) {
        this.__wallCheck = v;
        updateWallCheckUI();
    }
});
settings.__wallCheck = initialWallCheck;

Object.defineProperty(settings, "fovCircleEnabled", {
    get() { return this.__fovCircleEnabled; },
    set(v) {
        this.__fovCircleEnabled = v;
        updateFovCircleUI();
    }
});
settings.__fovCircleEnabled = initialFovCircle;

Object.defineProperty(settings, "fovCircleHidden", {
    get() { return this.__fovCircleHidden; },
    set(v) {
        this.__fovCircleHidden = v;
        updateFovCircleHiddenUI();
    }
});
settings.__fovCircleHidden = initialFovHidden;

updateAimbotUI();
updateAdsUI();
updateWallCheckUI();
updateFovCircleUI();
updateFovCircleHiddenUI();


    contentEl.appendChild(aimbotItem);

    const uiUpdaters = {};

    for (const prop in settings) {
        if (prop.startsWith("__")) continue;
        if (prop === 'espColor' || prop === 'aimbotEnabled' || prop === 'aimbotOnRightMouse' || prop === 'wallCheck' || prop === 'aimbotSmoothing' || prop === 'aimbotFov' || prop === 'fovCircleEnabled' || prop === 'fovCircleHidden' || prop === 'fovCircleColor') continue;

        let name = displayNames[prop] || fromCamel(prop);
        let shortKey = null;
        for (const key in keyToSetting) {
            if (keyToSetting[key] === prop) { shortKey = key; break; }
        }

        if (shortKey) {
            if (shortKey.startsWith('Key')) shortKey = shortKey.slice(3);
            name = `[${shortKey}] ${name}`;
        }

        const itemEl = fromHtml(`<div class="zui-item">
            <span style="color:#636363;">${name}</span>
            <span class="zui-item-value"></span>
         </div>`);
        const valueEl = itemEl.querySelector('.zui-item-value');

        function updateValueEl() {
            const value = settings[prop];
            valueEl.innerText = value ? 'ON' : 'OFF';
            valueEl.style.color = value ? 'lime' : 'red';
        }

        uiUpdaters[prop] = updateValueEl;

        itemEl.onclick = function () {
            settings[prop] = !settings[prop];
        }

        updateValueEl();
        contentEl.appendChild(itemEl);

        const p = `__${prop}`;
        settings[p] = settings[prop];
        Object.defineProperty(settings, prop, {
            get() { return this[p]; },
            set(value) {
                this[p] = value;
                updateValueEl();
            }
        });
    }

    const espColorItem = fromHtml(`
    <div class="zui-item" style="flex-direction:column;">
        <div style="display:flex;justify-content:space-between;align-items:center;color:#636363;">
            <span>ESP Color</span>
            <span style="color:#66b3ff;">▼</span>
        </div>
        <div style="display:none;margin-top:8px;flex-direction:column;gap:6px;">
            <input type="color" value="${settings.espColor}" style="width:100%;height:28px;border:none;cursor:pointer;">
            <label style="display:flex;align-items:center;gap:6px;cursor:pointer;">
                <input type="checkbox" id="espRainbowCheckbox" style="
                    accent-color: #66b3ff;
                    width:16px; height:16px;
                    cursor:pointer;
                ">
                <span style="color:#66b3ff;font-weight:bold;">Rainbow ESP</span>
            </label>
        </div>
    </div>
    `);

    const espDropdown = espColorItem.children[1];
    const colorInput = espDropdown.querySelector('input[type=color]');
    const rainbowCheckbox = espDropdown.querySelector('#espRainbowCheckbox');

    rainbowCheckbox.checked = settings.espRainbow;

    espColorItem.children[0].onclick = function () {
        espDropdown.style.display = espDropdown.style.display === 'none' ? '' : 'none';
    };

    colorInput.oninput = function (e) {
        settings.espColor = e.target.value;
    };

    rainbowCheckbox.onchange = function (e) {
        settings.espRainbow = e.target.checked;
    };

    contentEl.appendChild(espColorItem);

    const configItem = fromHtml(`
    <div class="zui-item" style="display:flex;gap:6px;padding:8px 12px;background:rgba(0,0,0,0.3);">
        <button id="exportConfigBtn" style="flex:1;background:#6cc7ff;color:#000;border:none;padding:6px;border-radius:4px;font-family:monospace;font-weight:bold;cursor:pointer;">Export Config</button>
        <button id="importConfigBtn" style="flex:1;background:#6cc7ff;color:#000;border:none;padding:6px;border-radius:4px;font-family:monospace;font-weight:bold;cursor:pointer;">Import Config</button>
    </div>
    `);

    const exportBtn = configItem.querySelector('#exportConfigBtn');
    const importBtn = configItem.querySelector('#importConfigBtn');

    exportBtn.onclick = function (e) {
        e.stopPropagation();
        const exportData = {
            aimbotEnabled: settings.aimbotEnabled,
            aimbotOnRightMouse: settings.aimbotOnRightMouse,
            aimbotSmoothing: settings.aimbotSmoothing,
            aimbotFov: settings.aimbotFov,
            wallCheck: settings.wallCheck,
            fovCircleEnabled: settings.fovCircleEnabled,
            fovCircleHidden: settings.fovCircleHidden,
            fovCircleColor: settings.fovCircleColor,
            espEnabled: settings.espEnabled,
            espColor: settings.espColor,
            espRainbow: settings.espRainbow
        };
        const jsonString = JSON.stringify(exportData);
        navigator.clipboard.writeText(jsonString).then(() => {
            alert("Config code copied to your clipboard!");
        }).catch(err => {
            prompt("Failed to copy automatically. Copy your config code below:", jsonString);
        });
    };

    importBtn.onclick = function (e) {
        e.stopPropagation();
        const inputString = prompt("Paste your config code here:");
        if (!inputString) return;
        try {
            const imported = JSON.parse(inputString);
            for (const key in imported) {
                if (settings.hasOwnProperty(key)) {
                    settings[key] = imported[key];
                }
            }

            updateAimbotUI();
            updateAdsUI();
            updateWallCheckUI();
            updateFovCircleUI();
            updateFovCircleHiddenUI();
            smoothSlider.value = settings.aimbotSmoothing;
            smoothValDisplay.innerText = settings.aimbotSmoothing;
            fovSlider.value = settings.aimbotFov;
            fovValDisplay.innerText = settings.aimbotFov + 'px';
            if (fovCircleEl) {
                fovCircleEl.style.width = (settings.aimbotFov * 2) + 'px';
                fovCircleEl.style.height = (settings.aimbotFov * 2) + 'px';
                fovCircleEl.style.borderColor = settings.fovCircleColor;
            }
            fovColorInput.value = settings.fovCircleColor;
            colorInput.value = settings.espColor;
            rainbowCheckbox.checked = !!settings.espRainbow;

            for (const prop in uiUpdaters) {
                uiUpdaters[prop]();
            }

            alert("Config loaded successfully!");
        } catch (err) {
            alert("Invalid config code!");
        }
    };

    contentEl.appendChild(configItem);

    let hue = 0;
    const originalAnimate = animate;
    animate = function () {
        if (settings.espEnabled && settings.espRainbow) {
            hue += 0.5;
            if (hue > 360) hue = 0;
            const color = new THREE.Color(`hsl(${hue}, 100%, 50%)`);
            material.uniforms.uColor.value.copy(color);
        } else {
            material.uniforms.uColor.value.set(settings.espColor);
        }

        originalAnimate();
    };

    return guiEl;
}

function fromCamel(text) {
    const result = text.replace(/([A-Z])/g, ' $1');
    return result.charAt(0).toUpperCase() + result.slice(1);
}

function fromHtml(html) {
    const div = document.createElement('div');
    div.innerHTML = html;
    return div.children.length > 0 ? div.children[0] : div.firstChild;
}

function toggleSetting(key) {
    settings[key] = !settings[key];
    showMsg(displayNames[key] || fromCamel(key), settings[key]);
}