// ==UserScript==
// @name Sploop.io Tracers
// @author Murka
// @description Draws tracers on enemies, teammates and animals
// @icon https://sploop.io/img/ui/favicon.png
// @version 0.2
// @match *://sploop.io/*
// @run-at document-start
// @grant none
// @license MIT
// @namespace https://greasyfork.org/users/919633
// ==/UserScript==
/* jshint esversion:6 */
/*
Author: Murka
Github: https://github.com/Murka007
Discord: https://discord.gg/sG9cyfGPj5
Greasyfork: https://greasyfork.org/en/users/919633
Description:
- Draws tracers at enemies, teammates and animals
- You can choose your tracers mode, `ARROWS` or `LINES`
- If you will have any issues with this script, report about it in my discord
*/
(function() {
"use strict";
// Customize tracers by changing values
window.tracers = {
mode: "ARROWS", // ARROWS, LINES
color: {
teammate: "#a4cc4f",
enemy: "#cc5151"
}
};
const log = console.log;
function createHook(target, prop, setter) {
if (!window.hooks) {
window.hooks = {
setter: [],
getter: []
};
}
window.hooks.setter.push(setter);
const symbol = Symbol(prop);
Object.defineProperty(target, prop, {
get() {
return this[symbol];
},
set(value) {
for (const setter of window.hooks.setter) {
setter(this, symbol, value);
}
},
configurable: true
})
}
const myPlayer = {
id: null,
data: null
};
// Get player id
window.WebSocket = new Proxy(WebSocket, {
construct(target, args) {
const socket = new target(...args);
socket.addEventListener("message", function(event) {
try {
const data = JSON.parse(event.data);
if (data[0] === 35) {
myPlayer.id = data[1];
}
} catch(err) {}
})
return socket;
}
})
createHook(Object.prototype, "i", function(that, symbol, value) {
that[symbol] = value;
if (myPlayer.id === value) myPlayer.data = that;
});
function formatPosition(args) {
const [ img, x, y ] = args;
return {
x: x + 0.5 * img.width / 2,
y: y - 67.5
};
}
function triangle(ctx, x, y, width, height, angle, color) {
ctx.save();
ctx.translate(x, y);
ctx.rotate(angle);
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(width, 0);
ctx.lineTo(0, -height);
ctx.lineTo(-width, 0);
ctx.closePath();
ctx.fill();
ctx.restore();
}
function lines(ctx, x1, y1, x2, y2, color) {
ctx.save();
ctx.strokeStyle = color;
ctx.lineCap = "round";
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
ctx.restore();
}
const COLOR = {
TEAMMATE: "#a4cc4f",
ENEMY: "#cc5151"
};
// drawImage is called when the game draws a health gauge
CanvasRenderingContext2D.prototype.drawImage = new Proxy(CanvasRenderingContext2D.prototype.drawImage, {
apply(target, _this, args) {
const data = target.apply(_this, args);
const [ img, x, y, w, h ] = args;
if (
img instanceof HTMLCanvasElement &&
[COLOR.TEAMMATE, COLOR.ENEMY].includes(_this.fillStyle) &&
myPlayer.data !== null &&
w === img.width * 0.5 &&
h === img.height * 0.5
) {
const { gU: x1, gV: y1 } = myPlayer.data;
const { x: x2, y: y2 } = formatPosition(args);
const angle = Math.atan2(y2 - y1, x2 - x1);
const isMyPlayer = angle === -Math.PI/2 && _this.fillStyle === COLOR.TEAMMATE;
const { teammate, enemy } = window.tracers.color;
const color = _this.fillStyle === COLOR.TEAMMATE ? teammate : enemy;
if (!isMyPlayer) {
const x = x1 + 80 * Math.cos(angle);
const y = y1 + 80 * Math.sin(angle);
switch (window.tracers.mode) {
case "ARROWS":
triangle(_this, x, y, 15, 40, angle + Math.PI / 2, color);
break;
case "LINES":
lines(_this, x1, y1, x2, y2, color);
break;
}
}
}
return data;
}
})
})();