Enables the attack button on profile pages and mini-profiles even if the target is in the hospital or otherwise unable to be attacked.
// ==UserScript==
// @name Torn Attack Enabler
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Enables the attack button on profile pages and mini-profiles even if the target is in the hospital or otherwise unable to be attacked.
// @author Deviyl[3722358]
// @match https://www.torn.com/*
// @icon https://raw.githubusercontent.com/deviyl/media/refs/heads/main/icons/devicon.png
// @grant none
// @license MIT
// @run-at document-start
// ==/UserScript==
// Donations are always appreciated if you find this helpful. <3
(function() {
'use strict';
function enableAttackButton(button) {
if (!button) return;
if (button.dataset.enablerProcessed) return;
let isOriginallyDisabled = button.classList.contains('disabled');
const buttonDisabledClass = Array.from(button.classList).some(cls => cls.includes('disabled___') || cls.includes('_disabled___'));
if (buttonDisabledClass) isOriginallyDisabled = true;
const svgIcon = button.querySelector('svg');
if (svgIcon && !isOriginallyDisabled) {
const svgDisabledClass = Array.from(svgIcon.classList).some(cls => cls.includes('disabled___') || cls.includes('_disabled___') || cls.toLowerCase().includes('disabled'));
if (svgDisabledClass) isOriginallyDisabled = true;
}
if (!isOriginallyDisabled) return;
button.classList.remove('disabled');
const elementsToClean = svgIcon ? [button, svgIcon] : [button];
elementsToClean.forEach(el => {
const classesToRemove = Array.from(el.classList).filter(cls => cls.includes('disabled___') || cls.includes('_disabled___'));
classesToRemove.forEach(cls => el.classList.remove(cls));
});
button.style.setProperty('pointer-events', 'auto', 'important');
button.style.setProperty('cursor', 'pointer', 'important');
button.style.setProperty('opacity', '1', 'important');
if (svgIcon) {
svgIcon.style.setProperty('opacity', '1', 'important');
svgIcon.style.setProperty('fill', '#ff3b30', 'important');
}
button.dataset.enablerProcessed = 'true';
const clonedButton = button.cloneNode(true);
clonedButton.style.setProperty('pointer-events', 'auto', 'important');
clonedButton.style.setProperty('cursor', 'pointer', 'important');
clonedButton.style.setProperty('opacity', '1', 'important');
clonedButton.addEventListener('click', function(e) {
e.stopPropagation();
const href = clonedButton.getAttribute('href');
if (href) window.location.href = href;
}, true);
button.parentNode.replaceChild(clonedButton, button);
}
function scanAndModify() {
const attackButtons = document.querySelectorAll('a[href*="sid=attack"][class*="profile-button-attack"]');
attackButtons.forEach(button => { enableAttackButton(button); });
}
const observer = new MutationObserver(() => { scanAndModify(); });
const startObserver = () => {
if (document.body) {
observer.observe(document.body, {
childList: true,
subtree: true
});
scanAndModify();
} else setTimeout(startObserver, 50);
};
startObserver();
setInterval(scanAndModify, 1000);
})();