Alguien Client - Surve.io Client

A client to enhance the survev.io in-game experience with many features, as well as future features.

Verzia zo dňa 06.12.2024. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Alguien Client - Surve.io Client
// @namespace    https://github.com/SoyAlguien0/AlguienClient
// @version      0.0.1
// @description  A client to enhance the survev.io in-game experience with many features, as well as future features.
// @author       SoyAlguien
// @license      AGPL-3.0
// @require      https://update.greasyfork.org/scripts/391611/743919/WSHook.js
// @run-at       document-end
// @match        *://survev.io/*
// @match        *://66.179.254.36/*
// @match        *://expandedwater.online/*
// @grant        none
// ==/UserScript==
class GameMod {
  constructor() {
    this.lastFrameTime = performance.now();
    this.frameCount = 0;
    this.fps = 0;
    this.isFpsUncapped = false;
    this.isFpsVisible = true;
    this.isMenuVisible = true;

    this.animationFrameCallback = window.requestAnimationFrame.bind(window);

    this.initFpsCounter();
    this.initMenu();
    this.startUpdateLoop();
    this.setupWeaponBorderHandler();
    this.setupKeyListeners();
  }

  initFpsCounter() {
    this.fpsCounter = document.createElement("div");
    this.fpsCounter.id = "fpsCounter";
    Object.assign(this.fpsCounter.style, {
      position: "fixed",
      top: "10px",
      left: "10px",
      color: "white",
      backgroundColor: "rgba(0, 0, 0, 0.2)",
      padding: "5px 10px",
      borderRadius: "5px",
      fontFamily: "Arial, sans-serif",
      fontSize: "14px",
      zIndex: "10000",
      pointerEvents: "none",
    });

    document.body.appendChild(this.fpsCounter);
    this.updateFpsVisibility();
  }

  updateFpsVisibility() {
    this.fpsCounter.style.display = this.isFpsVisible ? "block" : "none";
  }

  toggleFpsDisplay() {
    this.isFpsVisible = !this.isFpsVisible;
    this.updateFpsVisibility();
  }

  toggleFpsUncap() {
    this.isFpsUncapped = !this.isFpsUncapped;
    this.animationFrameCallback = this.isFpsUncapped
      ? (callback) => setTimeout(callback, 1)
      : window.requestAnimationFrame.bind(window);
  }

  updateHealthBars() {
    const healthBars = document.querySelectorAll("#ui-health-container");
    healthBars.forEach((container) => {
      const bar = container.querySelector("#ui-health-actual");
      if (bar) {
        const width = Math.round(parseFloat(bar.style.width));
        let percentageText = container.querySelector(".health-text");

        if (!percentageText) {
          percentageText = document.createElement("span");
          percentageText.classList.add("health-text");
          Object.assign(percentageText.style, {
            width: "100%",
            textAlign: "center",
            marginTop: "5px",
            color: "#333",
            fontSize: "20px",
            fontWeight: "bold",
            position: "absolute",
            zIndex: "10",
          });
          container.appendChild(percentageText);
        }

        percentageText.textContent = `${width}%`;
      }
    });
  }

  updateBoostBars() {
    const boostCounter = document.querySelector("#ui-boost-counter");
    if (boostCounter) {
      const boostBars = boostCounter.querySelectorAll(
        ".ui-boost-base .ui-bar-inner",
      );

      let totalBoost = 0;
      const weights = [25, 25, 40, 10];

      boostBars.forEach((bar, index) => {
        const width = parseFloat(bar.style.width);
        if (!isNaN(width)) {
          totalBoost += width * (weights[index] / 100);
        }
      });

      const averageBoost = Math.round(totalBoost);
      let boostDisplay = boostCounter.querySelector(".boost-display");

      if (!boostDisplay) {
        boostDisplay = document.createElement("div");
        boostDisplay.classList.add("boost-display");
        Object.assign(boostDisplay.style, {
          position: "absolute",
          bottom: "75px",
          right: "335px",
          color: "#FF901A",
          backgroundColor: "rgba(0, 0, 0, 0.4)",
          padding: "5px 10px",
          borderRadius: "5px",
          fontFamily: "Arial, sans-serif",
          fontSize: "14px",
          zIndex: "10",
          textAlign: "center",
        });

        boostCounter.appendChild(boostDisplay);
      }

      boostDisplay.textContent = `AD: ${averageBoost}%`;
    }
  }

  setupWeaponBorderHandler() {
    const weaponContainers = Array.from(
      document.getElementsByClassName("ui-weapon-switch"),
    );
    weaponContainers.forEach((container) => {
      if (container.id === "ui-weapon-id-4") {
        container.style.border = "3px solid #2f4032";
      } else {
        container.style.border = "3px solid #FFFFFF";
      }
    });

    const weaponNames = Array.from(
      document.getElementsByClassName("ui-weapon-name"),
    );
    weaponNames.forEach((weaponNameElement) => {
      const weaponContainer = weaponNameElement.closest(".ui-weapon-switch");
      const observer = new MutationObserver(() => {
        const weaponName = weaponNameElement.textContent.trim();
        let border = "#FFFFFF";

        switch (weaponName.toUpperCase()) {
          case "CZ-3A1":
          case "G18C":
          case "M9":
          case "M93R":
          case "MAC-10":
          case "MP5":
          case "P30L":
          case "DUAL P30L":
          case "UMP9":
          case "VECTOR (9MM)":
          case "VSS":
          case "FLAMETHROWER":
            border = "#FFAE00";
            break;

          case "AK-47":
          case "OT-38":
          case "OTS-38":
          case "M39 EMR":
          case "DP-28":
          case "MOSIN-NAGANT":
          case "SCAR-H":
          case "SV-98":
          case "M1 GARAND":
          case "PKP PECHENEG":
          case "AN-94":
          case "BAR M1918":
          case "BLR 81":
          case "SVD-63":
          case "M134":
          case "WATER GUN":
            border = "#007FFF";
            break;

          case "FAMAS":
          case "M416":
          case "M249":
          case "QBB-97":
          case "MK 12 SPR":
          case "M4A1-S":
          case "SCOUT ELITE":
          case "L86A2":
            border = "#0f690d";
            break;

          case "M870":
          case "MP220":
          case "SAIGA-12":
          case "SPAS-12":
          case "USAS-12":
          case "SUPER 90":
          case "LASR GUN":
          case "M1100":
            border = "#FF0000";
            break;

          case "DEAGLE 50":
          case "RAINBOW BLASTER":
            border = "#000000";
            break;

          case "AWM-S":
          case "MK 20 SSR":
            border = "#808000";
            break;

          case "FLARE GUN":
            border = "#FF4500";
            break;

          case "MODEL 94":
          case "PEACEMAKER":
          case "VECTOR (.45 ACP)":
          case "M1911":
          case "M1A1":
            border = "#800080";
            break;

          case "M79":
            border = "#008080";
            break;

          case "POTATO CANNON":
          case "SPUD GUN":
            border = "#A52A2A";
            break;

          case "HEART CANNON":
            border = "#FFC0CB";
            break;

          default:
            border = "#FFFFFF";
            break;
        }

        if (weaponContainer.id !== "ui-weapon-id-4") {
          weaponContainer.style.border = `3px solid ${border}`;
        }
      });

      observer.observe(weaponNameElement, {
        childList: true,
        characterData: true,
        subtree: true,
      });
    });
  }

  updateMenuButtonText() {
    const hideButton = document.getElementById("hideMenuButton");
    hideButton.textContent = this.isMenuVisible
      ? "Hide Menu [P]"
      : "Show Menu [P]";
  }

  setupKeyListeners() {
    document.addEventListener("keydown", (event) => {
      if (event.key.toLowerCase() === "p") {
        this.toggleMenuVisibility();
      }
    });
  }

  initMenu() {
    const menu = document.createElement("div");
    menu.id = "soyAlguienMenu";
    Object.assign(menu.style, {
      position: "fixed",
      top: "50px",
      left: "10px",
      backgroundColor: "rgba(0, 0, 0, 0.8)",
      padding: "15px",
      borderRadius: "10px",
      boxShadow: "0 4px 10px rgba(0, 0, 0, 0.6)",
      zIndex: "10001",
      width: "250px",
      fontFamily: "Arial, sans-serif",
      color: "#fff",
    });

    const title = document.createElement("h2");
    title.textContent = "SoyAlguien Mod Menu";
    title.style.margin = "0 0 10px";
    title.style.textAlign = "center";
    title.style.fontSize = "18px";
    title.style.color = "#FFAE00";
    menu.appendChild(title);

    const fpsToggle = document.createElement("button");
    fpsToggle.textContent = "Show FPS";
    Object.assign(fpsToggle.style, {
      backgroundColor: "#FFAE00",
      border: "none",
      color: "#fff",
      padding: "10px",
      borderRadius: "5px",
      width: "100%",
      marginBottom: "10px",
      fontSize: "14px",
      cursor: "pointer",
    });
    fpsToggle.onclick = () => this.toggleFpsDisplay();
    menu.appendChild(fpsToggle);

    const uncapFpsToggle = document.createElement("button");
    uncapFpsToggle.textContent = "Uncap FPS";
    Object.assign(uncapFpsToggle.style, {
      backgroundColor: "#FF4500",
      border: "none",
      color: "#fff",
      padding: "10px",
      borderRadius: "5px",
      width: "100%",
      marginBottom: "10px",
      fontSize: "14px",
      cursor: "pointer",
    });
    uncapFpsToggle.onclick = () => this.toggleFpsUncap();
    menu.appendChild(uncapFpsToggle);

    const hideShowToggle = document.createElement("button");
    hideShowToggle.textContent = "Hide/Show Menu [P]";
    Object.assign(hideShowToggle.style, {
      backgroundColor: "#808080",
      border: "none",
      color: "#fff",
      padding: "10px",
      borderRadius: "5px",
      width: "100%",
      marginBottom: "10px",
      fontSize: "14px",
      cursor: "pointer",
    });
    hideShowToggle.onclick = () => this.toggleMenuVisibility();
    menu.appendChild(hideShowToggle);

    document.body.appendChild(menu);

    this.menu = menu;
  }

  toggleMenuVisibility() {
    const isVisible = this.menu.style.display !== "none";
    this.menu.style.display = isVisible ? "none" : "block";
  }

  startUpdateLoop() {
    const now = performance.now();
    const delta = now - this.lastFrameTime;

    this.frameCount++;

    if (delta >= 1000) {
      this.fps = Math.round((this.frameCount * 1000) / delta);
      this.frameCount = 0;
      this.lastFrameTime = now;

      if (this.isFpsVisible) {
        this.fpsCounter.textContent = `FPS: ${this.fps}`;
      }
    }

    this.updateHealthBars();
    this.updateBoostBars();
    this.animationFrameCallback(() => this.startUpdateLoop());
  }
}

const gameMod = new GameMod();