// ==UserScript==
// @name Crosshair Mod
// @namespace http://tampermonkey.net/
// @version 1
// @description Custom crosshairs for Sploop.io
// @author You
// @match https://sploop.io/*
// @grant none
// @license MIT
// @run-at document-end
// @downloadURL none
// ==/UserScript==
(function () {
'use strict';
const style = document.createElement('style');
style.textContent = `
* {
font-family: 'Segoe UI', sans-serif;
}
#hookx-ui {
position: fixed;
top: 50px;
left: 50px;
width: 300px;
background: rgba(20, 20, 20, 0.95);
border-radius: 10px;
color: white;
z-index: 100000;
box-shadow: 0 0 12px rgba(0,0,0,0.6);
padding: 15px;
}
.hookx-select, .hookx-color {
margin-top: 10px;
width: 100%;
padding: 5px;
background: #111;
color: white;
border: 1px solid #333;
border-radius: 5px;
}
.crosshair {
position: fixed;
z-index: 99999;
pointer-events: none;
display: none;
transform: translate(-50%, -50%);
will-change: transform;
}
.crosshair.dot {
width: 12px;
height: 12px;
border-radius: 50%;
}
.crosshair.cross {
width: 20px;
height: 20px;
}
.crosshair.cross::before, .crosshair.cross::after {
content: '';
position: absolute;
background-color: currentColor;
}
.crosshair.cross::before {
top: 50%;
left: 0;
width: 100%;
height: 2px;
transform: translateY(-50%);
}
.crosshair.cross::after {
top: 0;
left: 50%;
width: 2px;
height: 100%;
transform: translateX(-50%);
}
.crosshair.spike {
width: 48px;
height: 48px;
background-image: url("https://sploop.io/img/entity/hard_spike.png");
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
.crosshair.square {
width: 14px;
height: 14px;
border: 2px solid;
}
.crosshair.triangle {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 18px solid currentColor;
}
.crosshair.xcross {
width: 20px;
height: 20px;
}
.crosshair.xcross::before, .crosshair.xcross::after {
content: '';
position: absolute;
width: 2px;
height: 100%;
background-color: currentColor;
left: 50%;
top: 0;
transform-origin: center;
}
.crosshair.xcross::before {
transform: rotate(45deg);
}
.crosshair.xcross::after {
transform: rotate(-45deg);
}
body.hide-cursor * {
cursor: none !important;
}
`;
document.head.appendChild(style);
const ui = document.createElement('div');
ui.id = 'hookx-ui';
ui.innerHTML = `
`;
document.body.appendChild(ui);
let crosshair = document.createElement('div');
crosshair.className = 'crosshair dot';
document.body.appendChild(crosshair);
const toggle = document.getElementById('toggleCrosshair');
const styleSelect = document.getElementById('crosshairStyle');
const colorPicker = document.getElementById('crosshairColor');
function throttle(fn, wait) {
let lastCall = 0;
return function (...args) {
const now = performance.now();
if (now - lastCall >= wait) {
lastCall = now;
fn(...args);
}
};
}
function debounce(fn, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => fn(...args), wait);
};
}
function setCrosshairStyle(styleName) {
const newCrosshair = document.createElement('div');
newCrosshair.className = 'crosshair ' + styleName;
document.body.replaceChild(newCrosshair, crosshair);
crosshair = newCrosshair;
updateColor();
if (toggle.checked) {
crosshair.style.display = 'block';
}
}
toggle.addEventListener('change', () => {
if (toggle.checked) {
crosshair.style.display = 'block';
document.body.classList.add('hide-cursor');
document.addEventListener('mousemove', throttledMoveCrosshair);
} else {
crosshair.style.display = 'none';
document.body.classList.remove('hide-cursor');
document.removeEventListener('mousemove', throttledMoveCrosshair);
}
});
styleSelect.addEventListener('change', () => {
setCrosshairStyle(styleSelect.value);
});
const debouncedUpdateColor = debounce(updateColor, 100);
colorPicker.addEventListener('input', debouncedUpdateColor);
function updateColor() {
const color = colorPicker.value;
crosshair.style.backgroundColor = '';
crosshair.style.borderColor = '';
crosshair.style.color = color;
if (crosshair.classList.contains('dot')) {
crosshair.style.backgroundColor = color;
} else if (crosshair.classList.contains('cross') || crosshair.classList.contains('xcross')) {
crosshair.style.background = 'transparent';
} else if (crosshair.classList.contains('square')) {
crosshair.style.borderColor = color;
crosshair.style.background = 'transparent';
}
}
const throttledMoveCrosshair = throttle((e) => {
crosshair.style.transform = `translate(${e.clientX}px, ${e.clientY}px) translate(-50%, -50%)`;
}, 16);
})();