Krunkax - levifrsn63

Locks aim to the nearest player in krunker.io and shows players behind walls. Also shows a line between you and them.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Krunkax - levifrsn63
// @namespace    http://tampermonkey.net/
// @version      0.6(Beta)
// @description  Locks aim to the nearest player in krunker.io and shows players behind walls. Also shows a line between you and them.
// @author       levifrsn63
// @match        *://krunker.io/*
// @match        *://browserfps.com/*
// @exclude      *://krunker.io/social*
// @exclude      *://krunker.io/editor*
// @icon         https://www.google.com/s2/favicons?domain=krunker.io
// @grant        none
// @license      MIT
// @run-at       document-start
// @require      https://unpkg.com/[email protected]/build/three.min.js
// ==/UserScript==

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

// LocalStorage key for persistence
const STORAGE_KEY = 'krunkax_settings';

// Default settings
const defaultSettings = {
  aimbotEnabled: true,
  aimbotOnRightMouse: true,
  espEnabled: true,
  espLines: false,
  wireframe: false,
  fovCircle: true,
  fovRadius: 200,
  aimSmoothing: false,
  antiRecoil: false,
  teamCheck: false,
  iPadMode: false,
  aimSmoothingSpeed: 30,
  antiRecoilOffset: 0,
  antiRecoilAmount: 0,
  allHacksEnabled: true,
  dialogDismissed: false,
  nearestPlayerIndicator: false
};

// Load settings from localStorage or use defaults
function loadSettings() {
  try {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved) {
      const parsed = JSON.parse(saved);
      return { ...defaultSettings, ...parsed };
    }
  } catch (e) {
    console.log('Error loading settings:', e);
  }
  return { ...defaultSettings };
}

// Save settings to localStorage
function saveSettings() {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
  } catch (e) {
    console.log('Error saving settings:', e);
  }
}

// Clear settings from localStorage
function clearSettings() {
  try {
    localStorage.removeItem(STORAGE_KEY);
    // Reset to defaults
    Object.assign(settings, defaultSettings);
    console.log('Settings cleared and reset to defaults');
  } catch (e) {
    console.log('Error clearing settings:', e);
  }
}

// Clear all cookies and storage to unban
function unban() {
  try {
    // Clear all cookies
    document.cookie.split(';').forEach(cookie => {
      const eqPos = cookie.indexOf('=');
      const name = eqPos > -1 ? cookie.substring(0, eqPos).trim() : cookie.trim();
      document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/';
      document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=' + location.hostname;
      document.cookie = name + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/;domain=.' + location.hostname;
    });

    // Clear localStorage
    localStorage.clear();

    // Clear sessionStorage
    sessionStorage.clear();

    console.log('All cookies and storage cleared for unban');
  } catch (e) {
    console.log('Error during unban:', e);
  }
}

// Initialize settings
const settings = loadSettings();

const keyToSetting = {
  Digit5: 'aimbotEnabled',
  Digit6: 'aimbotOnRightMouse',
  Digit7: 'espEnabled',
  Digit8: 'espLines',
  Digit9: 'wireframe',
  Digit0: 'fovCircle',
  Digit1: 'aimSmoothing',
  Digit2: 'antiRecoil'
};

// Default keybinds
const defaultKeybinds = {
  aimbotEnabled: 'Digit5',
  aimbotOnRightMouse: 'Digit6',
  espEnabled: 'Digit7',
  espLines: 'Digit8',
  wireframe: 'Digit9',
  fovCircle: 'Digit0',
  aimSmoothing: 'Digit1',
  antiRecoil: 'Digit2',
  teamCheck: '',
  rightMouseAimbot: ''
};

// Custom keybinds (will be updated by user)
const customKeybinds = { ...defaultKeybinds };

const gui = createGUI();

// Create FOV circle canvas
const fovCanvas = document.createElement('canvas');
fovCanvas.style.position = 'fixed';
fovCanvas.style.top = '0';
fovCanvas.style.left = '0';
fovCanvas.style.width = '100%';
fovCanvas.style.height = '100%';
fovCanvas.style.pointerEvents = 'none';
fovCanvas.style.zIndex = '9999';

let scene;

const x = {
  window: window,
  document: document,
  querySelector: document.querySelector,
  consoleLog: console.log,
  ReflectApply: Reflect.apply,
  ArrayPrototype: Array.prototype,
  ArrayPush: Array.prototype.push,
  ObjectPrototype: Object.prototype,
  clearInterval: window.clearInterval,
  setTimeout: window.setTimeout,
  reToString: RegExp.prototype.toString,
  indexOf: String.prototype.indexOf,
  requestAnimationFrame: window.requestAnimationFrame
};

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

const proxied = function ( object ) {

  // [native code]

  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 tempObject = new THREE.Object3D();
tempObject.rotation.order = 'YXZ';

// Store target player info for indicator
let targetPlayerScreenPos = { x: null, y: null };
let targetPlayerDistance = null;

// FOV circle drawing function
function drawFOVCircle() {
  const ctx = fovCanvas.getContext('2d');
  ctx.clearRect(0, 0, fovCanvas.width, fovCanvas.height);

  if (settings.fovCircle) {
    const centerX = fovCanvas.width / 2;
    const centerY = fovCanvas.height / 2;

    ctx.beginPath();
    ctx.arc(centerX, centerY, settings.fovRadius, 0, 2 * Math.PI);
    ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)';
    ctx.lineWidth = 2;
    ctx.stroke();

    // Draw crosshair
    ctx.beginPath();
    ctx.moveTo(centerX - 10, centerY);
    ctx.lineTo(centerX + 10, centerY);
    ctx.moveTo(centerX, centerY - 10);
    ctx.lineTo(centerX, centerY + 10);
    ctx.strokeStyle = 'rgba(0, 255, 0, 0.7)';
    ctx.lineWidth = 2;
    ctx.stroke();
  }

  // Draw nearest player indicator on circle around crosshair
  if (settings.nearestPlayerIndicator && targetPlayerScreenPos.x !== null && targetPlayerDistance !== null) {
    const centerX = fovCanvas.width / 2;
    const centerY = fovCanvas.height / 2;

    // Calculate direction to target
    const dx = targetPlayerScreenPos.x - centerX;
    const dy = targetPlayerScreenPos.y - centerY;
    const angle = Math.atan2(dy, dx);

    // Position indicator on 240px radius circle around crosshair
    const indicatorRadius = 240;
    const indicatorX = centerX + Math.cos(angle) * indicatorRadius;
    const indicatorY = centerY + Math.sin(angle) * indicatorRadius;

    // Draw triangle pointing toward nearest player
    const triangleSize = 12;
    ctx.save();
    ctx.translate(indicatorX, indicatorY);
    ctx.rotate(angle);

    ctx.beginPath();
    ctx.moveTo(0, -triangleSize);
    ctx.lineTo(-triangleSize / 2, triangleSize / 2);
    ctx.lineTo(triangleSize / 2, triangleSize / 2);
    ctx.closePath();

    ctx.fillStyle = 'rgba(255, 100, 100, 0.8)';
    ctx.fill();
    ctx.strokeStyle = 'rgba(255, 100, 100, 1)';
    ctx.lineWidth = 2;
    ctx.stroke();

    ctx.restore();
  }

  // Always show distance at bottom of screen if we have a target
  if (targetPlayerDistance !== null) {
    const centerX = fovCanvas.width / 2;
    const distanceText = `Closest Player: ${Math.round(targetPlayerDistance)}m`;

    ctx.font = 'bold 14px monospace';
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';

    // Draw text shadow for better visibility
    ctx.fillStyle = 'rgba(0, 0, 0, 0.8)';
    ctx.fillText(distanceText, centerX + 1, fovCanvas.height - 9);

    // Draw text
    ctx.fillStyle = 'rgba(255, 255, 255, 0.95)';
    ctx.fillText(distanceText, centerX, fovCanvas.height - 10);
  }
}

// Check if point is within FOV
function isWithinFOV(screenX, screenY) {
  // When FOV circle is disabled, always return true to target closest person overall
  if (!settings.fovCircle) return true;

  const centerX = window.innerWidth / 2;
  const centerY = window.innerHeight / 2;
  const distance = Math.sqrt(
    Math.pow(screenX - centerX, 2) +
    Math.pow(screenY - centerY, 2)
  );

  return distance <= settings.fovRadius;
}

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

function createBoxMaterial() {
  return new THREE.RawShaderMaterial( {
    uniforms: {
      boxColor: { value: new THREE.Color( 1.0, 0.0, 0.0 ) }
    },
    vertexShader: `

    attribute vec3 position;

    uniform mat4 projectionMatrix;
    uniform mat4 modelViewMatrix;

    void main() {

      gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
      gl_Position.z = 1.0;

    }

    `,
    fragmentShader: `

    precision mediump float;
    uniform vec3 boxColor;

    void main() {

      gl_FragColor = vec4( boxColor, 1.0 );

    }

    `
  } );
}

const material = new THREE.RawShaderMaterial( {
  vertexShader: `

  attribute vec3 position;

  uniform mat4 projectionMatrix;
  uniform mat4 modelViewMatrix;

  void main() {

    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
    gl_Position.z = 1.0;

  }

  `,
  fragmentShader: `

  void main() {

    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );

  }

  `
} );

const line = new THREE.LineSegments( new THREE.BufferGeometry(), material );

line.frustumCulled = false;

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

let injectTimer = null;
let lastRotation = { x: 0, y: 0 };
let lockedTarget = null;
let isMouseDown = false;

function animate() {

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

  // Draw FOV circle
  drawFOVCircle();

  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 === undefined || ! scene.children ) {

    return;

  }

  const players = [];

  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.material ) {

      child.material.wireframe = settings.wireframe;

    }

  }

  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 camera = myPlayer.children[ 0 ].children[ 0 ];
  const validTargets = [];

  for ( let i = 0; i < players.length; i ++ ) {

    const player = players[ i ];

    if ( ! player.box ) {

      const boxMaterial = createBoxMaterial();
      const box = new THREE.LineSegments( geometry, boxMaterial );
      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.allHacksEnabled && settings.espEnabled) || player.visible;
    player.box.visible = settings.allHacksEnabled && settings.espEnabled;

    const distance = player.position.distanceTo( myPlayer.position );

    // Check if player is within FOV before adding to valid targets
    tempVector.setScalar( 0 );
    player.children[ 0 ].children[ 0 ].localToWorld( tempVector );
    const targetScreen = tempVector.clone();
    targetScreen.project( camera );

    const screenX = ( targetScreen.x + 1 ) / 2 * window.innerWidth;
    const screenY = ( -targetScreen.y + 1 ) / 2 * window.innerHeight;

    if ( isWithinFOV( screenX, screenY ) ) {
      // When FOV is enabled, only target players in front (not behind)
      let isInFront = true;
      if ( settings.fovCircle ) {
        // Check if player is in front using projected Z coordinate
        isInFront = targetScreen.z < 1; // Z < 1 means in front of camera
      }

      if ( isInFront ) {
        // Team check - don't add teammates to valid targets
        if ( settings.teamCheck ) {
          // Check if both players have team property and are on same team
          if ( myPlayer.team !== undefined && player.team !== undefined && myPlayer.team === player.team ) {
            // Skip adding teammate to valid targets
          } else {
            validTargets.push({ player, distance });
          }
        } else {
          validTargets.push({ player, distance });
        }
      }
    }

  }

  // Natural target locking - only use when FOV circle is enabled
  if ( settings.fovCircle && lockedTarget ) {
    // Check if locked target is still within FOV
    const lockedStillInFOV = validTargets.find( t => t.player === lockedTarget );
    if ( lockedStillInFOV ) {
      targetPlayer = lockedTarget;
    } else {
      // Release lock if target left FOV
      lockedTarget = null;
    }
  }

  // Select nearest target from valid targets
  if ( !targetPlayer && validTargets.length > 0 ) {
    validTargets.sort( ( a, b ) => a.distance - b.distance );
    targetPlayer = validTargets[ 0 ].player;
    // Only lock target when FOV circle is enabled
    if ( settings.fovCircle ) {
      lockedTarget = targetPlayer;
    }
  }

  // Clear locked target when FOV circle is disabled
  if ( !settings.fovCircle ) {
    lockedTarget = null;
  }

  // Update ESP box colors based on targeting
  for ( let i = 0; i < players.length; i ++ ) {
    const player = players[ i ];

    if ( player.box && player.box.material && player.box.material.uniforms ) {
      // Set color to green if this player is the target, red otherwise
      if ( player === targetPlayer ) {
        player.box.material.uniforms.boxColor.value.setRGB( 0.0, 1.0, 0.0 );
      } else {
        player.box.material.uniforms.boxColor.value.setRGB( 1.0, 0.0, 0.0 );
      }
    }
  }

  // Store target player screen position and distance for indicator
  if ( targetPlayer ) {
    // Use same projection method as ESP lines
    tempVector.setScalar( 0 );
    targetPlayer.children[ 0 ].children[ 0 ].localToWorld( tempVector );
    const targetScreen = tempVector.clone();
    targetScreen.project( camera );

    targetPlayerScreenPos.x = ( targetScreen.x + 1 ) / 2 * window.innerWidth;
    targetPlayerScreenPos.y = ( -targetScreen.y + 1 ) / 2 * window.innerHeight;

    // Calculate distance (in 3D space)
    targetPlayerDistance = targetPlayer.position.distanceTo( myPlayer.position );
  } else {
    targetPlayerScreenPos.x = null;
    targetPlayerScreenPos.y = null;
    targetPlayerDistance = null;
  }

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

  line.visible = settings.allHacksEnabled && settings.espLines;

  // Check if aimbot should be active
  const shouldAimbot = settings.allHacksEnabled && settings.aimbotEnabled && targetPlayer !== undefined && (
    ( settings.iPadMode && isTouching ) || // iPad mode: active when touching
    ( rightMouseAimbotKeyPressed ) || // Right mouse aimbot keybind
    ( !settings.iPadMode && settings.aimbotOnRightMouse && rightMouseDown ) || // Right mouse mode
    ( !settings.iPadMode && !settings.aimbotOnRightMouse && !rightMouseAimbotKeyPressed ) // Always on mode
  );

  if ( !shouldAimbot ) {
    // Update lastRotation with current camera position when aimbot is not active
    // This ensures smooth transition when aimbot activates
    lastRotation.x = myPlayer.children[ 0 ].rotation.x;
    lastRotation.y = myPlayer.rotation.y;
    return;

  }

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

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

  let targetRotX = - tempObject.rotation.x;
  let targetRotY = tempObject.rotation.y + Math.PI;

  // Apply smoothing
  if ( settings.aimSmoothing ) {
    const smoothness = settings.aimSmoothingSpeed / 100;
    targetRotX = lastRotation.x + ( targetRotX - lastRotation.x ) * smoothness;
    targetRotY = lastRotation.y + ( targetRotY - lastRotation.y ) * smoothness;
  }

  lastRotation.x = targetRotX;
  lastRotation.y = targetRotY;

  // Apply offset when locked on target
  const offsetRadians = ( settings.antiRecoilOffset / 100 );
  targetRotX += offsetRadians;

  // Apply anti-recoil compensation (moves down while shooting)
  if ( settings.antiRecoil && isMouseDown ) {
    const recoilCompensation = -( settings.antiRecoilAmount / 100 );
    targetRotX += recoilCompensation;
  }

  myPlayer.children[ 0 ].rotation.x = targetRotX;
  myPlayer.rotation.y = targetRotY;

}

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

el.innerHTML = `<style>

.dialog {
  position: absolute;
  left: 50%;
  top: 50%;
  padding: 30px;
  background: rgba(18, 18, 18, 0.98);
  border: 1px solid rgba(80, 80, 90, 0.5);
  border-radius: 8px;
  color: #e5e5e5;
  transform: translate(-50%, -50%);
  text-align: center;
  z-index: 999999;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.6);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', sans-serif;
}

.dialog * {
  color: #e5e5e5;
}

.close {
  position: absolute;
  right: 5px;
  top: 5px;
  width: 20px;
  height: 20px;
  opacity: 0.5;
  cursor: pointer;
}

.close:before, .close:after {
  content: ' ';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 100%;
  height: 20%;
  transform: translate(-50%, -50%) rotate(-45deg);
  background: #fff;
}

.close:after {
  transform: translate(-50%, -50%) rotate(45deg);
}

.close:hover {
  opacity: 1;
}

.btn {
  cursor: pointer;
  padding: 10px 20px;
  background: linear-gradient(135deg, rgba(60, 60, 70, 0.9), rgba(50, 50, 60, 0.9));
  border: 1px solid rgba(100, 100, 110, 0.3);
  border-radius: 8px;
  color: white;
  font-weight: 600;
  transition: all 0.2s ease;
}

.btn:active {
  transform: scale(0.95);
}

.btn:hover {
  background: linear-gradient(135deg, rgba(70, 70, 80, 0.95), rgba(60, 60, 70, 0.95));
}

.msg {
  position: absolute;
  left: 15px;
  bottom: 15px;
  color: #e5e5e5;
  background: rgba(18, 18, 18, 0.95);
  font-weight: 600;
  padding: 12px 20px;
  border-radius: 6px;
  border: 1px solid rgba(80, 80, 90, 0.5);
  animation: msg 0.5s forwards, msg 0.5s reverse forwards 3s;
  z-index: 999999;
  pointer-events: none;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', sans-serif;
  display: none !important;
}

@keyframes msg {
  from {
    transform: translate(-120%, 0);
  }

  to {
    transform: none;
  }
}

.zui {
  position: fixed;
  right: 15px;
  top: 15px;
  z-index: 999;
  display: flex;
  flex-direction: column;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', sans-serif;
  font-size: 13px;
  color: #fff;
  width: 420px;
  height: 480px;
  user-select: none;
  border: 1px solid rgba(80, 80, 90, 0.5);
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
  transition: all 0.3s ease;
  background: rgba(18, 18, 18, 1);
}

.zui.minimized {
  width: auto;
  height: auto;
}

.zui.minimized .zui-content,
.zui.minimized .zui-tabs,
.zui.minimized .zui-footer {
  display: none;
}

.zui.minimized .zui-header {
  padding: 8px 12px;
  border-radius: 8px;
  justify-content: space-between;
}

.zui.minimized .zui-header-title {
  display: inline-block;
}

.zui.minimized .zui-window-controls {
  position: static;
}

.zui-content {
  overflow-y: auto;
  overflow-x: hidden;
  flex: 1;
  scrollbar-width: thin;
  scrollbar-color: rgba(100, 100, 110, 0.5) transparent;
}

.zui-content::-webkit-scrollbar {
  width: 5px;
}

.zui-content::-webkit-scrollbar-track {
  background: transparent;
}

.zui-content::-webkit-scrollbar-thumb {
  background: rgba(100, 100, 110, 0.5);
  border-radius: 3px;
}

.zui-content::-webkit-scrollbar-thumb:hover {
  background: rgba(120, 120, 130, 0.7);
}

.zui-item {
  padding: 10px 14px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background: rgba(25, 25, 25, 0.6);
  cursor: pointer;
  transition: all 0.2s ease;
  margin: 6px 10px;
  border-radius: 6px;
}

.zui-item.text {
  justify-content: center;
  cursor: unset;
  text-align: center;
  background: rgba(30, 30, 30, 0.8);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: rgba(180, 180, 190, 0.9);
  margin: 12px 10px 8px 10px;
}

.zui-item:hover {
  background: rgba(30, 30, 30, 0.8);
}

.zui-item:active {
  transform: scale(0.98);
}

.zui-item span {
  color: #e5e7eb;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', sans-serif;
  font-size: 12px;
}

.zui-header {
  background: rgba(20, 20, 20, 1);
  padding: 12px 14px;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: move;
  border-bottom: 1px solid rgba(80, 80, 90, 0.4);
  position: relative;
}

.zui-header-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: #ffffff;
}

.zui-window-controls {
  display: flex;
  gap: 8px;
  position: absolute;
  right: 12px;
}

.zui-window-btn {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  cursor: pointer;
  transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  font-weight: bold;
  border: 2px solid;
}

.zui-window-btn.close {
  background: rgba(15, 15, 15, 1);
  border-color: rgba(15, 15, 15, 1);
  color: rgb(220, 80, 80);
}

.zui-window-btn.minimize {
  background: rgba(120, 120, 130, 0.2);
  border-color: rgba(120, 120, 130, 0.6);
  color: rgb(180, 180, 190);
}

.zui-window-btn:hover {
  transform: scale(1.05);
  opacity: 0.8;
}

.zui-window-btn:active {
  transform: scale(0.95);
}

.zui-header:hover {
  background: rgba(25, 25, 25, 1);
}

.zui-on {
  color: #10b981;
}

.zui-item-value {
  font-size: 11px;
  font-weight: 700;
  padding: 4px 10px;
  border-radius: 6px;
  background: rgba(15, 15, 15, 1);
  border: 1px solid rgba(100, 100, 110, 0.4);
}

.zui-content .zui-item-value {
  font-weight: 700;
}

.zui-tabs {
  display: flex;
  background: rgba(15, 15, 15, 0.8);
  border-bottom: 1px solid rgba(80, 80, 90, 0.4);
}

.zui-tab {
  flex: 1;
  padding: 10px;
  text-align: center;
  cursor: pointer;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: rgba(140, 140, 150, 0.8);
  transition: all 0.2s ease;
  border-bottom: 2px solid transparent;
}

.zui-tab:hover {
  color: rgba(180, 180, 190, 0.9);
  background: rgba(25, 25, 25, 0.4);
}

.zui-tab.active {
  color: rgba(200, 200, 210, 1);
  border-bottom-color: rgba(120, 120, 130, 1);
  background: rgba(25, 25, 25, 0.6);
}

.zui-tab-content {
  display: none;
}

.zui-tab-content.active {
  display: block;
}

.zui-slider-container {
  padding: 12px 14px;
  background: rgba(25, 25, 25, 0.6);
  margin: 6px 10px;
  border-radius: 6px;
}

.zui-slider-label {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
  color: #e5e7eb;
  font-size: 12px;
  font-weight: 500;
}

.zui-slider-value {
  color: #e5e7eb;
  font-weight: 700;
}

.zui-slider {
  width: 100%;
  height: 5px;
  border-radius: 3px;
  background: rgba(30, 30, 30, 0.8);
  outline: none;
  -webkit-appearance: none;
  appearance: none;
}

.zui-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: rgb(140, 140, 150);
  cursor: pointer;
  transition: all 0.2s ease;
}

.zui-slider::-webkit-slider-thumb:hover {
  background: rgb(160, 160, 170);
  transform: scale(1.1);
}

.zui-slider::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: rgb(140, 140, 150);
  cursor: pointer;
  border: none;
  transition: all 0.2s ease;
}

.zui-slider::-moz-range-thumb:hover {
  background: rgb(160, 160, 170);
  transform: scale(1.1);
}

.zui-footer {
  padding: 8px 14px;
  background: rgba(15, 15, 15, 0.95);
  text-align: center;
  font-size: 10px;
  color: rgba(140, 140, 150, 0.6);
  border-top: 1px solid rgba(80, 80, 90, 0.4);
  font-weight: 500;
  letter-spacing: 0.3px;
}

</style>
<div class="msg" style="display: none;"></div>
<div class="dialog">${`<div class="close" onclick="this.parentNode.style.display='none';"></div>
  <big>🎯 Advanced Aimbot & ESP</big>
  <br>
  <br>
  <strong>Aimbot Controls:</strong><br>
  [5] Toggle Aimbot | [6] Right Mouse Mode<br>
  [0] FOV Circle | [1] Aim Smoothing<br>
  [2] Anti Recoil<br>
  <br>
  <strong>ESP Controls:</strong><br>
  [7] Toggle ESP | [8] ESP Lines<br>
  [9] Wireframe Mode<br>
  <br>
  <strong>UI Controls:</strong><br>
  [H] Show/Hide Help | [/] Toggle Menu<br>
  <br>
  </div>
  ` }
</div>`;

const msgEl = el.querySelector( '.msg' );
const dialogEl = el.querySelector( '.dialog' );

// Setup dialog close persistence
const closeBtn = dialogEl.querySelector( '.close' );
closeBtn.onclick = function() {
  dialogEl.style.display = 'none';
  settings.dialogDismissed = true;
  saveSettings();
};

window.addEventListener( 'DOMContentLoaded', function () {

  while ( el.children.length > 0 ) {

    document.body.appendChild( el.children[ 0 ] );

  }

  document.body.appendChild( gui );
  document.body.appendChild( fovCanvas );

  // Hide dialog if it was previously dismissed
  if ( settings.dialogDismissed ) {
    dialogEl.style.display = 'none';
  }

  // Set canvas size
  fovCanvas.width = window.innerWidth;
  fovCanvas.height = window.innerHeight;

  // Update canvas size on window resize
  window.addEventListener('resize', function() {
    fovCanvas.width = window.innerWidth;
    fovCanvas.height = window.innerHeight;
  });

} );

let rightMouseDown = false;
let isTouching = false;
let rightMouseAimbotKeyPressed = false;

function handleMouse( event ) {

  if ( event.button === 2 ) {

    rightMouseDown = event.type === 'pointerdown' ? true : false;

  }

  // Track left mouse button for shooting
  if ( event.button === 0 ) {
    isMouseDown = event.type === 'pointerdown' ? true : false;
  }

}

function handleTouch( event ) {
  // For iPad/mobile mode
  isTouching = event.type === 'touchstart' ? true : false;
}

window.addEventListener( 'pointerdown', handleMouse );
window.addEventListener( 'pointerup', handleMouse );
window.addEventListener( 'touchstart', handleTouch );
window.addEventListener( 'touchend', handleTouch );

window.addEventListener( 'keyup', function ( event ) {

  if ( x.document.activeElement && x.document.activeElement.value !== undefined ) return;

  // Check custom keybinds first
  Object.keys(customKeybinds).forEach(settingKey => {
    if (customKeybinds[settingKey] === event.code && customKeybinds[settingKey] !== '') {
      if (settingKey !== 'rightMouseAimbot') {
        toggleSetting( settingKey );
      }
    }
  });

  // Handle right mouse aimbot keybind release
  if (customKeybinds.rightMouseAimbot === event.code && customKeybinds.rightMouseAimbot !== '') {
    rightMouseAimbotKeyPressed = false;
  }

  switch ( event.code ) {

    case 'Slash' :
      if ( gui.style.display === 'none' ) {
        gui.style.display = '';
      } else {
        toggleElementVisibility( gui );
      }
      break;

    case 'KeyH' :
      toggleElementVisibility( dialogEl );
      break;

  }

} );

// Handle right mouse aimbot keybind press
window.addEventListener( 'keydown', function ( event ) {

  if ( x.document.activeElement && x.document.activeElement.value !== undefined ) return;

  // Handle right mouse aimbot keybind press
  if (customKeybinds.rightMouseAimbot === event.code && customKeybinds.rightMouseAimbot !== '') {
    rightMouseAimbotKeyPressed = true;
  }

} );

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 class="zui-header-title">KRUNKAX AIMBOT</span>
      <div class="zui-window-controls">
        <div class="zui-window-btn minimize">-</div>
        <div class="zui-window-btn close">×</div>
      </div>
    </div>
    <div class="zui-tabs">
      <div class="zui-tab active" data-tab="cheats">Cheats</div>
      <div class="zui-tab" data-tab="settings">Settings</div>
      <div class="zui-tab" data-tab="keybinds" style="display:none;">Keybinds</div>
    </div>
    <div class="zui-content">
      <div class="zui-tab-content active" id="cheats-tab"></div>
      <div class="zui-tab-content" id="settings-tab"></div>
      <div class="zui-tab-content" id="keybinds-tab"></div>
    </div>
    <div class="zui-footer">Created by levifrsn63</div>
  </div>` );

  const headerEl = guiEl.querySelector( '.zui-header' );
  const cheatsContent = guiEl.querySelector( '#cheats-tab' );
  const settingsContent = guiEl.querySelector( '#settings-tab' );
  const keybindsContent = guiEl.querySelector( '#keybinds-tab' );
  const closeBtn = guiEl.querySelector( '.zui-window-btn.close' );
  const minimizeBtn = guiEl.querySelector( '.zui-window-btn.minimize' );
  const tabs = guiEl.querySelectorAll( '.zui-tab' );
  const tabContents = guiEl.querySelectorAll( '.zui-tab-content' );
  const keybindsTab = guiEl.querySelector( '.zui-tab[data-tab="keybinds"]' );

  // Tab switching
  tabs.forEach( tab => {
    tab.onclick = function() {
      tabs.forEach( t => t.classList.remove('active') );
      tabContents.forEach( tc => tc.classList.remove('active') );
      tab.classList.add('active');
      const tabName = tab.getAttribute('data-tab');
      guiEl.querySelector( `#${tabName}-tab` ).classList.add('active');
    };
  });

  // Close button
  closeBtn.onclick = function(e) {
    e.stopPropagation();
    guiEl.style.display = 'none';
  };

  // Minimize button
  minimizeBtn.onclick = function(e) {
    e.stopPropagation();
    guiEl.classList.toggle('minimized');
  };

  // Make draggable
  let isDragging = false;
  let currentX;
  let currentY;
  let initialX;
  let initialY;

  headerEl.addEventListener('mousedown', function(e) {
    if (e.target.classList.contains('zui-window-btn')) return;

    isDragging = true;
    initialX = e.clientX - guiEl.offsetLeft;
    initialY = e.clientY - guiEl.offsetTop;
  });

  document.addEventListener('mousemove', function(e) {
    if (isDragging) {
      e.preventDefault();
      currentX = e.clientX - initialX;
      currentY = e.clientY - initialY;

      guiEl.style.left = currentX + 'px';
      guiEl.style.top = currentY + 'px';
      guiEl.style.right = 'auto';
    }
  });

  document.addEventListener('mouseup', function() {
    isDragging = false;
  });

  const settingToKey = {};
  for ( const key in keyToSetting ) {
    settingToKey[ keyToSetting[ key ] ] = key;
  }

  // Define which settings go to which tab
  const cheatsSettings = ['aimbotEnabled', 'aimbotOnRightMouse', 'aimSmoothing', 'antiRecoil', 'teamCheck', 'fovCircle', 'espEnabled', 'espLines', 'wireframe'];
  const settingsTabSettings = ['fovRadius', 'aimSmoothingSpeed', 'antiRecoilOffset', 'antiRecoilAmount'];

  // Add section header helper
  function addSectionHeader(parent, title) {
    const headerEl = fromHtml( `<div class="zui-item text"><span>${title}</span></div>` );
    parent.appendChild( headerEl );
  }

  // Populate Cheats Tab
  // Master toggle button
  const masterToggle = fromHtml( `<div class="zui-item" style="background: rgba(40, 40, 40, 0.9); margin-bottom: 8px;">
    <span style="font-weight: 700; font-size: 13px;">Master Toggle</span>
    <span class="zui-item-value master-toggle-value"></span>
  </div>` );
  const masterToggleValue = masterToggle.querySelector( '.master-toggle-value' );

  function updateMasterToggle() {
    const value = settings.allHacksEnabled;
    masterToggleValue.innerText = value ? 'DISABLE HACKS' : 'ENABLE HACKS';
    masterToggleValue.style.color = value ? '#ef4444' : '#10b981';
    masterToggleValue.style.background = value ? 'rgba(239, 68, 68, 0.2)' : 'rgba(16, 185, 129, 0.2)';
  }

  masterToggle.onclick = function() {
    settings.allHacksEnabled = ! settings.allHacksEnabled;
  }
  updateMasterToggle();

  cheatsContent.appendChild( masterToggle );

  const masterP = '__allHacksEnabled';
  settings[ masterP ] = settings.allHacksEnabled;
  Object.defineProperty( settings, 'allHacksEnabled', {
    get() {
      return this[ masterP ];
    },
    set( value ) {
      this[ masterP ] = value;
      updateMasterToggle();
      saveSettings();
    }
  } );

  addSectionHeader(cheatsContent, 'Aimbot/Exploits');

  ['aimbotEnabled', 'aimbotOnRightMouse', 'aimSmoothing', 'antiRecoil', 'teamCheck'].forEach(prop => {
    let name = fromCamel( prop );
    let shortKey = settingToKey[ prop ];

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

    const itemEl = fromHtml( `<div class="zui-item">
      <span>${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 ? '#10b981' : '#ef4444';
    }

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

    cheatsContent.appendChild( itemEl );

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

  addSectionHeader(cheatsContent, 'ESP / Visual');

  ['fovCircle', 'espEnabled', 'espLines', 'nearestPlayerIndicator', 'wireframe'].forEach(prop => {
    let name = fromCamel( prop );
    let shortKey = settingToKey[ prop ];

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

    const itemEl = fromHtml( `<div class="zui-item">
      <span>${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 ? '#10b981' : '#ef4444';
    }

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

    cheatsContent.appendChild( itemEl );

    const p = `__${prop}`;
    settings[ p ] = settings[ prop ];

    // Create setter with proper closure
    const propName = prop; // Capture in closure
    Object.defineProperty( settings, prop, {
      get() {
        return this[ p ];
      },
      set( value ) {
        this[ p ] = value;
        updateValueEl();
        // Auto-disable aim smoothing when FOV is turned on
        if ( propName === 'fovCircle' && value === true ) {
          this.aimSmoothing = false;
        }
        saveSettings();
      }
    } );
  });

  // Populate Settings Tab with sliders

  // FOV Radius slider
  const fovSlider = fromHtml( `<div class="zui-slider-container">
    <div class="zui-slider-label">
      <span style="color: #e5e7eb;">FOV Radius</span>
      <span class="zui-slider-value">${settings.fovRadius}px</span>
    </div>
    <input type="range" min="50" max="400" value="${settings.fovRadius}" class="zui-slider" />
  </div>` );

  const fovSliderInput = fovSlider.querySelector( '.zui-slider' );
  const fovSliderValue = fovSlider.querySelector( '.zui-slider-value' );

  fovSliderInput.addEventListener( 'input', function() {
    settings.fovRadius = parseInt( fovSliderInput.value );
    fovSliderValue.innerText = fovSliderInput.value + 'px';
    saveSettings();
  });

  settingsContent.appendChild( fovSlider );

  // Aimbot Smoothing Speed slider
  const smoothSlider = fromHtml( `<div class="zui-slider-container">
    <div class="zui-slider-label">
      <span style="color: #e5e7eb;">Aimbot Smoothing Speed</span>
      <span class="zui-slider-value">${settings.aimSmoothingSpeed}%</span>
    </div>
    <input type="range" min="1" max="100" value="${settings.aimSmoothingSpeed}" class="zui-slider" />
  </div>` );

  const smoothSliderInput = smoothSlider.querySelector( '.zui-slider' );
  const smoothSliderValue = smoothSlider.querySelector( '.zui-slider-value' );

  smoothSliderInput.addEventListener( 'input', function() {
    settings.aimSmoothingSpeed = parseInt( smoothSliderInput.value );
    smoothSliderValue.innerText = smoothSliderInput.value + '%';
    saveSettings();
  });

  settingsContent.appendChild( smoothSlider );

  // Anti-Recoil Offset slider
  const recoilSlider = fromHtml( `<div class="zui-slider-container">
    <div class="zui-slider-label">
      <span style="color: #e5e7eb;">Aimbot Lock Offset</span>
      <span class="zui-slider-value">${settings.antiRecoilOffset.toFixed(1)}</span>
    </div>
    <input type="range" min="0" max="20" step="0.1" value="${settings.antiRecoilOffset}" class="zui-slider" />
  </div>` );

  const recoilSliderInput = recoilSlider.querySelector( '.zui-slider' );
  const recoilSliderValue = recoilSlider.querySelector( '.zui-slider-value' );

  recoilSliderInput.addEventListener( 'input', function() {
    settings.antiRecoilOffset = parseFloat( recoilSliderInput.value );
    recoilSliderValue.innerText = parseFloat(recoilSliderInput.value).toFixed(1);
    saveSettings();
  });

  settingsContent.appendChild( recoilSlider );

  // Anti-Recoil Amount slider
  const recoilAmountSlider = fromHtml( `<div class="zui-slider-container">
    <div class="zui-slider-label">
      <span style="color: #e5e7eb;">Anti-Recoil Strength</span>
      <span class="zui-slider-value">${settings.antiRecoilAmount}</span>
    </div>
    <input type="range" min="0" max="10" value="${settings.antiRecoilAmount}" class="zui-slider" />
  </div>` );

  const recoilAmountSliderInput = recoilAmountSlider.querySelector( '.zui-slider' );
  const recoilAmountSliderValue = recoilAmountSlider.querySelector( '.zui-slider-value' );

  recoilAmountSliderInput.addEventListener( 'input', function() {
    settings.antiRecoilAmount = parseInt( recoilAmountSliderInput.value );
    recoilAmountSliderValue.innerText = recoilAmountSliderInput.value;
    saveSettings();
  });

  settingsContent.appendChild( recoilAmountSlider );

  // iPad Mode toggle
  const iPadModeItem = fromHtml( `<div class="zui-item">
    <span>iPad Mode</span>
    <span class="zui-item-value"></span>
  </div>` );
  const iPadValueEl = iPadModeItem.querySelector( '.zui-item-value' );

  function updateIPadModeValue() {
    const value = settings.iPadMode;
    iPadValueEl.innerText = value ? 'ON' : 'OFF';
    iPadValueEl.style.color = value ? '#10b981' : '#ef4444';
  }

  iPadModeItem.onclick = function() {
    settings.iPadMode = ! settings.iPadMode;
  }
  updateIPadModeValue();

  settingsContent.appendChild( iPadModeItem );

  const iPadP = `__iPadMode`;
  settings[ iPadP ] = settings.iPadMode;
  Object.defineProperty( settings, 'iPadMode', {
    get() {
      return this[ iPadP ];
    },
    set( value ) {
      this[ iPadP ] = value;
      updateIPadModeValue();
      saveSettings();
    }
  } );

  // Clear Settings button
  const clearSettingsButton = fromHtml( `<div class="zui-item" style="justify-content: center; background: rgba(239, 68, 68, 0.2); cursor: pointer; margin-top: 10px;">
    <span style="font-weight: 600; color: #ef4444;">🗑️ Clear Settings</span>
  </div>` );

  clearSettingsButton.onclick = function() {
    if (confirm('Are you sure you want to reset all settings to defaults?')) {
      clearSettings();
      // Refresh the page to reload with default settings
      location.reload();
    }
  };

  settingsContent.appendChild( clearSettingsButton );

  // Unban button
  const unbanButton = fromHtml( `<div class="zui-item" style="justify-content: center; background: rgba(59, 130, 246, 0.2); cursor: pointer; margin-top: 10px;">
    <span style="font-weight: 600; color: #3b82f6;">🔓 Unban</span>
  </div>` );

  unbanButton.onclick = function() {
    if (confirm('Clear all cookies and storage to remove ban? The page will reload.')) {
      unban();
      // Refresh the page
      location.reload();
    }
  };

  settingsContent.appendChild( unbanButton );

  // Config Keybinds button
  const keybindsButton = fromHtml( `<div class="zui-item" style="justify-content: center;">
    <span style="font-weight: 600;">⌨️ Config Keybinds</span>
  </div>` );

  keybindsButton.onclick = function() {
    tabs.forEach( t => t.classList.remove('active') );
    tabContents.forEach( tc => tc.classList.remove('active') );
    keybindsTab.classList.add('active');
    keybindsContent.classList.add('active');
  };

  settingsContent.appendChild( keybindsButton );

  // Populate Keybinds Tab
  const backButton = fromHtml( `<div class="zui-item" style="justify-content: center; background: rgba(30, 30, 30, 0.9); cursor: pointer; font-weight: 600;">
    <span>← Back to Settings</span>
  </div>` );

  backButton.onclick = function() {
    tabs.forEach( t => t.classList.remove('active') );
    tabContents.forEach( tc => tc.classList.remove('active') );
    tabs[1].classList.add('active'); // Settings tab
    settingsContent.classList.add('active');
  };

  keybindsContent.appendChild( backButton );

  addSectionHeader(keybindsContent, 'Configure Keybinds');

  const keybindSettings = [
    { key: 'aimbotEnabled', label: 'Aimbot Enabled' },
    { key: 'aimbotOnRightMouse', label: 'Aimbot On Right Mouse' },
    { key: 'aimSmoothing', label: 'Aim Smoothing' },
    { key: 'antiRecoil', label: 'Anti Recoil' },
    { key: 'teamCheck', label: 'Team Check' },
    { key: 'espEnabled', label: 'ESP Enabled' },
    { key: 'espLines', label: 'ESP Lines' },
    { key: 'wireframe', label: 'Wireframe' },
    { key: 'fovCircle', label: 'FOV Circle' },
    { key: 'rightMouseAimbot', label: 'Right Mouse Aimbot Trigger' }
  ];

  keybindSettings.forEach(setting => {
    const defaultKey = defaultKeybinds[setting.key] || 'None';
    const currentKey = customKeybinds[setting.key] || 'None';

    const keybindItem = fromHtml( `<div class="zui-item" style="cursor: default;">
      <span>${setting.label} <span style="color: rgba(140, 140, 150, 0.7); font-size: 11px;">(${defaultKey})</span></span>
      <span class="zui-item-value keybind-value" data-setting="${setting.key}" style="cursor: pointer; min-width: 80px; text-align: center; background: rgba(60, 60, 70, 0.5); padding: 6px 12px; border-radius: 4px;">
        ${currentKey}
      </span>
    </div>` );

    const valueEl = keybindItem.querySelector('.keybind-value');

    valueEl.onclick = function(e) {
      e.stopPropagation();
      const originalValue = valueEl.innerText;
      valueEl.innerText = 'Press key...';
      valueEl.style.color = '#fbbf24';
      valueEl.style.background = 'rgba(251, 191, 36, 0.2)';

      const keyHandler = function(event) {
        event.preventDefault();
        event.stopPropagation();
        const newKey = event.code;
        customKeybinds[setting.key] = newKey;
        valueEl.innerText = newKey;
        valueEl.style.color = '#10b981';
        valueEl.style.background = 'rgba(16, 185, 129, 0.2)';

        window.removeEventListener('keydown', keyHandler);

        // Reset color after a moment
        setTimeout(() => {
          valueEl.style.color = '#e5e7eb';
          valueEl.style.background = 'rgba(60, 60, 70, 0.5)';
        }, 1000);
      };

      const escHandler = function(event) {
        if (event.code === 'Escape') {
          event.preventDefault();
          valueEl.innerText = originalValue;
          valueEl.style.color = '#e5e7eb';
          valueEl.style.background = 'rgba(60, 60, 70, 0.5)';
          window.removeEventListener('keydown', keyHandler);
          window.removeEventListener('keydown', escHandler);
        }
      };

      window.addEventListener('keydown', keyHandler, { once: true });
      window.addEventListener('keydown', escHandler);
    };

    keybindsContent.appendChild( keybindItem );
  });

  // Reset button at bottom
  const resetButton = fromHtml( `<div class="zui-item" style="justify-content: center; background: rgba(220, 80, 80, 0.3); margin-top: 10px; border: 1px solid rgba(220, 80, 80, 0.5);">
    <span style="font-weight: 600; color: rgb(220, 80, 80);">🔄 Reset to Defaults</span>
  </div>` );

  resetButton.onclick = function() {
    Object.keys(defaultKeybinds).forEach(key => {
      customKeybinds[key] = defaultKeybinds[key];
    });

    // Update all keybind displays
    keybindsContent.querySelectorAll('.keybind-value').forEach(el => {
      const settingKey = el.getAttribute('data-setting');
      el.innerText = customKeybinds[settingKey] || 'None';
      el.style.color = '#10b981';
      el.style.background = 'rgba(16, 185, 129, 0.2)';

      setTimeout(() => {
        el.style.color = '#e5e7eb';
        el.style.background = 'rgba(60, 60, 70, 0.5)';
      }, 1000);
    });
  };

  keybindsContent.appendChild( resetButton );

  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[ 0 ];

}

function toggleSetting( key ) {

  settings[ key ] = ! settings[ key ];
  showMsg( fromCamel( key ), settings[ key ] );

}