Randomizes your selected items
// ==UserScript==
// @name Nitro Type - Loadout Randomizer
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Randomizes your selected items
// @author thisisks
// @match https://www.nitrotype.com/race*
// @match https://www.nitrotype.com/garage/customizer*
// @run-at document-start
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const isRace = location.pathname.startsWith("/race");
const isCustomizer = location.pathname.startsWith("/garage/customizer");
// -----------------------------
// CORE RANDOMIZER (shared)
// -----------------------------
async function runRandomizer() {
const random = (arr) => arr[Math.floor(Math.random() * arr.length)];
const raw = localStorage.getItem("persist:nt");
if (!raw) return console.error("persist:nt not found");
const parsed = JSON.parse(raw);
let dataKey = null;
let data = null;
for (const key in parsed) {
try {
const obj = JSON.parse(parsed[key]);
if (obj && obj.cars && obj.loot) {
data = obj;
dataKey = key;
break;
}
} catch {}
}
if (!data) return console.error("Player data not found");
const cars = data.cars.map(c => ({
id: c[0],
hueAngle: c[2] || 0
}));
const trails = data.loot.filter(l => l.type === "trail");
const nitros = data.loot.filter(l => l.type === "nitro");
const nametags = data.loot.filter(l => l.type === "nametag");
const titles = data.loot.filter(l => l.type === "title");
const car = random(cars);
const trail = random(trails);
const nitro = random(nitros);
const nametag = random(nametags);
const title = random(titles);
const perk = Math.random() < 0.5 ? 1 : 0;
data.carID = car.id;
data.carHueAngle = car.hueAngle;
data.title = title.name;
data.disablePerk = perk;
const typesToHandle = ["trail", "nitro", "nametag"];
data.loot.forEach(item => {
if (typesToHandle.includes(item.type)) {
item.equipped = 0;
}
});
data.loot.forEach(item => {
if (item.type === "trail" && item.lootID === trail.lootID) item.equipped = 1;
if (item.type === "nitro" && item.lootID === nitro.lootID) item.equipped = 1;
if (item.type === "nametag" && item.lootID === nametag.lootID) item.equipped = 1;
});
parsed[dataKey] = JSON.stringify(data);
localStorage.setItem("persist:nt", JSON.stringify(parsed));
const payload = [
{ id: car.id, hueAngle: car.hueAngle, type: "car" },
{ id: trail.lootID, type: "trail" },
{ id: nitro.lootID, type: "nitro" },
{ id: nametag.lootID, type: "nametag" },
{ id: title.lootID, type: "title" },
{ disablePerk: perk, type: "perk" }
];
const token = localStorage.getItem("player_token");
await fetch("https://www.nitrotype.com/api/v2/loot/equip", {
method: "POST",
headers: {
authorization: `Bearer ${token}`,
"content-type": "application/json"
},
body: JSON.stringify(payload),
credentials: "include"
});
console.log("Randomized & saved");
}
// -----------------------------
// FIX: race-safe execution (wait for data)
// -----------------------------
function runOnRaceWhenReady() {
let tries = 0;
const interval = setInterval(() => {
tries++;
const raw = localStorage.getItem("persist:nt");
if (raw) {
clearInterval(interval);
runRandomizer();
return;
}
// stop after ~10s to avoid infinite loop
if (tries > 50) {
clearInterval(interval);
console.error("Timed out waiting for persist:nt");
}
}, 200);
}
// -----------------------------
// CUSTOMIZER BUTTON
// -----------------------------
function injectButton() {
const nav = document.querySelector(".customizer--tabs.nav-list");
if (!nav || document.querySelector("#nt-randomizer-btn")) return;
const btn = document.createElement("div");
btn.id = "nt-randomizer-btn";
btn.className = "nav-list-item customizer--tab";
btn.innerHTML = `
<div class="customizer--tab--content">
<div class="customizer--tab--icon">🎲</div>
<div class="customizer--tab--label">Randomize</div>
</div>
`;
btn.style.cursor = "pointer";
btn.addEventListener("click", async () => {
btn.style.opacity = "0.6";
btn.style.pointerEvents = "none";
await runRandomizer();
location.reload();
});
nav.appendChild(btn);
}
// -----------------------------
// ROUTER
// -----------------------------
if (isRace) {
runOnRaceWhenReady();
}
if (isCustomizer) {
const obs = new MutationObserver(injectButton);
obs.observe(document.documentElement, { childList: true, subtree: true });
injectButton();
}
})();