Xianware

Krunker.io assistant

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.

ستحتاج إلى تثبيت إضافة مثل Stylus لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتتمكن من تثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

ستحتاج إلى تثبيت إضافة لإدارة أنماط المستخدم لتثبيت هذا النمط.

(لدي بالفعل مثبت أنماط للمستخدم، دعني أقم بتثبيته!)

// ==UserScript==
// @name         Xianware
// @namespace    http://tampermonkey.net/
// @version      8.2.1
// @description  Krunker.io assistant
// @author       simplexian
// @match        *://krunker.io/*
// @exclude      *://krunker.io/social*
// @exclude      *://krunker.io/editor*
// @exclude      *://krunker.io/viewer*
// @icon         https://iili.io/qNroOue.png
// @grant        none
// @run-at       document-start
// @license      MIT
// @require      https://unpkg.com/[email protected]/build/three.min.js
// ==/UserScript==

(function () {
  "use strict";

  let THREE, MathUtils;
  try {
    THREE = window.THREE;
    MathUtils = THREE.MathUtils;
    delete window.THREE;
  } catch (e) {
    console.error("[Xianware] Error initializing THREE.js:", e);
  }

  class ConfigManager {
    constructor() {
      this.defaultSettings = {
        aimbotEnabled: true,
        aimbotOnRightMouse: false,
        smoothAim: true,
        horizontalFreeAim: true,
        verticalFreeAim: true,
        aimOffset: 0.75,
        aimHorizontal: true,
        aimVertical: true,
        wallCheck: true,
        aimSpeedXMin: 0.15,
        aimSpeedXMax: 0.3,
        aimSpeedYMin: 0.15,
        aimSpeedYMax: 0.3,
        aimPrediction: false,
        predictionFactor: 1.0,
        fovCheck: true,
        fovRadius: 150,
        fovCircleColor: "#ffffff",
        drawFov: true,
        targetIndicator: true,
        indicatorShape: "Arrow",
        indicatorColor: "#ff0000",
        indicatorSize: 15,
        indicatorOpacity: 1.0,
        indicatorImageUrl: "",
        espEnabled: true,
        espRainbow: false,
        espColor: "#fbc02d",
        espSnaplines: false,
        snaplineColor: "#ffffff",
        snaplineOrigin: "Bottom",
        espDistance: false,
        espDistanceColor: "#ffffff",
        chamsEnabled: false,
        chamsRainbow: false,
        chamsColor: "#ff0000",
        menuTheme: "Dark",
        menuScale: 1.0,
        menuColor: "#fbc02d",
        showNotifications: true,
        showHud: true,
        hudScale: 1.0,
        hudPosition: "Top Left",
        customCssText: "",
      };

      this.defaultKeybinds = {
        menuToggle: "Insert",
        aimbotEnabled: "KeyB",
        drawFov: "KeyG",
        espEnabled: "KeyV",
        espSnaplines: "",
        chamsEnabled: "",
        wallCheck: "",
        reloadScript: "KeyZ",
        showNotifications: "",
        showHud: "",
      };

      this.settings = JSON.parse(JSON.stringify(this.defaultSettings));
      this.keybinds = JSON.parse(JSON.stringify(this.defaultKeybinds));

      this.profiles = {
        Default: {
          settings: JSON.parse(JSON.stringify(this.defaultSettings)),
          keybinds: JSON.parse(JSON.stringify(this.defaultKeybinds)),
          hotkey: "",
        },
      };
      this.activeProfile = "Default";
      this.autoLoadProfile = "Default";

      this.reverseKeyMap = {};
      this.profileKeyMap = {};

      this.load();
    }

    updateKeyMaps() {
      this.reverseKeyMap = {};
      for (const [feat, key] of Object.entries(this.keybinds)) {
        if (key) this.reverseKeyMap[key] = feat;
      }
      this.profileKeyMap = {};
      for (const [pName, pData] of Object.entries(this.profiles)) {
        if (pData.hotkey) this.profileKeyMap[pData.hotkey] = pName;
      }
    }

    save() {
      try {
        localStorage.setItem(
          "xian_profiles_v82",
          JSON.stringify(this.profiles),
        );
        localStorage.setItem("xian_autoload_profile_v82", this.autoLoadProfile);
        this.updateKeyMaps();
      } catch (e) {}
    }

    load() {
      try {
        let savedProfiles =
          JSON.parse(localStorage.getItem("xian_profiles_v82")) ||
          JSON.parse(localStorage.getItem("xian_profiles_v81")) ||
          JSON.parse(localStorage.getItem("xian_profiles_v8")) ||
          JSON.parse(localStorage.getItem("xian_profiles_v75"));

        if (savedProfiles) {
          this.profiles = savedProfiles;
        }

        this.autoLoadProfile =
          localStorage.getItem("xian_autoload_profile_v82") ||
          localStorage.getItem("xian_autoload_profile_v81") ||
          localStorage.getItem("xian_autoload_profile_v8") ||
          localStorage.getItem("xian_autoload_profile_v75") ||
          "Default";
        this.activeProfile = this.autoLoadProfile;

        if (!this.profiles[this.activeProfile]) {
          this.activeProfile = "Default";
          this.autoLoadProfile = "Default";
        }

        this.migrateProfiles();
        this.applyProfile(this.activeProfile);
      } catch (e) {}
    }

    migrateProfiles() {
      for (const pName of Object.keys(this.profiles)) {
        const prof = this.profiles[pName];
        if (prof.hotkey === undefined) prof.hotkey = "";
        if (!prof.settings) prof.settings = {};
        if (!prof.keybinds) prof.keybinds = {};
        for (const key of Object.keys(this.defaultSettings)) {
          if (prof.settings[key] === undefined)
            prof.settings[key] = this.defaultSettings[key];
        }
        for (const key of Object.keys(this.defaultKeybinds)) {
          if (prof.keybinds[key] === undefined)
            prof.keybinds[key] = this.defaultKeybinds[key];
        }
      }
    }

    applyProfile(name) {
      if (!this.profiles[name]) return;
      this.activeProfile = name;
      const prof = this.profiles[name];

      Object.keys(this.defaultSettings).forEach((k) => {
        this.settings[k] = prof.settings.hasOwnProperty(k)
          ? prof.settings[k]
          : this.defaultSettings[k];
      });
      Object.keys(this.defaultKeybinds).forEach((k) => {
        this.keybinds[k] = prof.keybinds.hasOwnProperty(k)
          ? prof.keybinds[k]
          : this.defaultKeybinds[k];
      });
      this.updateKeyMaps();
    }

    resetToDefault() {
      Object.keys(this.defaultSettings).forEach((k) => {
        this.settings[k] = this.defaultSettings[k];
      });
      Object.keys(this.defaultKeybinds).forEach((k) => {
        this.keybinds[k] = this.defaultKeybinds[k];
      });
    }
  }

  class UIManager {
    constructor(app) {
      this.app = app;
      this.config = app.config;
      this.canvas = null;
      this.ctx = null;
      this.gui = null;
      this.welcomeGui = null;
      this.hudEl = null;
      this.notificationEl = null;
      this.toastQueue = [];
      this.toastActive = false;
      this.toastTimer = null;
      this.bindingFeature = null;
      this.saveDebounce = null;

      this.menuStructure = this.buildMenuStructure();
    }

    init() {
      this.createCanvas();
      this.injectCSS();
      this.createDOM();
      this.attachEventListeners();
      this.refreshUI();

      window.addEventListener("resize", () => {
        this.canvas.width = window.innerWidth;
        this.canvas.height = window.innerHeight;
      });
    }

    createCanvas() {
      this.canvas = document.createElement("canvas");
      this.canvas.style.position = "fixed";
      this.canvas.style.top = "0";
      this.canvas.style.left = "0";
      this.canvas.style.width = "100%";
      this.canvas.style.height = "100%";
      this.canvas.style.pointerEvents = "none";
      this.canvas.style.zIndex = "999";
      document.documentElement.appendChild(this.canvas);
      this.ctx = this.canvas.getContext("2d", { alpha: true });
      this.canvas.width = window.innerWidth;
      this.canvas.height = window.innerHeight;
    }

    cleanKeyName(code) {
      return !code || code === ""
        ? "NONE"
        : code.replace("Key", "").replace("Digit", "");
    }

    showToast(text, stateText = "", duration = 1500) {
      if (!this.config.settings.showNotifications) return;
      this.toastQueue.push({ text, stateText, duration });
      if (!this.toastActive) this.processToastQueue();
    }

    processToastQueue() {
      if (this.toastQueue.length === 0) {
        this.toastActive = false;
        return;
      }
      this.toastActive = true;
      const { text, stateText, duration } = this.toastQueue.shift();
      this.notificationEl.innerHTML = `${text} <span>${stateText}</span>`;
      this.notificationEl.classList.add("show");
      clearTimeout(this.toastTimer);
      this.toastTimer = setTimeout(() => {
        this.notificationEl.classList.remove("show");
        setTimeout(() => this.processToastQueue(), 300);
      }, duration);
    }

    queueSave() {
      clearTimeout(this.saveDebounce);
      this.saveDebounce = setTimeout(() => {
        this.config.profiles[this.config.activeProfile].settings = JSON.parse(
          JSON.stringify(this.config.settings),
        );
        this.config.profiles[this.config.activeProfile].keybinds = JSON.parse(
          JSON.stringify(this.config.keybinds),
        );
        this.config.save();
      }, 2000);
    }

    applyTheme() {
      document.documentElement.setAttribute(
        "data-theme",
        this.config.settings.menuTheme.toLowerCase(),
      );
      document.documentElement.style.setProperty(
        "--accent-color",
        this.config.settings.menuColor,
      );
    }

    refreshUI() {
      this.applyTheme();
      this.updateHud();

      if (this.gui)
        this.gui.style.transform = `scale(${this.config.settings.menuScale})`;
      if (this.welcomeGui)
        this.welcomeGui.style.transform = `scale(${this.config.settings.menuScale})`;

      this.menuStructure.forEach((cat) =>
        cat.groups.forEach((group) =>
          group.items.forEach((item) => {
            const chk = document.getElementById(`chk-${item.id}`);
            const sld = document.getElementById(`sld-${item.id}`);
            const col = document.getElementById(`col-${item.id}`);
            const sel = document.getElementById(`sel-${item.id}`);
            const txt = document.getElementById(`txt-${item.id}`);
            const bind = document.getElementById(
              `bind-${item.bind || item.id}`,
            );

            if (chk) chk.checked = this.config.settings[item.id];
            if (sld) {
              sld.value = this.config.settings[item.id];
              const valEl = document.getElementById(`val-${item.id}`);
              if (valEl) valEl.innerText = this.config.settings[item.id];
            }
            if (col) col.value = this.config.settings[item.id];
            if (sel && item.id !== "profileSelect")
              sel.value = this.config.settings[item.id];
            if (txt && item.id !== "profileName" && item.id !== "configData")
              txt.value = this.config.settings[item.id] || "";

            if (
              item.type === "bind" &&
              this.config.keybinds[item.bind || item.id] !== undefined
            ) {
              if (bind)
                bind.innerText = this.cleanKeyName(
                  this.config.keybinds[item.bind || item.id] || "",
                );
            } else if (
              item.type === "customBind" &&
              item.id === "profileHotkey"
            ) {
              if (bind)
                bind.innerText = this.cleanKeyName(
                  this.config.profiles[this.config.activeProfile]?.hotkey || "",
                );
            }
          }),
        ),
      );

      this.updateProfileDropdown();
      this.app.engine.updateMaterials();
    }

    updateProfileDropdown() {
      const sel = document.getElementById("sel-profileSelect");
      if (!sel) return;
      sel.innerHTML = Object.keys(this.config.profiles)
        .map((p) => {
          const isActive = p === this.config.activeProfile ? " [ACTIVE]" : "";
          const isAuto = p === this.config.autoLoadProfile ? " [AUTO]" : "";
          const hk = this.config.profiles[p].hotkey
            ? ` [${this.cleanKeyName(this.config.profiles[p].hotkey)}]`
            : "";
          return `<option value="${p}">${p}${isActive}${isAuto}${hk}</option>`;
        })
        .join("");
      sel.value = this.config.activeProfile;
    }

    updateHud() {
      if (!this.hudEl) return;
      const s = this.config.settings;

      if (!s.showHud) {
        this.hudEl.style.display = "none";
        return;
      }

      this.hudEl.style.display = "flex";
      this.hudEl.style.transform = `scale(${s.hudScale})`;
      this.hudEl.style.top = "auto";
      this.hudEl.style.bottom = "auto";
      this.hudEl.style.left = "auto";
      this.hudEl.style.right = "auto";
      this.hudEl.style.alignItems = "flex-start";

      switch (s.hudPosition) {
        case "Top Left":
          this.hudEl.style.top = "15px";
          this.hudEl.style.left = "15px";
          this.hudEl.style.transformOrigin = "top left";
          break;
        case "Top Right":
          this.hudEl.style.top = "15px";
          this.hudEl.style.right = "15px";
          this.hudEl.style.alignItems = "flex-end";
          this.hudEl.style.transformOrigin = "top right";
          break;
        case "Bottom Left":
          this.hudEl.style.bottom = "15px";
          this.hudEl.style.left = "15px";
          this.hudEl.style.transformOrigin = "bottom left";
          break;
        case "Bottom Right":
          this.hudEl.style.bottom = "15px";
          this.hudEl.style.right = "15px";
          this.hudEl.style.alignItems = "flex-end";
          this.hudEl.style.transformOrigin = "bottom right";
          break;
      }

      const activeFeatures = [
        { name: "XianWare", active: true, color: s.menuColor, isTitle: true },
        { name: "Profile", state: `[${this.config.activeProfile}]` },
      ];

      if (s.aimbotEnabled)
        activeFeatures.push({
          name: "Aimbot",
          state: s.aimbotOnRightMouse ? "[ADS]" : "[ON]",
        });
      if (s.aimPrediction)
        activeFeatures.push({ name: "Prediction", state: "[ON]" });
      let freeAimState =
        s.horizontalFreeAim && s.verticalFreeAim
          ? "[H+V]"
          : s.horizontalFreeAim
            ? "[HORIZ]"
            : s.verticalFreeAim
              ? "[VERT]"
              : "";
      if (freeAimState)
        activeFeatures.push({ name: "Free-Aim", state: freeAimState });
      if (s.espEnabled)
        activeFeatures.push({
          name: "ESP",
          state: s.espRainbow ? "[RAINBOW]" : "[ON]",
        });
      if (s.espSnaplines)
        activeFeatures.push({ name: "Snaplines", state: "[ON]" });
      if (s.espDistance)
        activeFeatures.push({ name: "Distance", state: "[ON]" });
      if (s.chamsEnabled)
        activeFeatures.push({
          name: "Chams",
          state: s.chamsRainbow ? "[RAINBOW]" : "[ON]",
        });
      if (s.drawFov) activeFeatures.push({ name: "Draw FOV", state: "[ON]" });
      if (s.targetIndicator)
        activeFeatures.push({ name: "Target Ind.", state: "[ON]" });
      if (s.wallCheck)
        activeFeatures.push({ name: "Wall Check", state: "[ON]" });

      this.hudEl.innerHTML = activeFeatures
        .map((f) => {
          if (f.isTitle)
            return `<div class="hud-item title" style="color:${f.color}; font-size: 20px;">${f.name} <span style="font-size:12px;color:#fff;">V8.2.1</span></div>`;
          return `<div class="hud-item">${f.name} <span>${f.state}</span></div>`;
        })
        .join("");
    }

    injectCustomCss() {
      const existing = document.getElementById("xian-custom-css");
      if (existing) existing.remove();
      if (
        !this.config.settings.customCssText ||
        this.config.settings.customCssText.trim() === ""
      )
        return;
      const styleBlock = document.createElement("style");
      styleBlock.id = "xian-custom-css";
      styleBlock.innerHTML = this.config.settings.customCssText;
      document.documentElement.appendChild(styleBlock);
      this.showToast("Custom CSS", "APPLIED");
    }

    confirmAction(message) {
      return new Promise((resolve) => {
        const overlay = document.createElement("div");
        overlay.style.cssText =
          "position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.6);z-index:10000001;display:flex;justify-content:center;align-items:center;font-family:'Rajdhani',sans-serif;";
        overlay.innerHTML = `<div style="background:var(--bg-main);border:2px solid var(--border-light);border-radius:8px;padding:24px 32px;text-align:center;color:var(--text-main);min-width:300px;box-shadow:0 10px 40px rgba(0,0,0,0.8);"><div style="font-size:16px;font-weight:700;margin-bottom:20px;text-transform:uppercase;">${message}</div><div style="display:flex;gap:12px;justify-content:center;"><button class="xian-btn" id="xian-confirm-yes" style="width:auto;padding:8px 24px;border-color:#ff4444;color:#ff4444;">YES</button><button class="xian-btn" id="xian-confirm-no" style="width:auto;padding:8px 24px;">CANCEL</button></div></div>`;
        document.documentElement.appendChild(overlay);
        document.getElementById("xian-confirm-yes").onclick = () => {
          overlay.remove();
          resolve(true);
        };
        document.getElementById("xian-confirm-no").onclick = () => {
          overlay.remove();
          resolve(false);
        };
      });
    }

    btnSaveProfile() {
      this.config.profiles[this.config.activeProfile].settings = JSON.parse(
        JSON.stringify(this.config.settings),
      );
      this.config.profiles[this.config.activeProfile].keybinds = JSON.parse(
        JSON.stringify(this.config.keybinds),
      );
      this.config.save();
      this.updateProfileDropdown();
      this.showToast("Profile Saved", this.config.activeProfile.toUpperCase());
    }

    btnLoadProfile() {
      const sel = document.getElementById("sel-profileSelect");
      if (sel && this.config.profiles[sel.value]) {
        this.config.applyProfile(sel.value);
        this.refreshUI();
        this.injectCustomCss();
        this.showToast("Profile Loaded", sel.value.toUpperCase());
      }
    }

    btnCreateProfile() {
      const name = document.getElementById("txt-profileName").value.trim();
      if (!name) return this.showToast("Error", "NAME EMPTY");
      if (this.config.profiles[name]) return this.showToast("Error", "EXISTS");

      this.config.activeProfile = name;
      this.config.profiles[name] = {
        settings: JSON.parse(JSON.stringify(this.config.settings)),
        keybinds: JSON.parse(JSON.stringify(this.config.keybinds)),
        hotkey: "",
      };
      this.config.save();
      document.getElementById("txt-profileName").value = "";
      this.updateProfileDropdown();
      this.showToast("Profile Created", name.toUpperCase());
    }

    async btnDeleteProfile() {
      const sel = document.getElementById("sel-profileSelect");
      if (sel.value === "Default")
        return this.showToast("Error", "CANNOT DELETE DEFAULT");
      const confirmed = await this.confirmAction(
        `Delete profile "${sel.value}"?`,
      );
      if (!confirmed) return;
      delete this.config.profiles[sel.value];
      if (this.config.activeProfile === sel.value)
        this.config.applyProfile("Default");
      if (this.config.autoLoadProfile === sel.value)
        this.config.autoLoadProfile = "Default";
      this.config.save();
      this.updateProfileDropdown();
      this.refreshUI();
      this.showToast("Profile Deleted", sel.value.toUpperCase());
    }

    btnSetAutoLoad() {
      const sel = document.getElementById("sel-profileSelect");
      this.config.autoLoadProfile = sel.value;
      this.config.save();
      this.updateProfileDropdown();
      this.showToast("Auto-Load Set", sel.value.toUpperCase());
    }

    btnExportConfig() {
      const jsonStr = JSON.stringify(
        { settings: this.config.settings, keybinds: this.config.keybinds },
        null,
        2,
      );
      const txt = document.getElementById("txt-configData");
      if (txt) {
        txt.value = jsonStr;
        txt.select();
      }
      if (navigator.clipboard)
        navigator.clipboard
          .writeText(jsonStr)
          .catch(() => document.execCommand("copy"));
      else document.execCommand("copy");
      this.showToast("Config Exported", "COPIED TO CLIPBOARD");
    }

    btnImportConfig() {
      const txt = document.getElementById("txt-configData");
      try {
        const parsed = JSON.parse(txt.value.trim());
        if (parsed.settings)
          Object.assign(this.config.settings, parsed.settings);
        if (parsed.keybinds)
          Object.assign(this.config.keybinds, parsed.keybinds);
        this.refreshUI();
        this.showToast("Config Imported", "UNSAVED");
      } catch (e) {
        this.showToast("Import Error", "INVALID JSON");
      }
    }

    async btnResetSettings() {
      const confirmed = await this.confirmAction(
        "Reset all settings to default?",
      );
      if (!confirmed) return;
      this.config.resetToDefault();
      this.refreshUI();
      this.showToast("Current Profile Reset", "DEFAULT");
    }

    injectCSS() {
      const style = document.createElement("style");
      style.innerHTML = `
                @import url('https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;700&display=swap');
                :root { --accent-color: ${this.config.settings.menuColor}; }
                :root[data-theme="dark"] { --bg-main: rgba(20, 20, 20, 0.95); --text-main: #ffffff; --bg-header: rgba(10, 10, 10, 0.8); --text-muted: #dddddd; --bg-tab-hover: rgba(255, 255, 255, 0.08); --bg-group: rgba(0, 0, 0, 0.25); --border-light: rgba(255, 255, 255, 0.08); --bg-row: rgba(255, 255, 255, 0.03); --bg-row-hover: rgba(255, 255, 255, 0.07); --bg-input: #2a2a2a; --bg-input-dark: #1f1f1f; --border-input: #555; --text-input: #ffffff; --bg-tooltip: #1a1a1a; --bg-slider-track: #555; }
                :root[data-theme="light"] { --bg-main: rgba(240, 240, 240, 0.95); --text-main: #111111; --bg-header: rgba(220, 220, 220, 0.9); --text-muted: #333333; --bg-tab-hover: rgba(0, 0, 0, 0.05); --bg-group: rgba(255, 255, 255, 0.6); --border-light: rgba(0, 0, 0, 0.1); --bg-row: rgba(255, 255, 255, 0.4); --bg-row-hover: rgba(255, 255, 255, 0.8); --bg-input: #e8e8e8; --bg-input-dark: #dddddd; --border-input: #aaaaaa; --text-input: #111111; --bg-tooltip: #f5f5f5; --bg-slider-track: #bbbbbb; }
                #xian-ui { position: fixed; width: 440px; background: var(--bg-main); border-radius: 8px; box-shadow: 0 10px 40px rgba(0,0,0,0.8); color: var(--text-main); font-family: 'Rajdhani', sans-serif; z-index: 1000000; user-select: none; transform-origin: top left; transform: scale(${this.config.settings.menuScale}); border: 2px solid var(--border-light); }
                #xian-welcome { position: fixed; top: 20px; right: 20px; width: 320px; background: var(--bg-main); border-radius: 8px; box-shadow: 0 10px 40px rgba(0,0,0,0.8); color: var(--text-main); font-family: 'Rajdhani', sans-serif; z-index: 1000001; border: 2px solid var(--border-light); transform-origin: top right; transform: scale(${this.config.settings.menuScale}); }
                #xian-welcome a { color: var(--accent-color); text-decoration: underline; font-weight: bold; transition: 0.2s; }
                #xian-welcome a:hover { filter: brightness(1.2); }
                .xian-header { display: flex; flex-direction: column; background: var(--bg-header); border-radius: 8px 8px 0 0; cursor: grab; border-bottom: 2px solid var(--border-light); }
                .xian-header:active { cursor: grabbing; }
                .xian-header-top { display: flex; justify-content: space-between; align-items: flex-start; width: 100%; }
                .xian-brand-container { display: flex; align-items: center; gap: 10px; padding: 12px 15px 4px 15px; pointer-events: none; }
                .xian-brand-logo { width: 24px; height: 24px; border-radius: 4px; filter: drop-shadow(0 0 2px rgba(0,0,0,0.5)); }
                .xian-brand-text { font-size: 20px; font-weight: 700; color: var(--text-main); text-transform: uppercase; letter-spacing: 1px; }
                .xian-brand-text span { color: var(--accent-color); }
                .xian-tabs { display: flex; width: 100%; overflow: hidden; }
                .xian-tab { padding: 10px 10px; font-size: 14px; font-weight: 700; color: var(--text-muted); cursor: pointer; transition: 0.2s; border-bottom: 3px solid transparent; text-transform: uppercase; text-align: center; flex: 1; white-space: nowrap; }
                .xian-tab.active { color: var(--text-main); background: var(--bg-row); border-bottom: 3px solid var(--accent-color); }
                .xian-tab:hover:not(.active) { background: var(--bg-tab-hover); color: var(--text-main); }
                .xian-close { padding: 12px 16px; font-weight: 700; cursor: pointer; color: #ff4444; font-size: 15px; transition: 0.2s; border-radius: 0 8px 0 0; }
                .xian-close:hover { color: #ff6666; background: rgba(255,0,0,0.1); }
                .xian-content { padding: 15px; max-height: 500px; overflow-y: auto; }
                .xian-content::-webkit-scrollbar { width: 6px; }
                .xian-content::-webkit-scrollbar-thumb { background: var(--bg-input); border-radius: 3px; }
                .xian-tab-pane { display: none; }
                .xian-tab-pane.active { display: block; animation: fadeIn 0.2s; }
                @keyframes fadeIn { from { opacity: 0; transform: translateY(5px); } to { opacity: 1; transform: translateY(0); } }
                .xian-group { margin-bottom: 12px; background: var(--bg-group); border-radius: 6px; border: 1px solid var(--border-light); }
                .xian-group-header { padding: 8px 14px; background: transparent; font-size: 14px; font-weight: 700; color: var(--accent-color); text-transform: uppercase; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border-light); }
                .xian-group-content { padding: 8px 10px; }
                .xian-row { display: flex; justify-content: space-between; align-items: center; padding: 8px 10px; margin-bottom: 4px; background: var(--bg-row); border-radius: 4px; transition: background 0.2s; }
                .xian-row:hover { background: var(--bg-row-hover); }
                .xian-label { font-size: 15px; color: var(--text-main); font-weight: 600; text-transform: uppercase; display: flex; align-items: center; }
                .xian-info { display: inline-flex; justify-content: center; align-items: center; width: 16px; height: 16px; background: var(--border-light); border-radius: 50%; font-size: 11px; font-weight: bold; margin-left: 8px; cursor: help; color: var(--text-muted); position: relative; transition: 0.2s; }
                .xian-info:hover { background: var(--accent-color); color: #000; }
                .xian-info::after { content: attr(data-tooltip); position: absolute; bottom: 130%; left: 50%; transform: translateX(-50%); background: var(--bg-tooltip); color: var(--text-main); padding: 8px 12px; border-radius: 4px; font-size: 13px; white-space: normal; width: max-content; max-width: 220px; text-align: center; line-height: 1.3; opacity: 0; visibility: hidden; pointer-events: none; transition: 0.2s; border: 1px solid var(--border-input); box-shadow: 0 4px 10px rgba(0,0,0,0.5); z-index: 1000; font-weight: 600; font-family: sans-serif; text-transform: none; }
                .xian-info:hover::after { opacity: 1; visibility: visible; }
                .xian-controls { display: flex; align-items: center; gap: 12px; }
                .xian-switch { position: relative; display: inline-block; width: 40px; height: 22px; }
                .xian-switch input { opacity: 0; width: 0; height: 0; }
                .xian-slider { position: absolute; cursor: pointer; top: 0; left: 0; right: 0; bottom: 0; background-color: var(--bg-input-dark); transition: .3s; border-radius: 4px; }
                .xian-slider:before { position: absolute; content: ""; height: 14px; width: 14px; left: 4px; bottom: 4px; background-color: var(--text-muted); transition: .3s; border-radius: 2px; }
                input:checked + .xian-slider { background-color: var(--border-light); }
                input:checked + .xian-slider:before { transform: translateX(18px); background-color: var(--accent-color); box-shadow: 0 0 8px var(--accent-color); }
                .xian-bind { background: var(--bg-input); border: 1px solid var(--border-input); color: var(--text-main); padding: 4px 10px; border-radius: 4px; font-size: 13px; cursor: pointer; min-width: 60px; text-align: center; font-weight: 700; }
                .xian-bind:hover { border-color: var(--accent-color); color: var(--accent-color); }
                .xian-bind.active { border-color: var(--accent-color); color: var(--accent-color); animation: pulse 1s infinite; }
                .xian-btn { background: var(--bg-input); border: 1px solid var(--border-input); color: var(--text-main); padding: 6px 15px; border-radius: 4px; font-family: inherit; font-size: 14px; font-weight: 700; cursor: pointer; transition: 0.2s; width: 100%; text-transform: uppercase; }
                .xian-btn:hover { border-color: var(--accent-color); color: var(--accent-color); background: var(--bg-row-hover); }
                .xian-select { background: var(--bg-input); color: var(--text-input); border: 1px solid var(--border-input); padding: 4px 8px; border-radius: 4px; font-family: inherit; font-size: 14px; font-weight: 600; outline: none; cursor: pointer; }
                .xian-textarea, .xian-text { background: var(--bg-input-dark); border: 1px solid var(--border-input); color: var(--text-input); padding: 8px 12px; border-radius: 4px; font-family: monospace; font-size: 12px; outline: none; margin-top: 8px; box-sizing: border-box; width: 100%; }
                .xian-textarea { height: 120px; resize: vertical; white-space: pre-wrap; overflow-wrap: break-word; overflow-y: auto; }
                .xian-textarea:focus, .xian-text:focus, .xian-select:focus { border-color: var(--accent-color); }
                .xian-search { background: var(--bg-input-dark); border: 1px solid var(--border-input); color: var(--text-input); padding: 8px 12px; border-radius: 4px; font-family: 'Rajdhani', sans-serif; font-size: 14px; font-weight: 600; outline: none; box-sizing: border-box; width: 100%; margin-bottom: 10px; }
                .xian-search:focus { border-color: var(--accent-color); }
                .xian-search::placeholder { color: var(--text-muted); opacity: 0.6; }
                .range-container { width: 100%; padding: 5px 0; }
                input[type=range] { -webkit-appearance: none; width: 100%; background: transparent; }
                input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; height: 16px; width: 16px; border-radius: 4px; background: var(--accent-color); cursor: pointer; margin-top: -6px; }
                input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; background: var(--bg-slider-track); border-radius: 2px; }
                input[type="color"] { -webkit-appearance: none; border: none; width: 26px; height: 26px; background: none; cursor: pointer; }
                input[type="color"]::-webkit-color-swatch { border: 2px solid var(--border-input); border-radius: 4px; }
                .xian-footer { padding: 10px 15px; background: var(--bg-header); border-top: 2px solid var(--border-light); border-radius: 0 0 8px 8px; font-size: 13px; font-weight: 700; color: var(--text-muted); text-align: center; text-transform: uppercase; cursor: default; }
                .xian-footer span { color: var(--accent-color); }
                .xian-notification { position: fixed; top: 15px; left: 50%; transform: translateX(-50%) translateY(-20px) scale(0.9); background: var(--bg-main); color: var(--text-main); padding: 10px 24px; border-radius: 6px; font-size: 14px; font-weight: 700; pointer-events: none; opacity: 0; z-index: 1000000; display: flex; align-items: center; box-shadow: 0 5px 20px rgba(0,0,0,0.5); border: 1px solid var(--border-light); transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275); text-transform: uppercase; }
                .xian-notification.show { transform: translateX(-50%) translateY(0) scale(1); opacity: 1; }
                .xian-notification span { color: var(--accent-color); margin-left: 8px; }
                #xian-hud { position: fixed; pointer-events: none; z-index: 999999; display: flex; flex-direction: column; gap: 4px; font-family: 'Rajdhani', sans-serif; text-transform: uppercase; font-weight: 700; text-shadow: 1px 1px 2px #000, -1px -1px 2px #000, 1px -1px 2px #000, -1px 1px 2px #000; }
                .hud-item { color: #fff; font-size: 16px; }
                .hud-item.title { margin-bottom: 5px; }
                .hud-item span { color: var(--accent-color); }
                @keyframes pulse { 0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; } }
            `;
      document.documentElement.appendChild(style);
    }

    createDOM() {
      this.gui = document.createElement("div");
      this.gui.id = "xian-ui";
      this.gui.style.left = `${window.innerWidth / 2 - 220}px`;
      this.gui.style.top = `${window.innerHeight / 2 - 200}px`;

      let tabsHtml = "",
        panesHtml = "";
      this.menuStructure.forEach((cat, index) => {
        const isActive = index === 0 ? "active" : "";
        const safeId = cat.title.replace(/\s+/g, "");
        tabsHtml += `<div class="xian-tab ${isActive}" data-target="${safeId}">${cat.title}</div>`;
        panesHtml += `<div class="xian-tab-pane ${isActive}" id="pane-${safeId}">`;

        cat.groups.forEach((group) => {
          panesHtml += `<div class="xian-group" data-group-name="${group.name}"><div class="xian-group-header">${group.name}</div><div class="xian-group-content">`;

          group.items.forEach((item) => {
            let labelHtml = item.tooltip
              ? `<span class="xian-label">${item.name}<span class="xian-info" data-tooltip="${item.tooltip}">?</span></span>`
              : `<span class="xian-label">${item.name}</span>`;
            let controlsHtml = "";

            if (item.type === "slider") {
              panesHtml += `<div class="xian-row" data-item-id="${item.id}" data-search-name="${item.name.toLowerCase()}" data-search-tip="${(item.tooltip || "").toLowerCase()}" style="flex-direction: column; align-items: flex-start;"><div style="display:flex; justify-content:space-between; width:100%; margin-bottom:5px;">${labelHtml}<span class="xian-label" id="val-${item.id}" style="color:var(--accent-color);">${this.config.settings[item.id]}</span></div><div class="range-container"><input type="range" id="sld-${item.id}" min="${item.min}" max="${item.max}" step="${item.step}" value="${this.config.settings[item.id]}"></div></div>`;
            } else if (item.type === "textarea" || item.type === "text") {
              const tag = item.type === "textarea" ? "textarea" : "input";
              const typeAttr = item.type === "text" ? 'type="text"' : "";
              panesHtml += `<div class="xian-row" data-item-id="${item.id}" data-search-name="${item.name.toLowerCase()}" data-search-tip="${(item.tooltip || "").toLowerCase()}" style="flex-direction: column; align-items: flex-start;">${labelHtml}<${tag} ${typeAttr} id="txt-${item.id}" class="xian-${item.type}" placeholder="${item.placeholder || ""}">${item.type === "textarea" ? this.config.settings[item.id] || "" : ""}</${tag}></div>`;
            } else if (item.type === "button") {
              const bindHtml = item.bind
                ? `<div class="xian-bind" id="bind-${item.bind}" data-key="${item.bind}">${this.cleanKeyName(this.config.keybinds[item.bind])}</div>`
                : "";
              panesHtml += `<div class="xian-row" data-item-id="${item.id}" data-search-name="${item.name.toLowerCase()}" data-search-tip="${(item.tooltip || "").toLowerCase()}">${labelHtml}<div class="xian-controls">${bindHtml}<button class="xian-btn" id="btn-${item.id}" style="width: auto; padding: 4px 12px; margin-left: ${item.bind ? "5px" : "0"};">EXECUTE</button></div></div>`;
            } else {
              if (item.type === "checkbox") {
                const bindHtml = item.bind
                  ? `<div class="xian-bind" id="bind-${item.bind}" data-key="${item.bind}">${this.cleanKeyName(this.config.keybinds[item.bind])}</div>`
                  : "";
                controlsHtml = `${bindHtml}<label class="xian-switch"><input type="checkbox" id="chk-${item.id}" ${this.config.settings[item.id] ? "checked" : ""}><span class="xian-slider"></span></label>`;
              } else if (item.type === "color") {
                controlsHtml = `<input type="color" id="col-${item.id}" value="${this.config.settings[item.id]}">`;
              } else if (item.type === "select") {
                controlsHtml = `<select class="xian-select" id="sel-${item.id}">${item.options.map((opt) => `<option value="${opt}" ${this.config.settings[item.id] === opt ? "selected" : ""}>${opt}</option>`).join("")}</select>`;
              } else if (item.type === "bind" || item.type === "customBind") {
                controlsHtml = `<div class="xian-bind" id="bind-${item.bind || item.id}" data-key="${item.bind || item.id}">${this.cleanKeyName(item.id === "profileHotkey" ? this.config.profiles[this.config.activeProfile]?.hotkey : this.config.keybinds[item.bind])}</div>`;
              }
              panesHtml += `<div class="xian-row" data-item-id="${item.id}" data-search-name="${item.name.toLowerCase()}" data-search-tip="${(item.tooltip || "").toLowerCase()}">${labelHtml}<div class="xian-controls">${controlsHtml}</div></div>`;
            }
          });
          panesHtml += `</div></div>`;
        });
        panesHtml += `</div>`;
      });

      this.gui.innerHTML = `<div class="xian-header"><div class="xian-header-top"><div class="xian-brand-container"><img src="https://iili.io/qNroOue.png" class="xian-brand-logo" alt="logo"><div class="xian-brand-text">Xian<span>ware</span></div></div><div class="xian-close">✖</div></div><div class="xian-tabs">${tabsHtml}</div></div><div class="xian-content"><input type="text" id="xian-search" class="xian-search" placeholder="Search settings...">${panesHtml}</div><div class="xian-footer">Xianware V8.2.1 • Made with love by <span>simplexian</span></div>`;
      document.documentElement.appendChild(this.gui);

      this.gui.addEventListener("mousedown", (e) => e.stopPropagation());
      this.gui.addEventListener("wheel", (e) => e.stopPropagation());

      this.welcomeGui = document.createElement("div");
      this.welcomeGui.id = "xian-welcome";
      this.welcomeGui.innerHTML = `<div class="xian-header" style="justify-content: space-between; padding: 10px 14px; cursor: default; flex-direction: row; align-items: center;"><span style="font-weight: 700; color: var(--accent-color); text-transform: uppercase;">Xianware Announcement</span><div id="xian-welcome-close" class="xian-close" style="padding: 5px 10px; border-radius: 4px; font-size: 14px;">✖</div></div><div style="padding: 16px; font-size: 15px; line-height: 1.5; color: var(--text-main); font-weight: 600;">Join the official discord server at <a href="https://discord.gg/Jg6V3e6euj" target="_blank">https://discord.gg/Jg6V3e6euj</a> for the latest version / early access of the new update!<div id="xian-welcome-timer" style="margin-top: 14px; font-size: 13px; color: var(--text-muted); text-align: right; font-weight: 700; text-transform: uppercase;">Auto-closing in 30s...</div></div>`;
      document.documentElement.appendChild(this.welcomeGui);

      this.hudEl = document.createElement("div");
      this.hudEl.id = "xian-hud";
      document.documentElement.appendChild(this.hudEl);

      this.notificationEl = document.createElement("div");
      this.notificationEl.className = "xian-notification";
      document.documentElement.appendChild(this.notificationEl);
    }

    attachEventListeners() {
      const head = this.gui.querySelector(".xian-header");
      let initLeft, initTop, startX, startY;
      const onDragMove = (e) => {
        let newLeft = initLeft + (e.clientX - startX);
        let newTop = initTop + (e.clientY - startY);
        const scale = this.config.settings.menuScale;
        const h = 40 * scale;
        newLeft = Math.max(-360, Math.min(window.innerWidth - 80, newLeft));
        newTop = Math.max(0, Math.min(window.innerHeight - h, newTop));
        this.gui.style.left = `${newLeft}px`;
        this.gui.style.top = `${newTop}px`;
      };
      const onDragUp = () => {
        window.removeEventListener("mousemove", onDragMove);
        window.removeEventListener("mouseup", onDragUp);
        head.style.cursor = "grab";
      };
      head.addEventListener("mousedown", (e) => {
        if (
          e.target.classList.contains("xian-tab") ||
          e.target.classList.contains("xian-close")
        )
          return;
        startX = e.clientX;
        startY = e.clientY;
        initLeft = this.gui.offsetLeft;
        initTop = this.gui.offsetTop;
        head.style.cursor = "grabbing";
        window.addEventListener("mousemove", onDragMove);
        window.addEventListener("mouseup", onDragUp);
      });

      this.gui.querySelector(".xian-close").onclick = () =>
        (this.gui.style.display = "none");
      const tabs = this.gui.querySelectorAll(".xian-tab"),
        panes = this.gui.querySelectorAll(".xian-tab-pane");
      tabs.forEach((tab) =>
        tab.addEventListener("click", () => {
          tabs.forEach((t) => t.classList.remove("active"));
          panes.forEach((p) => p.classList.remove("active"));
          tab.classList.add("active");
          document
            .getElementById(`pane-${tab.dataset.target}`)
            .classList.add("active");
        }),
      );

      let wTimeLeft = 30;
      const wTimerText = document.getElementById("xian-welcome-timer");
      const wInterval = setInterval(() => {
        wTimeLeft--;
        if (wTimerText)
          wTimerText.innerText = `Auto-closing in ${wTimeLeft}s...`;
        if (wTimeLeft <= 0) {
          clearInterval(wInterval);
          if (this.welcomeGui) this.welcomeGui.remove();
        }
      }, 1000);
      document.getElementById("xian-welcome-close").onclick = () => {
        clearInterval(wInterval);
        this.welcomeGui.remove();
      };

      const searchInput = document.getElementById("xian-search");
      if (searchInput) {
        searchInput.addEventListener("input", (e) => {
          const query = e.target.value.toLowerCase().trim();
          const allRows = this.gui.querySelectorAll(".xian-row[data-item-id]");
          const allGroups = this.gui.querySelectorAll(".xian-group");

          allRows.forEach((row) => {
            const name = row.getAttribute("data-search-name") || "";
            const tip = row.getAttribute("data-search-tip") || "";
            const matches =
              !query || name.includes(query) || tip.includes(query);
            row.style.display = matches ? "" : "none";
          });

          allGroups.forEach((group) => {
            const visibleRows = group.querySelectorAll(
              '.xian-row[data-item-id]:not([style*="display: none"])',
            );
            group.style.display =
              !query || visibleRows.length > 0 ? "" : "none";
          });

          if (query) {
            panes.forEach((p) => p.classList.add("active"));
            tabs.forEach((t) => t.classList.add("active"));
          } else {
            panes.forEach((p) => p.classList.remove("active"));
            tabs.forEach((t) => t.classList.remove("active"));
            tabs[0].classList.add("active");
            panes[0].classList.add("active");
          }
        });
      }

      this.menuStructure.forEach((cat) =>
        cat.groups.forEach((group) =>
          group.items.forEach((item) => {
            const el =
              document.getElementById(`chk-${item.id}`) ||
              document.getElementById(`sld-${item.id}`) ||
              document.getElementById(`col-${item.id}`) ||
              document.getElementById(`sel-${item.id}`) ||
              document.getElementById(`txt-${item.id}`);
            if (el) {
              el.addEventListener(
                item.type === "slider" ||
                  item.type === "color" ||
                  item.type === "textarea" ||
                  item.type === "text"
                  ? "input"
                  : "change",
                (e) => {
                  if (
                    item.id === "configData" ||
                    item.id === "profileSelect" ||
                    item.id === "profileName"
                  )
                    return;
                  this.config.settings[item.id] =
                    item.type === "checkbox"
                      ? e.target.checked
                      : item.type === "slider"
                        ? parseFloat(e.target.value)
                        : e.target.value;
                  if (item.type === "slider") {
                    const valEl = document.getElementById(`val-${item.id}`);
                    if (valEl) valEl.innerText = this.config.settings[item.id];
                  }
                  if (item.id === "menuScale") {
                    this.gui.style.transform = `scale(${this.config.settings.menuScale})`;
                    if (this.welcomeGui)
                      this.welcomeGui.style.transform = `scale(${this.config.settings.menuScale})`;
                  }
                  if (item.id === "menuTheme" || item.id === "menuColor")
                    this.applyTheme();
                  if (item.type !== "textarea" && item.type !== "text")
                    this.updateHud();
                  this.app.engine.updateMaterials();
                  this.queueSave();
                },
              );
            }

            const btnMap = {
              loadCss: () => this.injectCustomCss(),
              reloadScript: () => this.app.engine.reset(),
              resetSettings: () => this.btnResetSettings(),
              loadProfile: () => this.btnLoadProfile(),
              saveProfile: () => this.btnSaveProfile(),
              deleteProfile: () => this.btnDeleteProfile(),
              setAutoLoad: () => this.btnSetAutoLoad(),
              createProfile: () => this.btnCreateProfile(),
              exportConfig: () => this.btnExportConfig(),
              importConfig: () => this.btnImportConfig(),
            };
            if (item.type === "button" && btnMap[item.id]) {
              const btnEl = document.getElementById(`btn-${item.id}`);
              if (btnEl) btnEl.onclick = btnMap[item.id];
            }

            if (
              item.bind ||
              item.type === "bind" ||
              item.type === "customBind"
            ) {
              const bindBtn = document.getElementById(
                `bind-${item.bind || item.id}`,
              );
              if (bindBtn)
                bindBtn.addEventListener("click", () => {
                  if (this.bindingFeature) return;
                  this.bindingFeature = item.bind || item.id;
                  bindBtn.classList.add("active");
                  bindBtn.innerText = "...";
                  this.showToast("Press key to bind", item.name);
                });
            }
          }),
        ),
      );
    }

    buildMenuStructure() {
      return [
        {
          title: "Combat",
          groups: [
            {
              name: "Aimbot",
              items: [
                {
                  id: "aimbotEnabled",
                  name: "Enable Aimbot",
                  type: "checkbox",
                  bind: "aimbotEnabled",
                  tooltip: "Automatically aims at enemies.",
                },
                {
                  id: "aimbotOnRightMouse",
                  name: "Aim on ADS",
                  type: "checkbox",
                  tooltip: "Only aims when holding the right mouse button.",
                },
                {
                  id: "aimOffset",
                  name: "Aim Height",
                  type: "slider",
                  min: 0.0,
                  max: 1.0,
                  step: 0.05,
                  tooltip:
                    "Where to aim. 0 = Feet, 0.5 = Chest, 0.75 = Head, 1.0 = Top of Head.",
                },
                {
                  id: "wallCheck",
                  name: "Visible Only",
                  type: "checkbox",
                  bind: "wallCheck",
                  tooltip: "Won't aim at enemies hidden behind walls.",
                },
                {
                  id: "aimPrediction",
                  name: "Aim Prediction",
                  type: "checkbox",
                  tooltip: "Leads targets based on their movement velocity.",
                },
                {
                  id: "predictionFactor",
                  name: "Prediction Strength",
                  type: "slider",
                  min: 0.1,
                  max: 3.0,
                  step: 0.1,
                  tooltip: "How far ahead to predict movement.",
                },
              ],
            },
            {
              name: "Aim Smoothing",
              items: [
                {
                  id: "smoothAim",
                  name: "Smooth Aiming",
                  type: "checkbox",
                  tooltip: "Makes aiming look more natural and human-like.",
                },
                {
                  id: "aimHorizontal",
                  name: "Horizontal Lock",
                  type: "checkbox",
                  tooltip: "Allows the aimbot to move left and right.",
                },
                {
                  id: "aimSpeedXMin",
                  name: "Min X Speed",
                  type: "slider",
                  min: 0.01,
                  max: 1.0,
                  step: 0.01,
                  tooltip: "Minimum horizontal aiming speed.",
                },
                {
                  id: "aimSpeedXMax",
                  name: "Max X Speed",
                  type: "slider",
                  min: 0.01,
                  max: 1.0,
                  step: 0.01,
                  tooltip: "Maximum horizontal aiming speed.",
                },
                {
                  id: "aimVertical",
                  name: "Vertical Lock",
                  type: "checkbox",
                  tooltip: "Allows the aimbot to move up and down.",
                },
                {
                  id: "aimSpeedYMin",
                  name: "Min Y Speed",
                  type: "slider",
                  min: 0.01,
                  max: 1.0,
                  step: 0.01,
                  tooltip: "Minimum vertical aiming speed.",
                },
                {
                  id: "aimSpeedYMax",
                  name: "Max Y Speed",
                  type: "slider",
                  min: 0.01,
                  max: 1.0,
                  step: 0.01,
                  tooltip: "Maximum vertical aiming speed.",
                },
              ],
            },
            {
              name: "Free-Aim Tracking",
              items: [
                {
                  id: "horizontalFreeAim",
                  name: "Horiz. Free-Aim",
                  type: "checkbox",
                  tooltip: "Allows manual horizontal movement while locked on.",
                },
                {
                  id: "verticalFreeAim",
                  name: "Vert. Free-Aim",
                  type: "checkbox",
                  tooltip:
                    "Allows manual vertical movement without breaking lock.",
                },
              ],
            },
            {
              name: "FOV Rules",
              items: [
                {
                  id: "drawFov",
                  name: "Show FOV Circle",
                  type: "checkbox",
                  bind: "drawFov",
                  tooltip: "Draws a circle to show the aimbot range.",
                },
                {
                  id: "fovRadius",
                  name: "FOV Size",
                  type: "slider",
                  min: 50,
                  max: 500,
                  step: 10,
                  tooltip: "How large the aimbot detection area is.",
                },
                {
                  id: "fovCircleColor",
                  name: "FOV Color",
                  type: "color",
                  tooltip: "Color of the FOV circle.",
                },
                {
                  id: "fovCheck",
                  name: "Require FOV",
                  type: "checkbox",
                  tooltip: "Only aims at enemies inside the FOV circle.",
                },
              ],
            },
          ],
        },
        {
          title: "Visuals",
          groups: [
            {
              name: "Player ESP",
              items: [
                {
                  id: "espEnabled",
                  name: "Enable ESP",
                  type: "checkbox",
                  bind: "espEnabled",
                  tooltip: "Draws a box around enemies so you can see them.",
                },
                {
                  id: "espRainbow",
                  name: "Rainbow ESP",
                  type: "checkbox",
                  tooltip: "Makes the ESP box constantly change colors.",
                },
                {
                  id: "espColor",
                  name: "ESP Color",
                  type: "color",
                  tooltip: "Choose a specific color for the ESP box.",
                },
                {
                  id: "espSnaplines",
                  name: "Snaplines",
                  type: "checkbox",
                  bind: "espSnaplines",
                  tooltip: "Draws lines from your screen to each enemy.",
                },
                {
                  id: "snaplineColor",
                  name: "Line Color",
                  type: "color",
                  tooltip: "Color of the snaplines.",
                },
                {
                  id: "snaplineOrigin",
                  name: "Line Origin",
                  type: "select",
                  options: ["Bottom", "Center", "Crosshair"],
                  tooltip: "Where the snapline starts on your screen.",
                },
                {
                  id: "espDistance",
                  name: "Show Distance",
                  type: "checkbox",
                  tooltip: "Displays the distance to each enemy in meters.",
                },
                {
                  id: "espDistanceColor",
                  name: "Distance Color",
                  type: "color",
                  tooltip: "Color of the distance text.",
                },
              ],
            },
            {
              name: "Player Chams",
              items: [
                {
                  id: "chamsEnabled",
                  name: "Enable Chams",
                  type: "checkbox",
                  bind: "chamsEnabled",
                  tooltip:
                    "Colors the enemy models so they are visible through walls.",
                },
                {
                  id: "chamsRainbow",
                  name: "Rainbow Chams",
                  type: "checkbox",
                  tooltip: "Makes the enemy models constantly change colors.",
                },
                {
                  id: "chamsColor",
                  name: "Chams Color",
                  type: "color",
                  tooltip: "Choose a specific color for the enemy models.",
                },
              ],
            },
            {
              name: "Target Indicator",
              items: [
                {
                  id: "targetIndicator",
                  name: "Show Marker",
                  type: "checkbox",
                  tooltip: "Draws a marker above the enemy currently targeted.",
                },
                {
                  id: "indicatorShape",
                  name: "Marker Shape",
                  type: "select",
                  options: ["Arrow", "Triangle", "Dot", "Image"],
                  tooltip: "The design of the target marker.",
                },
                {
                  id: "indicatorColor",
                  name: "Marker Color",
                  type: "color",
                  tooltip: "The color of the target marker.",
                },
                {
                  id: "indicatorSize",
                  name: "Marker Size",
                  type: "slider",
                  min: 5,
                  max: 100,
                  step: 1,
                  tooltip: "How big the target marker should be.",
                },
                {
                  id: "indicatorOpacity",
                  name: "Marker Opacity",
                  type: "slider",
                  min: 0.1,
                  max: 1.0,
                  step: 0.05,
                  tooltip:
                    "How transparent the target marker is (1 = solid, 0.1 = faint).",
                },
                {
                  id: "indicatorImageUrl",
                  name: "Custom Image URL",
                  type: "text",
                  placeholder: "https://example.com/image.png",
                  tooltip:
                    "Paste a direct link to an image (png/jpg) to use as the marker.",
                },
              ],
            },
          ],
        },
        {
          title: "System",
          groups: [
            {
              name: "Interface",
              items: [
                {
                  id: "menuToggle",
                  name: "Menu Key",
                  type: "bind",
                  bind: "menuToggle",
                  tooltip: "The keyboard key to open or close this menu.",
                },
                {
                  id: "menuTheme",
                  name: "UI Theme",
                  type: "select",
                  options: ["Dark", "Light"],
                  tooltip: "Switches the menu between Dark and Light mode.",
                },
                {
                  id: "menuColor",
                  name: "Menu Accent",
                  type: "color",
                  tooltip: "The main color used for buttons and active tabs.",
                },
                {
                  id: "menuScale",
                  name: "Menu Size",
                  type: "slider",
                  min: 0.5,
                  max: 1.5,
                  step: 0.1,
                  tooltip: "Adjusts how big the menu appears on your screen.",
                },
                {
                  id: "showHud",
                  name: "Enable HUD",
                  type: "checkbox",
                  bind: "showHud",
                  tooltip:
                    "Shows a small info box on screen with active features.",
                },
                {
                  id: "hudScale",
                  name: "HUD Size",
                  type: "slider",
                  min: 0.5,
                  max: 2.0,
                  step: 0.1,
                  tooltip: "Adjusts how big the HUD info box is.",
                },
                {
                  id: "hudPosition",
                  name: "HUD Location",
                  type: "select",
                  options: [
                    "Top Left",
                    "Top Right",
                    "Bottom Left",
                    "Bottom Right",
                  ],
                  tooltip: "Where the HUD is placed on your screen.",
                },
                {
                  id: "showNotifications",
                  name: "Notifications",
                  type: "checkbox",
                  bind: "showNotifications",
                  tooltip: "Shows small popup alerts when you toggle features.",
                },
              ],
            },
            {
              name: "Customization & Fixes",
              items: [
                {
                  id: "customCssText",
                  name: "Custom CSS",
                  type: "textarea",
                  placeholder:
                    "/* Paste CSS code here */\n.headerBar { display: none; }",
                  tooltip:
                    "Write your own CSS code to change how the game looks.",
                },
                {
                  id: "loadCss",
                  name: "Apply CSS",
                  type: "button",
                  tooltip: "Activates your custom CSS code immediately.",
                },
                {
                  id: "reloadScript",
                  name: "Reload Cheat",
                  type: "button",
                  bind: "reloadScript",
                  tooltip:
                    "Refreshes the cheat if it glitches or stops working.",
                },
                {
                  id: "resetSettings",
                  name: "Factory Reset",
                  type: "button",
                  tooltip:
                    "Restores all settings in the current profile back to default.",
                },
              ],
            },
          ],
        },
        {
          title: "Config",
          groups: [
            {
              name: "Profiles",
              items: [
                {
                  id: "profileSelect",
                  name: "Select Profile",
                  type: "select",
                  options: ["Default"],
                  tooltip: "Choose a saved profile from the list.",
                },
                {
                  id: "loadProfile",
                  name: "Load Profile",
                  type: "button",
                  tooltip: "Loads the settings of the selected profile.",
                },
                {
                  id: "saveProfile",
                  name: "Save Profile",
                  type: "button",
                  tooltip: "Saves your current settings to the active profile.",
                },
                {
                  id: "deleteProfile",
                  name: "Delete Profile",
                  type: "button",
                  tooltip: "Permanently removes the selected profile.",
                },
                {
                  id: "setAutoLoad",
                  name: "Set Startup Profile",
                  type: "button",
                  tooltip:
                    "Makes the selected profile load automatically when you join a game.",
                },
                {
                  id: "profileHotkey",
                  name: "Profile Hotkey",
                  type: "customBind",
                  bind: "profileHotkey",
                  tooltip:
                    "Assign a key to instantly switch to the active profile.",
                },
                {
                  id: "profileName",
                  name: "New Profile Name",
                  type: "text",
                  placeholder: "Enter new name...",
                  tooltip: "Type a name for your new settings profile.",
                },
                {
                  id: "createProfile",
                  name: "Create Profile",
                  type: "button",
                  tooltip:
                    "Creates a new profile with the name you typed above.",
                },
              ],
            },
            {
              name: "Data Management",
              items: [
                {
                  id: "configData",
                  name: "Config Data",
                  type: "textarea",
                  placeholder: "Paste config JSON here to import...",
                  tooltip:
                    "The raw text data of your settings. Use this to share or backup.",
                },
                {
                  id: "exportConfig",
                  name: "Copy to Clipboard",
                  type: "button",
                  tooltip:
                    "Copies your settings text so you can save it elsewhere.",
                },
                {
                  id: "importConfig",
                  name: "Load from Text",
                  type: "button",
                  tooltip: "Applies settings from the text you pasted above.",
                },
              ],
            },
          ],
        },
      ];
    }
  }

  class InputManager {
    constructor(app) {
      this.app = app;
      this.rightMouseDown = false;
    }

    init() {
      window.addEventListener("pointerdown", (e) => {
        if (e.button === 2) this.rightMouseDown = true;
      });
      window.addEventListener("pointerup", (e) => {
        if (e.button === 2) this.rightMouseDown = false;
      });

      window.addEventListener("keydown", (e) => {
        const ui = this.app.ui;
        const config = this.app.config;

        if (ui.bindingFeature) {
          e.preventDefault();
          e.stopPropagation();
          if (ui.bindingFeature === "profileHotkey") {
            const code = e.code === "Escape" ? "" : e.code;
            if (code !== "")
              for (let p in config.profiles)
                if (config.profiles[p].hotkey === code)
                  config.profiles[p].hotkey = "";
            config.profiles[config.activeProfile].hotkey = code;
            config.save();
            const btn = document.getElementById("bind-profileHotkey");
            if (btn) {
              btn.innerText = ui.cleanKeyName(code);
              btn.classList.remove("active");
            }
            ui.showToast("Profile Hotkey bound to", ui.cleanKeyName(code));
          } else {
            if (e.code === "Escape") {
              config.keybinds[ui.bindingFeature] = "";
              const btn = document.getElementById(`bind-${ui.bindingFeature}`);
              if (btn) {
                btn.innerText = "NONE";
                btn.classList.remove("active");
              }
              ui.showToast("Unbound feature", "");
            } else {
              config.keybinds[ui.bindingFeature] = e.code;
              const btn = document.getElementById(`bind-${ui.bindingFeature}`);
              if (btn) {
                btn.innerText = ui.cleanKeyName(e.code);
                btn.classList.remove("active");
              }
              ui.showToast("Bound to", ui.cleanKeyName(e.code));
            }
          }
          config.updateKeyMaps();
          ui.bindingFeature = null;
          return;
        }

        if (
          document.activeElement &&
          (document.activeElement.tagName === "INPUT" ||
            document.activeElement.tagName === "TEXTAREA")
        )
          return;

        if (config.profileKeyMap[e.code]) {
          const targetProfile = config.profileKeyMap[e.code];
          if (config.activeProfile !== targetProfile) {
            config.applyProfile(targetProfile);
            ui.refreshUI();
            ui.showToast("Profile Loaded", targetProfile.toUpperCase());
          }
          return;
        }

        const feature = config.reverseKeyMap[e.code];
        if (feature) {
          if (feature === "menuToggle") {
            if (ui.gui)
              ui.gui.style.display =
                ui.gui.style.display === "none" ? "block" : "none";
          } else if (feature === "reloadScript") {
            this.app.engine.reset();
          } else if (typeof config.settings[feature] === "boolean") {
            config.settings[feature] = !config.settings[feature];
            ui.updateHud();
            const chk = document.getElementById(`chk-${feature}`);
            if (chk) chk.checked = config.settings[feature];

            let displayName = feature;
            ui.menuStructure.forEach((cat) =>
              cat.groups.forEach((g) => {
                const item = g.items.find((i) => i.id === feature);
                if (item) displayName = item.name;
              }),
            );
            ui.showToast(displayName, config.settings[feature] ? "ON" : "OFF");
            ui.queueSave();
          }
        }
      });
    }
  }

  class Engine {
    constructor(app) {
      this.app = app;

      this.scene = null;
      this.gameCamera = null;
      this.cachedPlayers = [];
      this.mapMeshes = [];
      this.myPlayerCache = null;
      this.lastMapScrape = 0;
      this.lastNonPlayerCount = -1;
      this.lockedTarget = null;
      this.lastFrameTime = performance.now();
      this.canvasNeedsClear = false;

      this.hue = 0;
      this.cachedIndicatorImage = new Image();
      this.currentImageUrl = "";

      this.aimCandidates = [];
      this.nonPlayerObjects = [];

      this._pool = null;

      this.geometry = null;
      this.espMaterial = null;
      this.chamsMaterial = null;
      this.line = null;
      this.linePositions = null;

      this.originalPush = Array.prototype.push;
    }

    init() {
      if (!THREE) return;

      this._pool = {
        tempVec: new THREE.Vector3(),
        tempObj: new THREE.Object3D(),
        originVec: new THREE.Vector3(),
        destVec: new THREE.Vector3(),
        dirVec: new THREE.Vector3(),
        camPos: new THREE.Vector3(),
        centerVec: new THREE.Vector3(),
        topVec: new THREE.Vector3(),
        botVec: new THREE.Vector3(),
        targetVec: new THREE.Vector3(),
        raycaster: new THREE.Raycaster(),
        tempBox: new THREE.Box3(),
        localPos: new THREE.Vector3(),
        worldPos: new THREE.Vector3(),
        fallbackOffset: new THREE.Vector3(0, 5.5, 0),
        fallbackSize: new THREE.Vector3(3.5, 11, 3.5),
      };
      this._pool.tempObj.rotation.order = "YXZ";

      this.geometry = new THREE.EdgesGeometry(new THREE.BoxGeometry(1, 1, 1));

      this.espMaterial = new THREE.RawShaderMaterial({
        uniforms: {
          uColor: { value: new THREE.Color(this.app.config.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); }",
      });
      this.espMaterial.depthTest = false;
      this.espMaterial.depthWrite = false;
      this.espMaterial.transparent = true;

      this.line = new THREE.LineSegments(
        new THREE.BufferGeometry(),
        this.espMaterial,
      );
      this.line.frustumCulled = false;
      this.linePositions = new THREE.BufferAttribute(
        new Float32Array(100 * 2 * 3),
        3,
      );
      this.line.geometry.setAttribute("position", this.linePositions);

      this.chamsMaterial = new THREE.MeshBasicMaterial({
        color: new THREE.Color(this.app.config.settings.chamsColor),
        depthTest: false,
        depthWrite: false,
        transparent: true,
        opacity: 0.8,
      });

      this.hookArrayPush();
      this.renderLoop();
    }

    updateMaterials() {
      if (this.espMaterial)
        this.espMaterial.uniforms.uColor.value.set(
          this.app.config.settings.espColor,
        );
      if (this.chamsMaterial)
        this.chamsMaterial.color.set(this.app.config.settings.chamsColor);
    }

    hookArrayPush() {
      const self = this;
      const origPush = this.originalPush;
      if (Array.prototype.push === origPush) {
        Object.defineProperty(Array.prototype, "push", {
          configurable: true,
          enumerable: false,
          writable: true,
          value: function () {
            for (let i = 0; i < arguments.length; i++) {
              const obj = arguments[i];
              if (
                !self.scene &&
                obj &&
                typeof obj === "object" &&
                obj.parent &&
                obj.parent.type === "Scene" &&
                obj.parent.name === "Main"
              ) {
                self.scene = obj.parent;
                Object.defineProperty(Array.prototype, "push", {
                  configurable: true,
                  enumerable: false,
                  writable: true,
                  value: origPush,
                });
              }
            }
            return origPush.apply(this, arguments);
          },
        });
      }
    }

    reset() {
      this.scene = null;
      this.gameCamera = null;
      this.cachedPlayers.length = 0;
      this.mapMeshes.length = 0;
      this.myPlayerCache = null;
      this.lastMapScrape = 0;
      this.lastNonPlayerCount = -1;
      this.lockedTarget = null;
      this.hookArrayPush();
      this.app.ui.showToast("Cheat Reloaded", "SCANNING");
    }

    getPlayerHead(player) {
      try {
        const c0 = player?.children?.[0];
        const c00 = c0?.children?.[0];
        return c00 || null;
      } catch (e) {
        return null;
      }
    }

    renderLoop = () => {
      x.requestAnimationFrame.call(x.window, this.renderLoop);
      if (!THREE || !this.app.ui.ctx || !this._pool) return;

      const s = this.app.config.settings;
      const ctx = this.app.ui.ctx;
      const canvas = this.app.ui.canvas;

      let currentTime = performance.now();
      let delta = currentTime - this.lastFrameTime;
      if (delta > 100) delta = 16;
      this.lastFrameTime = currentTime;

      this.updateRainbow(s);
      this.updateIndicatorImage(s);

      let needs2D =
        s.drawFov || s.targetIndicator || s.espSnaplines || s.espDistance;
      if (needs2D || this.canvasNeedsClear) {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        this.canvasNeedsClear = needs2D;
      }

      if (s.drawFov) {
        ctx.beginPath();
        ctx.arc(
          canvas.width / 2,
          canvas.height / 2,
          s.fovRadius,
          0,
          2 * Math.PI,
        );
        ctx.strokeStyle = s.espRainbow
          ? `hsl(${this.hue}, 100%, 50%)`
          : s.fovCircleColor;
        ctx.lineWidth = 1.5;
        ctx.stroke();
      }

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

      this.scanScene(currentTime);

      if (!this.myPlayerCache || !this.gameCamera) return;

      const centerX = canvas.width / 2;
      const centerY = canvas.height / 2;
      const fovRadiusSq = s.fovRadius * s.fovRadius;

      const myHead = this.getPlayerHead(this.myPlayerCache);
      if (myHead) myHead.updateMatrixWorld(true);

      if (s.espEnabled)
        this._pool.tempObj.matrix.copy(this.myPlayerCache.matrix).invert();

      this.aimCandidates.length = 0;
      let counter = 0;

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

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

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

        player.visible = s.espEnabled || player.visible || s.chamsEnabled;
        player.box.visible = s.espEnabled;

        if (!player._xBox) player._xBox = new THREE.Box3();
        if (!player._xSize) player._xSize = new THREE.Vector3();
        if (!player._xCenter) player._xCenter = new THREE.Vector3();
        if (!player._xRawSize) player._xRawSize = new THREE.Vector3();
        if (!player._xRawCenter) player._xRawCenter = new THREE.Vector3();
        if (!player._xLastPos)
          player._xLastPos = new THREE.Vector3().copy(player.position);
        if (!player._xVelocity) player._xVelocity = new THREE.Vector3();

        player._xVelocity.copy(player.position).sub(player._xLastPos);
        player._xLastPos.copy(player.position);

        player._xBox.makeEmpty();
        let hasMesh = false;
        const applyChams = s.chamsEnabled;

        player.traverse((obj) => {
          if (!obj.isMesh || obj === player.box) return;
          if (!obj.visible) return;

          if (obj.geometry) {
            if (obj.geometry.boundingBox === null)
              obj.geometry.computeBoundingBox();
            this._pool.tempBox.copy(obj.geometry.boundingBox);
            this._pool.tempBox.applyMatrix4(obj.matrixWorld);
            player._xBox.union(this._pool.tempBox);
            hasMesh = true;
          }

          if (applyChams) {
            if (!obj.userData.originalMaterial)
              obj.userData.originalMaterial = obj.material;
            obj.material = this.chamsMaterial;
          } else if (
            obj.userData.originalMaterial &&
            obj.material === this.chamsMaterial
          ) {
            obj.material = obj.userData.originalMaterial;
          }
        });

        if (!hasMesh) {
          this._pool.tempVec
            .copy(player.position)
            .add(this._pool.fallbackOffset);
          player._xBox.setFromCenterAndSize(
            this._pool.tempVec,
            this._pool.fallbackSize,
          );
        }

        player._xBox.getSize(player._xRawSize);
        player._xBox.getCenter(player._xRawCenter);

        let tightBodyWidth = 3.5;
        player._xSize.set(tightBodyWidth, player._xRawSize.y, tightBodyWidth);
        player._xCenter.set(
          player.position.x,
          player._xRawCenter.y,
          player.position.z,
        );

        if (s.espEnabled) {
          player.box.scale.copy(player._xSize);
          this._pool.localPos.copy(player._xCenter);
          player.worldToLocal(this._pool.localPos);
          player.box.position.copy(this._pool.localPos);

          this.linePositions.setXYZ(counter++, 0, 10, -5);
          this._pool.tempVec
            .copy(player._xCenter)
            .applyMatrix4(this._pool.tempObj.matrix);
          this.linePositions.setXYZ(
            counter++,
            this._pool.tempVec.x,
            this._pool.tempVec.y,
            this._pool.tempVec.z,
          );
        }

        if (s.espSnaplines && this.gameCamera) {
          const head = this.getPlayerHead(player);
          if (head) {
            head.getWorldPosition(this._pool.worldPos);
            this._pool.worldPos.project(this.gameCamera);

            if (this._pool.worldPos.z < 1) {
              const sx = (this._pool.worldPos.x + 1) * centerX;
              const sy = (-this._pool.worldPos.y + 1) * centerY;

              let originX = centerX,
                originY;
              switch (s.snaplineOrigin) {
                case "Bottom":
                  originY = canvas.height;
                  break;
                case "Center":
                  originY = centerY;
                  break;
                case "Crosshair":
                  originY = centerY;
                  break;
                default:
                  originY = canvas.height;
              }

              ctx.beginPath();
              ctx.moveTo(originX, originY);
              ctx.lineTo(sx, sy);
              ctx.strokeStyle = s.espRainbow
                ? `hsl(${this.hue}, 100%, 50%)`
                : s.snaplineColor;
              ctx.lineWidth = 1;
              ctx.stroke();
            }
          }
        }

        if (s.espDistance && this.gameCamera) {
          this._pool.worldPos.copy(player._xCenter);
          this._pool.worldPos.y = player._xBox.min.y;
          this._pool.worldPos.project(this.gameCamera);

          if (this._pool.worldPos.z < 1) {
            const sx = (this._pool.worldPos.x + 1) * centerX;
            const sy = (-this._pool.worldPos.y + 1) * centerY;
            const dist = Math.sqrt(
              player.position.distanceToSquared(this.myPlayerCache.position),
            ).toFixed(0);

            ctx.font = "bold 13px Rajdhani";
            ctx.textAlign = "center";
            ctx.fillStyle = "#000";
            ctx.fillText(`${dist}m`, sx + 1, sy + 16);
            ctx.fillStyle = s.espDistanceColor;
            ctx.fillText(`${dist}m`, sx, sy + 15);
          }
        }

        if (s.aimbotEnabled) {
          let inFov = true;
          let distToCenterSq = 0;

          if (s.fovCheck) {
            const head = this.getPlayerHead(player);
            if (head) {
              head.getWorldPosition(this._pool.tempVec);
              this._pool.tempVec.project(this.gameCamera);
              const dx = (this._pool.tempVec.x + 1) * centerX - centerX;
              const dy = (-this._pool.tempVec.y + 1) * centerY - centerY;
              distToCenterSq = dx * dx + dy * dy;
              if (this._pool.tempVec.z > 1 || distToCenterSq > fovRadiusSq)
                inFov = false;
            } else {
              inFov = false;
            }
          }

          if (inFov) {
            this.aimCandidates.push({
              player: player,
              dist3D: player.position.distanceToSquared(
                this.myPlayerCache.position,
              ),
              distFOV: distToCenterSq,
            });
          }
        }
      }

      if (s.espEnabled) {
        this.linePositions.needsUpdate = true;
        this.line.geometry.setDrawRange(0, counter);
        this.line.visible = false;
      }

      const shouldAimbot =
        s.aimbotEnabled &&
        (!s.aimbotOnRightMouse || this.app.input.rightMouseDown);
      let targetPlayer = null;

      if (shouldAimbot && this.aimCandidates.length > 0) {
        if (s.fovCheck)
          this.aimCandidates.sort((a, b) => a.distFOV - b.distFOV);
        else this.aimCandidates.sort((a, b) => a.dist3D - b.dist3D);

        const checkWall = (candidate) => {
          if (!s.wallCheck || this.mapMeshes.length === 0) return true;
          if (
            candidate.lastWallCheckTime &&
            currentTime - candidate.lastWallCheckTime < 100
          )
            return candidate.isWallVisible;

          const myHead = this.getPlayerHead(this.myPlayerCache);
          const enemyHead = this.getPlayerHead(candidate);
          if (!myHead || !enemyHead) return false;

          myHead.getWorldPosition(this._pool.originVec);
          enemyHead.getWorldPosition(this._pool.destVec);

          const distToEnemy = this._pool.originVec.distanceTo(
            this._pool.destVec,
          );
          this._pool.dirVec
            .copy(this._pool.destVec)
            .sub(this._pool.originVec)
            .normalize();

          this._pool.raycaster.set(this._pool.originVec, this._pool.dirVec);
          this._pool.raycaster.far = distToEnemy;

          const intersects = this._pool.raycaster.intersectObjects(
            this.mapMeshes,
            false,
          );
          let isVisible = true;

          for (let j = 0; j < intersects.length; j++) {
            const hit = intersects[j].object;
            if (hit.visible && (!hit.material || hit.material.opacity > 0.5)) {
              isVisible = false;
              break;
            }
          }

          candidate.lastWallCheckTime = currentTime;
          candidate.isWallVisible = isVisible;
          return isVisible;
        };

        let lockedCandidate = this.lockedTarget
          ? this.aimCandidates.find((c) => c.player === this.lockedTarget)
          : null;

        if (lockedCandidate && checkWall(lockedCandidate.player)) {
          targetPlayer = this.lockedTarget;
        } else {
          for (let i = 0; i < this.aimCandidates.length; i++) {
            if (checkWall(this.aimCandidates[i].player)) {
              targetPlayer = this.aimCandidates[i].player;
              break;
            }
          }
          this.lockedTarget = targetPlayer;
        }
      } else {
        this.lockedTarget = null;
      }

      if (targetPlayer && s.targetIndicator && this.gameCamera) {
        this._pool.tempVec.set(
          targetPlayer._xCenter.x,
          targetPlayer._xBox.max.y + 1.5,
          targetPlayer._xCenter.z,
        );
        this._pool.tempVec.project(this.gameCamera);

        if (this._pool.tempVec.z < 1) {
          const screenX = (this._pool.tempVec.x + 1) * centerX;
          const screenY = (-this._pool.tempVec.y + 1) * centerY;
          ctx.globalAlpha = s.indicatorOpacity;
          const isz = s.indicatorSize;

          if (s.indicatorShape === "Image") {
            if (
              this.cachedIndicatorImage.complete &&
              this.cachedIndicatorImage.naturalWidth > 0
            ) {
              ctx.drawImage(
                this.cachedIndicatorImage,
                screenX - isz,
                screenY - isz * 2,
                isz * 2,
                isz * 2,
              );
            }
          } else {
            ctx.beginPath();
            if (s.indicatorShape === "Dot") {
              ctx.arc(screenX, screenY - isz * 0.6, isz * 0.5, 0, Math.PI * 2);
            } else if (s.indicatorShape === "Triangle") {
              ctx.moveTo(screenX, screenY);
              ctx.lineTo(screenX - isz * 0.6, screenY - isz * 1.2);
              ctx.lineTo(screenX + isz * 0.6, screenY - isz * 1.2);
            } else {
              ctx.moveTo(screenX, screenY);
              ctx.lineTo(screenX - isz * 0.5, screenY - isz * 0.6);
              ctx.lineTo(screenX - isz * 0.2, screenY - isz * 0.6);
              ctx.lineTo(screenX - isz * 0.2, screenY - isz * 1.2);
              ctx.lineTo(screenX + isz * 0.2, screenY - isz * 1.2);
              ctx.lineTo(screenX + isz * 0.2, screenY - isz * 0.6);
              ctx.lineTo(screenX + isz * 0.5, screenY - isz * 0.6);
            }
            ctx.closePath();
            ctx.fillStyle = s.indicatorColor;
            ctx.fill();
            ctx.strokeStyle = "rgba(0,0,0,0.8)";
            ctx.lineWidth = 1.5;
            ctx.stroke();
          }
          ctx.globalAlpha = 1.0;
        }
      }

      if (!targetPlayer) return;

      this.executeAimbot(s, targetPlayer);
    };

    updateRainbow(s) {
      if (s.espRainbow || s.chamsRainbow) this.hue = (this.hue + 1) % 360;
      if (s.espEnabled && s.espRainbow)
        this.espMaterial.uniforms.uColor.value.setHSL(this.hue / 360, 1, 0.5);
      if (s.chamsEnabled && this.chamsMaterial) {
        if (s.chamsRainbow)
          this.chamsMaterial.color.setHSL(this.hue / 360, 1, 0.5);
        else this.chamsMaterial.color.set(s.chamsColor);
      }
    }

    updateIndicatorImage(s) {
      if (
        s.indicatorShape === "Image" &&
        s.indicatorImageUrl !== this.currentImageUrl
      ) {
        this.currentImageUrl = s.indicatorImageUrl;
        if (this.currentImageUrl)
          this.cachedIndicatorImage.src = this.currentImageUrl;
      }
    }

    scanScene(currentTime) {
      this.cachedPlayers.length = 0;
      this.myPlayerCache = null;
      this.nonPlayerObjects.length = 0;

      for (let i = 0; i < this.scene.children.length; i++) {
        const child = this.scene.children[i];
        let isPlayer = false;
        if (child.type === "Object3D") {
          try {
            const c0 = child.children[0];
            if (c0 && c0.children && c0.children[0]) {
              if (c0.children[0].type === "PerspectiveCamera") {
                this.myPlayerCache = child;
                this.gameCamera = c0.children[0];
                isPlayer = true;
              } else {
                this.cachedPlayers.push(child);
                isPlayer = true;
              }
            }
          } catch (err) {}
        }
        if (!isPlayer) this.nonPlayerObjects.push(child);
      }

      if (this.nonPlayerObjects.length !== this.lastNonPlayerCount) {
        if (
          currentTime - this.lastMapScrape > 1000 ||
          this.lastNonPlayerCount === -1
        ) {
          this.mapMeshes.length = 0;
          for (let i = 0; i < this.nonPlayerObjects.length; i++) {
            const child = this.nonPlayerObjects[i];
            if (child.material) child.material.wireframe = false;
            child.traverse((node) => {
              if (node.isMesh && node.visible) {
                if (
                  node.material &&
                  (node.material.transparent ||
                    node.material.opacity < 0.9 ||
                    node.material.depthWrite === false)
                )
                  return;
                if (node.geometry) {
                  if (node.geometry.boundingSphere === null)
                    node.geometry.computeBoundingSphere();
                  if (node.geometry.boundingBox === null)
                    node.geometry.computeBoundingBox();
                }
                this.mapMeshes.push(node);
              }
            });
          }
          this.lastNonPlayerCount = this.nonPlayerObjects.length;
          this.lastMapScrape = currentTime;
        }
      }
    }

    executeAimbot(s, targetPlayer) {
      this.gameCamera.getWorldPosition(this._pool.camPos);

      let headTopY = targetPlayer._xBox.max.y;
      let feetY = targetPlayer._xBox.min.y;
      let dynamicHeight = targetPlayer._xSize.y;

      const getPitchYaw = (vec) => {
        this._pool.tempObj.position.copy(this._pool.camPos);
        this._pool.tempObj.lookAt(vec);
        let p = Math.max(
          -Math.PI / 2,
          Math.min(Math.PI / 2, -this._pool.tempObj.rotation.x),
        );
        let y = this._pool.tempObj.rotation.y + Math.PI;
        return { pitch: p, yaw: y };
      };

      this._pool.centerVec.set(
        targetPlayer._xCenter.x,
        targetPlayer.position.y,
        targetPlayer._xCenter.z,
      );

      if (s.aimPrediction && targetPlayer._xVelocity) {
        const dist = this._pool.camPos.distanceTo(targetPlayer.position);
        const travelTime = dist / 600;
        const leadFactor = travelTime * s.predictionFactor * 60;
        this._pool.centerVec.x += targetPlayer._xVelocity.x * leadFactor;
        this._pool.centerVec.z += targetPlayer._xVelocity.z * leadFactor;
      }

      let targetYaw = getPitchYaw(this._pool.centerVec).yaw;

      let angleDiff = targetYaw - this.myPlayerCache.rotation.y;
      while (angleDiff > Math.PI) angleDiff -= Math.PI * 2;
      while (angleDiff < -Math.PI) angleDiff += Math.PI * 2;

      if (s.aimHorizontal && s.horizontalFreeAim) {
        let distToTarget = this._pool.camPos.distanceTo(targetPlayer.position);
        let deadzoneAngle = Math.atan2(targetPlayer._xSize.x / 2, distToTarget);
        if (Math.abs(angleDiff) <= deadzoneAngle) angleDiff = 0;
        else
          angleDiff =
            angleDiff > 0
              ? angleDiff - deadzoneAngle
              : angleDiff + deadzoneAngle;
      }

      let currentPitch = this.myPlayerCache.children[0].rotation.x;
      let pitchDiff = 0;

      if (s.aimVertical) {
        let predOffsetX = 0,
          predOffsetZ = 0;
        if (s.aimPrediction && targetPlayer._xVelocity) {
          const dist = this._pool.camPos.distanceTo(targetPlayer.position);
          const travelTime = dist / 600;
          const leadFactor = travelTime * s.predictionFactor * 60;
          predOffsetX = targetPlayer._xVelocity.x * leadFactor;
          predOffsetZ = targetPlayer._xVelocity.z * leadFactor;
        }

        if (s.verticalFreeAim) {
          this._pool.topVec.set(
            targetPlayer._xCenter.x + predOffsetX,
            headTopY,
            targetPlayer._xCenter.z + predOffsetZ,
          );
          this._pool.botVec.set(
            targetPlayer._xCenter.x + predOffsetX,
            feetY,
            targetPlayer._xCenter.z + predOffsetZ,
          );

          let topPitch = getPitchYaw(this._pool.topVec).pitch;
          let botPitch = getPitchYaw(this._pool.botVec).pitch;

          let maxPitch = Math.max(topPitch, botPitch);
          let minPitch = Math.min(topPitch, botPitch);

          if (currentPitch < minPitch) pitchDiff = minPitch - currentPitch;
          else if (currentPitch > maxPitch) pitchDiff = maxPitch - currentPitch;
          else pitchDiff = 0;
        } else {
          let targetY = feetY + dynamicHeight * s.aimOffset;
          this._pool.targetVec.set(
            targetPlayer._xCenter.x + predOffsetX,
            targetY,
            targetPlayer._xCenter.z + predOffsetZ,
          );
          let targetPitch = getPitchYaw(this._pool.targetVec).pitch;
          pitchDiff = targetPitch - currentPitch;
        }
      }

      let targetPitchOffset = currentPitch + pitchDiff;
      targetPitchOffset = Math.max(
        -Math.PI / 2,
        Math.min(Math.PI / 2, targetPitchOffset),
      );

      if (s.smoothAim) {
        const minX = Math.min(s.aimSpeedXMin, s.aimSpeedXMax);
        const maxX = Math.max(s.aimSpeedXMin, s.aimSpeedXMax);
        const minY = Math.min(s.aimSpeedYMin, s.aimSpeedYMax);
        const maxY = Math.max(s.aimSpeedYMin, s.aimSpeedYMax);

        const speedX = (minX + Math.random() * (maxX - minX)) * 0.4;
        const speedY = (minY + Math.random() * (maxY - minY)) * 0.4;

        if (s.aimVertical && pitchDiff !== 0) {
          this.myPlayerCache.children[0].rotation.x = MathUtils.lerp(
            this.myPlayerCache.children[0].rotation.x,
            targetPitchOffset,
            speedY,
          );
        }
        if (s.aimHorizontal && angleDiff !== 0) {
          this.myPlayerCache.rotation.y += angleDiff * speedX;
        }
      } else {
        if (s.aimVertical && pitchDiff !== 0)
          this.myPlayerCache.children[0].rotation.x = targetPitchOffset;
        if (s.aimHorizontal && angleDiff !== 0)
          this.myPlayerCache.rotation.y += angleDiff;
      }
    }
  }

  class Xianware {
    constructor() {
      this.config = new ConfigManager();
      this.ui = new UIManager(this);
      this.input = new InputManager(this);
      this.engine = new Engine(this);
      this.isInitialized = false;
    }

    init() {
      if (this.isInitialized) return;
      this.isInitialized = true;

      this.ui.init();
      this.input.init();
      this.engine.init();

      if (this.config.settings.customCssText) this.ui.injectCustomCss();
      console.log("[Xianware] V8.2.1 Initialized Successfully.");
    }
  }

  const x = {
    window: window,
    document: document,
    requestAnimationFrame: window.requestAnimationFrame,
  };
  const app = new Xianware();

  if (
    document.readyState === "complete" ||
    document.readyState === "interactive"
  ) {
    app.init();
  } else {
    window.addEventListener("DOMContentLoaded", () => app.init());
    window.addEventListener("load", () => app.init());
  }
})();