Alguien Client - Surve.io Client

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

От 06.12.2024. Виж последната версия.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

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

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==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();