NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Halloween Chainer
// @version 1.4
// @namespace http://tampermonkey.net/
// @description Adds a Chain button and a minimizable UI for weapon and outcome selection.
// @author Omanpx [1906686] & Brother [2590792]
// @match https://www.torn.com/*
// @grant none
// @license AGPL-3.0-only
// @updateURL https://openuserjs.org/meta/brother-torn/Halloween_Chainer.meta.js
// ==/UserScript==
(function() {
'use strict';
// --- CONFIGURATION ---
const minID = 3500000;
const maxID = 3900000;
// --- END CONFIGURATION ---
function createUI() {
const controlContainer = document.createElement('div');
controlContainer.style.position = 'fixed';
controlContainer.style.top = '20%';
controlContainer.style.left = '10px';
controlContainer.style.zIndex = '9998';
controlContainer.style.backgroundColor = 'rgba(10, 10, 10, 0.8)';
controlContainer.style.padding = '10px';
controlContainer.style.borderRadius = '8px';
controlContainer.style.display = 'flex';
controlContainer.style.flexDirection = 'column';
controlContainer.style.gap = '10px';
controlContainer.style.border = '1px solid #444';
const uiHeader = document.createElement('div');
uiHeader.style.display = 'flex';
uiHeader.style.justifyContent = 'space-between';
uiHeader.style.alignItems = 'center';
const title = document.createElement('span');
title.textContent = 'Controls';
title.style.color = 'white';
title.style.fontWeight = 'bold';
title.style.userSelect = 'none';
const toggleButton = document.createElement('button');
toggleButton.style.backgroundColor = '#555';
toggleButton.style.color = 'white';
toggleButton.style.border = '1px solid #777';
toggleButton.style.borderRadius = '4px';
toggleButton.style.padding = '2px 4px';
toggleButton.style.cursor = 'pointer';
toggleButton.style.fontWeight = 'bold';
uiHeader.appendChild(title);
uiHeader.appendChild(toggleButton);
const dropdownWrapper = document.createElement('div');
dropdownWrapper.style.display = 'flex';
dropdownWrapper.style.flexDirection = 'column';
dropdownWrapper.style.gap = '5px';
const createDropdown = (id, labelText, options) => {
const wrapper = document.createElement('div');
const label = document.createElement('label');
label.setAttribute('for', id);
label.textContent = labelText;
label.style.color = 'white';
label.style.fontWeight = 'bold';
label.style.display = 'block';
label.style.marginBottom = '4px';
const select = document.createElement('select');
select.id = id;
select.style.width = '120px';
select.style.padding = '4px';
select.style.borderRadius = '4px';
select.style.border = '1px solid #555';
select.style.backgroundColor = '#333';
select.style.color = 'white';
for (const [text, value] of Object.entries(options)) {
const option = document.createElement('option');
option.value = value;
option.textContent = text;
select.appendChild(option);
}
wrapper.appendChild(label);
wrapper.appendChild(select);
return { wrapper, select };
};
const weaponOptions = { 'Secondary': 'secondary', 'Primary': 'primary', 'Melee': 'melee' };
const outcomeOptions = { 'Leave': 'leave', 'Mug': 'mug', 'Hospitalize': 'hospitalize' };
const { wrapper: weaponWrapper, select: weaponSelect } = createDropdown('chainHelperWeapon', 'Weapon:', weaponOptions);
const { wrapper: outcomeWrapper, select: outcomeSelect } = createDropdown('chainHelperOutcome', 'Outcome:', outcomeOptions);
dropdownWrapper.appendChild(weaponWrapper);
dropdownWrapper.appendChild(outcomeWrapper);
controlContainer.appendChild(uiHeader);
controlContainer.appendChild(dropdownWrapper);
document.body.appendChild(controlContainer);
const savedWeapon = localStorage.getItem('chainHelperWeapon');
const savedOutcome = localStorage.getItem('chainHelperOutcome');
if (savedWeapon) weaponSelect.value = savedWeapon;
if (savedOutcome) outcomeSelect.value = savedOutcome;
weaponSelect.addEventListener('change', () => localStorage.setItem('chainHelperWeapon', weaponSelect.value));
outcomeSelect.addEventListener('change', () => localStorage.setItem('chainHelperOutcome', outcomeSelect.value));
const setMinimizedState = (isMinimized) => {
dropdownWrapper.style.display = isMinimized ? 'none' : 'flex';
toggleButton.textContent = isMinimized ? '[+]' : '[-]';
localStorage.setItem('chainHelperUIMinimized', isMinimized);
};
toggleButton.addEventListener('click', () => {
const isCurrentlyMinimized = dropdownWrapper.style.display === 'none';
setMinimizedState(!isCurrentlyMinimized);
});
const isInitiallyMinimized = localStorage.getItem('chainHelperUIMinimized') === 'true';
setMinimizedState(isInitiallyMinimized);
}
function getRandomNumber(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function findNewTarget() {
let randID = getRandomNumber(minID, maxID);
let attackLink = `https://www.torn.com/loader.php?sid=attack&user2ID=${randID}`;
window.location.href = attackLink;
}
const chainButton = document.createElement('button');
chainButton.innerHTML = 'Chain';
chainButton.style.position = 'fixed';
chainButton.style.top = '27%';
chainButton.style.right = '0%';
chainButton.style.zIndex = '9999';
chainButton.style.backgroundColor = '#4CAF50';
chainButton.style.color = 'white';
chainButton.style.border = 'none';
chainButton.style.padding = '8px 12px';
chainButton.style.borderRadius = '6px';
chainButton.style.cursor = 'pointer';
chainButton.style.fontSize = '14px';
chainButton.style.fontWeight = 'bold';
chainButton.addEventListener('click', function() {
const startFightButton = document.querySelector('.defender___niX1M .dialogButtons___nX4Bz button');
if (startFightButton && startFightButton.innerText.toLowerCase().includes('start fight')) {
startFightButton.click();
return;
}
const postFightContainer = document.querySelector('.defender___niX1M .dialogButtons___nX4Bz');
if (postFightContainer) {
const outcomeButtons = Array.from(postFightContainer.querySelectorAll('button'));
const isPostFight = outcomeButtons.some(btn => btn.innerText.toLowerCase() === 'mug');
if (isPostFight) {
const desiredOutcome = document.getElementById('chainHelperOutcome').value;
const targetButton = outcomeButtons.find(btn => btn.innerText.toLowerCase() === desiredOutcome);
if (targetButton) {
targetButton.click();
} else {
outcomeButtons.find(btn => btn.innerText.toLowerCase() === 'leave')?.click();
}
return;
}
}
const preferredWeapon = document.getElementById('chainHelperWeapon').value;
const weaponSelectorMap = {
'primary': '#weapon_main',
'secondary': '#weapon_second',
'melee': '#weapon_melee'
};
const weaponSelector = weaponSelectorMap[preferredWeapon] || '#weapon_second';
const chosenWeapon = document.querySelector(weaponSelector);
const fightStarted = document.querySelector(`${weaponSelector}.attackStarted___iMM2u`);
if (chosenWeapon && fightStarted) {
chosenWeapon.click();
return;
}
findNewTarget();
});
document.body.appendChild(chainButton);
createUI();
})();