NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name ct hats
// @namespace torn.com
// @version 1.2
// @author Ahab [1735214]
// @include *torn.com/christmas_town*
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @run-at document-start
// ==/UserScript==
window.changeHat = function(newHat) {
localStorage.setItem('ctHat', newHat);
window.hat = newHat;
location.reload();
};
const code = `
window.hat = parseInt(localStorage.getItem('ctHat')) || null;
const originalFetch = window.fetch;
window.fetch = async function(...args) {
const response = await originalFetch(...args);
if ((args[0] && args[0].includes && args[0].includes('init')) || (args[0] && args[0].includes && args[0].includes('move'))) {
return response.clone().text().then(text => {
try {
const newResponse = JSON.parse(text);
if (!newResponse.error) {
newResponse.mapData.user.hat = window.hat;
return new Response(JSON.stringify(newResponse), {
status: response.status,
statusText: response.statusText,
headers: response.headers
});
} else {
return response;
}
} catch (e) {
return response;
}
});
} else {
return response;
}
};
`
const hats = {1:'-4px 0', 2:'-24px 0', 3:'-44px 0', 4:'-64px 0', 5:'-84px 0', 6:'-104px 0', 7:'-124px 0', 8:'-144px 0', 9:'-164px 0', 10:'-184px 0', 11:'-204px 0', 12:'-224px 0'}
var observer = new MutationObserver(function(mutations, obs) {
var target = document.querySelector(".ct-wrap");
if (target) {
var menu = ""
for (var i = 1; i <= 12; i++) {
menu += "<div class='hat-wrapper' style='display: flex; align-items: center; justify-content: center; width: 24px; height: 20px; margin-right: 5px; cursor: pointer;'><div id='hat"+i+"' class='hat' style='transform: scale(2); background-image: url(/images/v2/christmas_town/avatar-hats/avatar_hats_map.png); background-position:"+hats[i]+"; width: 12px; height: 10px; image-rendering: pixelated;'></div></div>"
};
target.insertAdjacentHTML('beforeBegin', "<span id='hats' style='display: flex; align-items: center;'>"+menu+"</span>");
document.querySelector("#hats").insertAdjacentHTML('beforeEnd', '<button id="removeHat" style="margin: 0 0 5px 5px; cursor: pointer; border-radius: 4px; border: 1px solid #444; background: #333; color: #fff; font-weight: bold;">Remove Hat</button>')
obs.disconnect();
}
})
observer.observe(document.documentElement, {
childList: true,
subtree: true
});
document.addEventListener('click', function(event) {
const wrapper = event.target.closest('.hat-wrapper');
if (wrapper) {
const hatIcon = wrapper.querySelector('.hat');
if (hatIcon && hatIcon.id) {
const match = hatIcon.id.match(/hat(\d+)/);
if (match) {
const hatNumber = match[1];
window.changeHat(hatNumber);
}
}
}
});
document.addEventListener('touchend', function(event) {
const wrapper = event.target.closest('.hat-wrapper');
if (wrapper) {
const hatIcon = wrapper.querySelector('.hat');
if (hatIcon && hatIcon.id) {
const match = hatIcon.id.match(/hat(\d+)/);
if (match) {
const hatNumber = match[1];
window.changeHat(hatNumber);
}
}
}
});
document.addEventListener('click', function(e) {
if (e.target.id === 'removeHat') {
e.target.innerText = "Saving...";
window.changeHat(null);
}
});
const script = document.createElement('script');
script.textContent = code;
(document.head || document.documentElement).appendChild(script);
script.remove();