A client to enhance the survev.io in-game experience with many features, as well as future features.
// ==UserScript==
// @name Alguien Client - Survev.io Client
// @namespace https://github.com/SoyAlguien0/AlguienClient
// @version 0.0.4
// @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 PingTest {
constructor(selectedServer) {
this.ptcDataBuf = new ArrayBuffer(1);
this.test = {
region: selectedServer.region,
url: `wss://${selectedServer.url}/ptc`,
ping: 9999,
ws: null,
sendTime: 0,
retryCount: 0,
};
}
startPingTest() {
if (!this.test.ws) {
const ws = new WebSocket(this.test.url);
ws.binaryType = "arraybuffer";
ws.onopen = () => {
this.sendPing();
this.test.retryCount = 0;
};
ws.onmessage = () => {
const elapsed = (Date.now() - this.test.sendTime) / 1e3;
this.test.ping = Math.round(elapsed * 1000);
this.test.retryCount = 0;
setTimeout(() => this.sendPing(), 200);
};
ws.onerror = () => {
this.test.ping = null;
this.test.retryCount++;
if (this.test.retryCount < 5) {
setTimeout(() => this.startPingTest(), 2000);
}
else {
try {
ws.close();
}
catch { }
this.test.ws = null;
}
};
ws.onclose = () => {
this.test.ws = null;
};
this.test.ws = ws;
}
}
sendPing() {
if (this.test.ws && this.test.ws.readyState === WebSocket.OPEN) {
this.test.sendTime = Date.now();
this.test.ws.send(this.ptcDataBuf);
}
}
getPingResult() {
return {
region: this.test.region,
ping: this.test.ping,
};
}
}
class GameMod {
constructor() {
this.fpsCounter = null;
this.pingCounter = null;
this.killsCounter = null;
this.menu = null;
this.currentServer = null;
this.pingTest = null;
const settings = this.getSettings();
this.kills = 0;
this.isFpsVisible = true;
this.isPingVisible = true;
this.isKillsVisible = true;
this.isMenuVisible = true;
this.isClean = false;
this.isFpsUncapped = settings["fps-uncap"] !== undefined ? !!settings["fps-uncap"] : true;
this.setAnimationFrameCallback();
this.initCounter("fpsCounter", this.updateFpsVisibility.bind(this));
this.initCounter("pingCounter", this.updatePingVisibility.bind(this));
this.initCounter("killsCounter", this.updateKillsVisibility.bind(this));
this.initMenu();
this.loadBackgroundFromLocalStorage();
this.loadLocalStorage();
this.startUpdateLoop();
this.setupWeaponBorderHandler();
this.setupKeyListeners();
}
init() {
this.startUpdateLoop();
this.pingShow();
this.customUiElements();
}
getSettings() {
return JSON.parse(localStorage.getItem("gameSettings") || "{}");
}
saveSettings() {
localStorage.setItem("gameSettings", JSON.stringify({ "fps-uncap": this.isFpsUncapped }));
}
initCounter(id, updateVisibilityFn) {
const el = document.createElement("div");
el.id = id;
Object.assign(el.style, {
color: "white",
backgroundColor: "rgba(0, 0, 0, 0.2)",
padding: "5px 10px",
marginTop: "10px",
borderRadius: "5px",
fontFamily: "Arial, sans-serif",
fontSize: "14px",
zIndex: "10000",
pointerEvents: "none",
});
const uiTopLeft = document.getElementById("ui-top-left");
if (uiTopLeft)
uiTopLeft.appendChild(el);
if (id === "fpsCounter")
this.fpsCounter = el;
if (id === "pingCounter")
this.pingCounter = el;
if (id === "killsCounter")
this.killsCounter = el;
updateVisibilityFn();
}
updateFpsVisibility() {
this.updateVisibility("fpsCounter", this.isFpsVisible);
}
updateFpsToggle() {
this.animationFrameCallback = this.isFpsUncapped
? (callback) => setTimeout(callback, 1)
: (callback) => requestAnimationFrame(callback);
}
updatePingVisibility() {
this.updateVisibility("pingCounter", this.isPingVisible);
}
updateKillsVisibility() {
this.updateVisibility("killsCounter", this.isKillsVisible);
}
updateVisibility(id, isVisible) {
const el = this[id];
if (el) {
el.style.display = isVisible ? "block" : "none";
el.style.backgroundColor = isVisible ? "rgba(0, 0, 0, 0.2)" : "transparent";
}
}
setAnimationFrameCallback() {
this.animationFrameCallback = (callback) => setTimeout(callback, 1);
}
getKills() {
const killElement = document.querySelector(".ui-player-kills.js-ui-player-kills");
if (killElement) {
const kills = Number.parseInt(killElement.textContent || "", 10);
return Number.isNaN(kills) ? 0 : kills;
}
return 0;
}
startPingTest() {
const currentUrl = globalThis.location.href;
const isSpecialUrl = /\/#\w+/.test(currentUrl);
const teamSelectElement = document.getElementById("team-server-select");
const mainSelectElement = document.getElementById("server-select-main");
const region = isSpecialUrl && teamSelectElement ? teamSelectElement.value : mainSelectElement ? mainSelectElement.value : null;
if (region && region !== this.currentServer) {
this.currentServer = region;
this.resetPing();
const servers = [
{ region: "NA", url: "usr.mathsiscoolfun.com:8001" },
{ region: "EU", url: "eur.mathsiscoolfun.com:8001" },
{ region: "Asia", url: "asr.mathsiscoolfun.com:8001" },
{ region: "SA", url: "sa.mathsiscoolfun.com:8001" },
];
const selectedServer = servers.find((server) => region.toUpperCase() === server.region.toUpperCase());
if (selectedServer) {
this.pingTest = new PingTest(selectedServer);
this.pingTest.startPingTest();
}
else {
this.resetPing();
}
}
}
resetPing() {
if (this.pingTest?.test.ws) {
try {
this.pingTest.test.ws.close();
}
catch { }
this.pingTest.test.ws = null;
}
this.pingTest = null;
}
saveBackgroundToLocalStorage(value) {
if (typeof value === "string") {
localStorage.setItem("lastBackgroundType", "url");
localStorage.setItem("lastBackgroundValue", value);
}
else {
localStorage.setItem("lastBackgroundType", "local");
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === "string")
localStorage.setItem("lastBackgroundValue", reader.result);
};
reader.readAsDataURL(value);
}
}
loadBackgroundFromLocalStorage() {
const backgroundType = localStorage.getItem("lastBackgroundType");
const backgroundValue = localStorage.getItem("lastBackgroundValue");
const backgroundElement = document.getElementById("background");
if (backgroundElement && backgroundType && backgroundValue) {
backgroundElement.style.backgroundImage = `url(${backgroundValue})`;
}
}
loadLocalStorage() {
try {
const savedSettings = JSON.parse(localStorage.getItem("userSettings") || "null");
if (savedSettings) {
this.isFpsVisible = savedSettings.isFpsVisible ?? this.isFpsVisible;
this.isPingVisible = savedSettings.isPingVisible ?? this.isPingVisible;
this.isKillsVisible = savedSettings.isKillsVisible ?? this.isKillsVisible;
this.isClean = savedSettings.isClean ?? this.isClean;
}
}
catch { }
this.updateKillsVisibility();
this.updateFpsVisibility();
this.updatePingVisibility();
}
updateHealthBars() {
const healthBars = document.querySelectorAll("#ui-health-container");
healthBars.forEach((container) => {
const bar = container.querySelector("#ui-health-actual");
if (bar) {
const width = Math.round(Number.parseFloat(bar.style.width || "0"));
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)
return;
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 = Number.parseFloat(bar.style.width || "0");
if (!Number.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) => {
container.style.border = container.id === "ui-weapon-id-4" ? "3px solid #2f4032" : "3px solid #FFFFFF";
});
const weaponNames = Array.from(document.getElementsByClassName("ui-weapon-name"));
weaponNames.forEach((weaponNameElement) => {
const weaponContainer = weaponNameElement.closest(".ui-weapon-switch");
if (!weaponContainer)
return;
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":
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 "GROZA":
case "GROZA-S":
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 "MODEL 94":
case "PEACEMAKER":
case "MK45G":
case "M1911":
case "M1A1":
border = "#800080";
break;
case "DEAGLE 50":
case "RAINBOW BLASTER":
border = "#000000";
break;
case "AWM-S":
case "MK 20 SSR":
border = "#808000";
break;
case "POTATO CANNON":
case "SPUD GUN":
border = "#A52A2A";
break;
case "FLARE GUN":
border = "#FF4500";
break;
case "M79":
border = "#008080";
break;
case "HEART CANNON":
border = "#FFC0CB";
break;
default:
break;
}
if (weaponContainer.id !== "ui-weapon-id-4") {
weaponContainer.style.border = `3px solid ${border}`;
}
});
observer.observe(weaponNameElement, { childList: true, characterData: true, subtree: true });
});
}
updateUiElements() {
const currentUrl = globalThis.location.href;
const isSpecialUrl = /\/#\w+/.test(currentUrl);
const playerOptions = document.getElementById("player-options");
if (!playerOptions)
return;
const teamMenuContents = document.getElementById("team-menu-contents");
const startMenuContainer = document.querySelector("#start-menu .play-button-container");
if (isSpecialUrl && teamMenuContents && playerOptions.parentNode !== teamMenuContents) {
teamMenuContents.appendChild(playerOptions);
}
else if (!isSpecialUrl && startMenuContainer && playerOptions.parentNode !== startMenuContainer) {
const firstChild = startMenuContainer.firstChild;
startMenuContainer.insertBefore(playerOptions, firstChild);
}
const teamMenu = document.getElementById("team-menu");
if (teamMenu)
teamMenu.style.height = "355px";
const menuBlocks = document.querySelectorAll(".menu-block");
menuBlocks.forEach((block) => { block.style.maxHeight = "355px"; });
}
updateCleanMode() {
const leftColumn = document.getElementById("left-column");
const newsBlock = document.getElementById("news-block");
if (this.isClean) {
if (leftColumn)
leftColumn.style.display = "none";
if (newsBlock)
newsBlock.style.display = "none";
}
else {
if (leftColumn)
leftColumn.style.display = "block";
if (newsBlock)
newsBlock.style.display = "block";
}
}
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, {
backgroundColor: "rgba(0, 0, 0, 0.5)",
padding: "15px",
marginLeft: "15px",
borderRadius: "10px",
boxShadow: "0 4px 10px rgba(0, 0, 0, 0.3)",
zIndex: "10001",
width: "250px",
fontFamily: "Arial, sans-serif",
color: "#fff",
maxHeight: "400px",
overflowY: "auto",
});
const title = document.createElement("h2");
title.textContent = "SoyAlguien Client";
Object.assign(title.style, {
margin: "0 0 10px",
textAlign: "center",
fontSize: "18px",
color: "#FFAE00",
});
menu.appendChild(title);
const updateLocalStorage = () => {
localStorage.setItem("userSettings", JSON.stringify({
isFpsVisible: this.isFpsVisible,
isPingVisible: this.isPingVisible,
isKillsVisible: this.isKillsVisible,
isClean: this.isClean,
}));
};
this.loadLocalStorage();
const createToggleButton = (text, stateKey, onClick) => {
const button = document.createElement("button");
const state = !!this[stateKey];
button.textContent = `${text} ${state ? "✅" : "❌"}`;
Object.assign(button.style, {
backgroundColor: state ? "#4CAF50" : "#FF0000",
border: "none",
color: "#fff",
padding: "10px",
borderRadius: "5px",
width: "100%",
marginBottom: "10px",
fontSize: "14px",
cursor: "pointer",
});
button.onclick = () => {
this[stateKey] = !this[stateKey];
onClick();
const newState = !!this[stateKey];
button.textContent = `${text} ${newState ? "✅" : "❌"}`;
button.style.backgroundColor = newState ? "#4CAF50" : "#FF0000";
updateLocalStorage();
};
return button;
};
menu.appendChild(createToggleButton("Show FPS", "isFpsVisible", this.updateFpsVisibility.bind(this)));
menu.appendChild(createToggleButton("Show Ping", "isPingVisible", this.updatePingVisibility.bind(this)));
menu.appendChild(createToggleButton("Show Kills", "isKillsVisible", this.updateKillsVisibility.bind(this)));
menu.appendChild(createToggleButton("Clean Menu", "isClean", this.updateCleanMode.bind(this)));
const hideShowToggle = document.createElement("button");
hideShowToggle.textContent = `👀 Hide/Show Menu [P]`;
Object.assign(hideShowToggle.style, {
backgroundColor: "#6F42C1",
border: "none",
color: "#fff",
padding: "10px",
borderRadius: "5px",
width: "100%",
marginBottom: "10px",
fontSize: "14px",
cursor: "pointer",
});
hideShowToggle.onclick = () => this.toggleMenuVisibility();
menu.appendChild(hideShowToggle);
const backgroundToggle = document.createElement("button");
backgroundToggle.textContent = `🎨 Change Background`;
Object.assign(backgroundToggle.style, {
backgroundColor: "#007BFF",
border: "none",
color: "#fff",
padding: "10px",
borderRadius: "5px",
width: "100%",
marginBottom: "10px",
fontSize: "14px",
cursor: "pointer",
});
backgroundToggle.onclick = () => {
const backgroundElement = document.getElementById("background");
if (!backgroundElement) {
alert("Element with id 'background' not found.");
return;
}
const choice = prompt("Enter '1' to provide a URL or '2' to upload a local image:");
if (choice === "1") {
const newBackgroundUrl = prompt("Enter the URL of the new background image:");
if (newBackgroundUrl) {
backgroundElement.style.backgroundImage = `url(${newBackgroundUrl})`;
this.saveBackgroundToLocalStorage(newBackgroundUrl);
alert("Background updated successfully!");
}
}
else if (choice === "2") {
const fileInput = document.createElement("input");
fileInput.type = "file";
fileInput.accept = "image/*";
fileInput.onchange = (event) => {
const file = event.target.files?.[0];
if (file) {
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === "string") {
backgroundElement.style.backgroundImage = `url(${reader.result})`;
this.saveBackgroundToLocalStorage(file);
alert("Background updated successfully!");
}
};
reader.readAsDataURL(file);
}
};
fileInput.click();
}
};
menu.appendChild(backgroundToggle);
const moreSettingsButton = document.createElement("button");
moreSettingsButton.textContent = "⚙️ More Settings";
Object.assign(moreSettingsButton.style, {
backgroundColor: "#1D1616",
border: "none",
color: "#fff",
padding: "10px",
borderRadius: "5px",
width: "100%",
fontSize: "14px",
cursor: "pointer",
});
moreSettingsButton.onclick = () => this.openSubMenu();
menu.appendChild(moreSettingsButton);
globalThis.onload = () => {
const savedBackground = localStorage.getItem("backgroundImage");
if (savedBackground) {
const backgroundElement = document.getElementById("background");
if (backgroundElement)
backgroundElement.style.backgroundImage = `url(${savedBackground})`;
}
};
const startRowTop = document.getElementById("start-row-top");
if (startRowTop)
startRowTop.appendChild(menu);
this.menu = menu;
}
openSubMenu() {
const overlay = document.createElement("div");
const savedOpacity = localStorage.getItem("opacity") ?? "1";
const savedScale = localStorage.getItem("scale") ?? "0.8";
Object.assign(overlay.style, {
position: "fixed",
top: "0",
left: "0",
width: "100%",
height: "100%",
backgroundColor: "rgba(0, 0, 0, 0.7)",
zIndex: "10002",
display: "flex",
justifyContent: "center",
alignItems: "center",
});
const subMenu = document.createElement("div");
Object.assign(subMenu.style, {
backgroundColor: "#333",
padding: "20px",
borderRadius: "15px",
width: "400px",
color: "#fff",
textAlign: "left",
zIndex: "10003",
boxShadow: "0 4px 15px rgba(0, 0, 0, 0.5)",
});
const createSectionHeader = (text) => {
const header = document.createElement("h3");
header.textContent = text;
Object.assign(header.style, {
fontSize: "18px",
fontWeight: "bold",
color: "#FFD700",
marginBottom: "10px",
});
return header;
};
const createSettingItem = (id, label, checked) => {
const wrapper = document.createElement("div");
Object.assign(wrapper.style, {
display: "flex",
alignItems: "center",
padding: "10px",
marginBottom: "10px",
borderRadius: "8px",
backgroundColor: "#444",
});
const checkbox = document.createElement("input");
checkbox.id = id;
checkbox.type = "checkbox";
checkbox.checked = checked;
Object.assign(checkbox.style, { marginRight: "10px", cursor: "pointer" });
const labelText = document.createElement("p");
labelText.textContent = label;
Object.assign(labelText.style, { margin: "0", fontSize: "16px", color: "#fff" });
wrapper.appendChild(checkbox);
wrapper.appendChild(labelText);
return wrapper;
};
const createCustomSlider = (id, min, max, step, value, onChange) => {
const wrapper = document.createElement("div");
Object.assign(wrapper.style, {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
marginBottom: "10px",
});
const slider = document.createElement("input");
slider.type = "range";
slider.id = id;
slider.min = String(min);
(slider).max = String(max);
(slider).step = String(step);
(slider).value = value;
Object.assign(slider.style, { flex: "1", marginRight: "10px" });
const valueLabel = document.createElement("span");
valueLabel.textContent = value;
Object.assign(valueLabel.style, { minWidth: "30px", textAlign: "right", color: "#fff" });
slider.oninput = () => {
valueLabel.textContent = (slider).value;
onChange((slider).value);
};
wrapper.appendChild(slider);
wrapper.appendChild(valueLabel);
return wrapper;
};
const titleClient = document.createElement("h2");
titleClient.textContent = "Client Settings";
Object.assign(titleClient.style, {
margin: "0 0 20px",
fontSize: "24px",
fontWeight: "bold",
color: "#FFAE00",
textAlign: "center",
});
subMenu.appendChild(titleClient);
subMenu.appendChild(createSectionHeader("FPS Uncap"));
subMenu.appendChild(createSettingItem("fps-uncap", "Enable/disable FPS uncap", this.isFpsUncapped));
const titleUI = document.createElement("h2");
titleUI.textContent = "UI Settings";
Object.assign(titleUI.style, {
margin: "20px 0 20px",
fontSize: "24px",
fontWeight: "bold",
color: "#FFAE00",
textAlign: "center",
});
subMenu.appendChild(titleUI);
subMenu.appendChild(createSectionHeader("Opacity"));
subMenu.appendChild(createCustomSlider("opacity-slider", 0, 1, 0.01, savedOpacity, (value) => localStorage.setItem("opacity", value)));
subMenu.appendChild(createSectionHeader("Scale"));
subMenu.appendChild(createCustomSlider("scale-slider", 0.5, 1, 0.01, savedScale, (value) => localStorage.setItem("scale", value)));
const closeButton = document.createElement("button");
closeButton.textContent = "Close";
Object.assign(closeButton.style, {
backgroundColor: "#FF4D4D",
border: "none",
color: "#fff",
padding: "10px 20px",
borderRadius: "8px",
marginTop: "20px",
cursor: "pointer",
fontSize: "16px",
fontWeight: "bold",
transition: "background-color 0.3s ease",
width: "100%",
});
closeButton.onmouseenter = () => { closeButton.style.backgroundColor = "#FF3333"; };
closeButton.onmouseleave = () => { closeButton.style.backgroundColor = "#FF4D4D"; };
closeButton.onclick = () => {
if (overlay.parentElement)
document.body.removeChild(overlay);
};
subMenu.appendChild(closeButton);
overlay.appendChild(subMenu);
document.body.appendChild(overlay);
this.attachSettingsEvents();
}
customUiElements() {
const scale = parseFloat(localStorage.getItem("scale") || "0.8");
const opacity = parseFloat(localStorage.getItem("opacity") || "1");
const healthBoost = document.getElementById("ui-bottom-center-0");
if (healthBoost) {
healthBoost.style.transform = `translateX(-50%) scale(${scale})`;
healthBoost.style.opacity = String(opacity);
healthBoost.style.bottom = globalThis.innerWidth > 1200 ? `-${(1 - scale) * 20 + 2}px` : "";
}
const weapon = document.getElementById("ui-weapon-container");
if (weapon) {
weapon.style.scale = String(scale);
weapon.style.opacity = String(opacity);
weapon.style.transformOrigin = "right";
}
const inventory = document.getElementById("ui-right-center");
if (inventory) {
inventory.style.scale = String(scale * 1.1);
inventory.style.opacity = String(opacity);
inventory.style.marginTop = `-${(1 - scale) * 100}px`;
}
const info = document.getElementById("ui-top-left");
if (info) {
info.style.transformOrigin = "top left";
info.style.scale = String(scale * 1.1);
info.style.opacity = String(opacity);
}
const players = document.getElementById("ui-leaderboard-wrapper");
if (players) {
players.style.scale = String(scale);
players.style.opacity = String(opacity);
players.style.transformOrigin = "top right";
}
const killfeed = document.getElementById("ui-killfeed-wrapper");
if (killfeed) {
killfeed.style.scale = String(scale);
killfeed.style.opacity = String(opacity);
killfeed.style.transformOrigin = "right";
}
const ammo = document.getElementById("ui-equipped-ammo-wrapper");
if (ammo) {
ammo.style.opacity = String(opacity);
ammo.style.transform = `translateX(-50%) scale(${scale})`;
const bottomValue = 62 - (1 - scale) * 20;
ammo.style.bottom = `${bottomValue}px`;
}
const gears = document.getElementById("ui-bottom-center-right");
if (gears) {
gears.style.opacity = String(opacity);
gears.style.scale = String(scale);
}
const scopes = document.getElementById("ui-top-center-scopes");
if (scopes) {
scopes.style.opacity = String(opacity);
scopes.style.scale = String(scale);
}
}
attachSettingsEvents() {
const fpsUncapCheckbox = document.querySelector("#fps-uncap");
if (fpsUncapCheckbox) {
fpsUncapCheckbox.addEventListener("change", (event) => {
const target = event.target;
this.isFpsUncapped = target.checked;
this.saveSettings();
});
}
const opacitySlider = document.querySelector("#opacity-slider");
if (opacitySlider) {
opacitySlider.addEventListener("input", (event) => {
const target = event.target;
localStorage.setItem("opacity", target.value);
this.customUiElements();
});
}
const scaleSlider = document.querySelector("#scale-slider");
if (scaleSlider) {
scaleSlider.addEventListener("input", (event) => {
const target = event.target;
localStorage.setItem("scale", target.value);
this.customUiElements();
});
}
}
toggleMenuVisibility() {
if (!this.menu)
return;
const isVisible = this.menu.style.display !== "none";
this.menu.style.display = isVisible ? "none" : "block";
}
startUpdateLoop() {
let lastFrameTime = performance.now();
let frameCount = 0;
let fps = 0;
const loop = () => {
const now = performance.now();
const delta = now - lastFrameTime;
frameCount++;
if (delta >= 1000) {
fps = Math.round((frameCount * 1000) / delta) * 2;
frameCount = 0;
lastFrameTime = now;
this.kills = this.getKills();
if (this.isFpsVisible && this.fpsCounter) {
this.fpsCounter.textContent = `FPS: ${Math.round(fps / 2)}`;
}
if (this.isKillsVisible && this.killsCounter) {
this.killsCounter.textContent = `Kills: ${this.kills}`;
}
if (this.isPingVisible && this.pingCounter && this.pingTest) {
const result = this.pingTest.getPingResult();
this.pingCounter.textContent = `PING: ${result.ping} ms`;
}
}
this.startPingTest();
this.updateFpsToggle();
this.animationFrameCallback(() => loop());
this.updateUiElements();
this.updateCleanMode();
this.updateBoostBars();
this.updateHealthBars();
};
loop();
}
pingShow() {
const serverSelect = document.getElementById("server-select-main");
if (!serverSelect)
return;
const updateOptionWithPing = (optionElement, ping) => {
const pingText = ` (${ping} ms)`;
const originalText = optionElement.textContent?.replace(/\(\d+ ms\)/g, "").trim() || "";
optionElement.textContent = `${originalText}${pingText}`;
if (ping > 300) {
optionElement.style.color = "red";
}
else if (ping > 200) {
optionElement.style.color = "orange";
}
else if (ping > 100) {
optionElement.style.color = "yellow";
}
else {
optionElement.style.color = "green";
}
};
const servers = [
{ region: "NA", url: "usr.mathsiscoolfun.com:8001" },
{ region: "EU", url: "eur.mathsiscoolfun.com:8001" },
{ region: "Asia", url: "asr.mathsiscoolfun.com:8001" },
{ region: "SA", url: "sa.mathsiscoolfun.com:8001" },
];
servers.forEach((server) => {
const pingTest = new PingTest(server);
pingTest.startPingTest();
const intervalId = globalThis.setInterval(() => {
const pingResult = pingTest.getPingResult();
if (pingResult.ping !== 9999 && pingResult.ping !== null) {
const optionElement = serverSelect.querySelector(`option[value="${server.region.toLowerCase()}"]`);
if (optionElement) {
updateOptionWithPing(optionElement, pingResult.ping);
}
clearInterval(intervalId);
}
}, 2000);
});
}
}
const gameMod = new GameMod();