Shows target's networth on the attack page before attacking
// ==UserScript==
// @name Torn Attack Networth Display
// @namespace torn.networth.attack
// @version 1.3
// @description Shows target's networth on the attack page before attacking
// @match https://www.torn.com/loader.php?sid=attack*
// @grant GM_getValue
// @grant GM_setValue
// @grant unsafeWindow
// ==/UserScript==
(function () {
'use strict';
function getApiKey() {
var pdaKey = '###PDA-APIKEY###';
// If PDA replaced the placeholder, use that
if (pdaKey !== '###PDA-APIKEY###') {
return pdaKey;
}
// Browser fallback: check stored key
try {
var stored = GM_getValue('torn_api_key', '');
if (stored) return stored;
} catch (e) {
// GM functions not available
}
// Prompt user once
var win = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
var input = win.prompt('Enter your Torn API key (public access is fine):');
if (input && input.trim().length === 16) {
try {
GM_setValue('torn_api_key', input.trim());
} catch (e) {
// Can't persist, will ask again next time
}
return input.trim();
}
return null;
}
var API_KEY = getApiKey();
if (!API_KEY) return;
function getUserID() {
const params = new URLSearchParams(window.location.search);
return params.get('user2ID');
}
function formatMoney(amount) {
if (amount >= 1e12) return '$' + (amount / 1e12).toFixed(2) + 'T';
if (amount >= 1e9) return '$' + (amount / 1e9).toFixed(2) + 'B';
if (amount >= 1e6) return '$' + (amount / 1e6).toFixed(2) + 'M';
if (amount >= 1e3) return '$' + (amount / 1e3).toFixed(2) + 'K';
return '$' + amount.toLocaleString();
}
function createDisplay(networth, status) {
var container = document.createElement('div');
container.id = 'nw-display';
container.style.cssText =
'padding: 8px 12px; margin: 8px 0; border-radius: 5px; font-size: 13px; font-weight: bold; text-align: center;';
if (status === 'ok') {
container.style.background = '#1a1a2e';
container.style.color = '#e0e0e0';
container.style.border = '1px solid #333';
container.textContent = 'Networth: ' + formatMoney(networth);
} else {
container.style.background = '#2e1a1a';
container.style.color = '#cc8888';
container.style.border = '1px solid #442222';
container.textContent = 'Networth: ' + status;
}
return container;
}
function injectDisplay(element) {
// Insert above the Start fight button inside the dialog
var dialogButtons = document.querySelector('[class*="dialogButtons"]');
if (dialogButtons) {
dialogButtons.parentNode.insertBefore(element, dialogButtons);
return true;
}
// Fallback: insert at the top of the dialog wrapper
var dialogWrapper = document.querySelector('[class*="dialogWrapper"]');
if (dialogWrapper) {
dialogWrapper.insertBefore(element, dialogWrapper.firstChild);
return true;
}
return false;
}
function tryInject(element, attempts) {
if (attempts <= 0) return;
if (!injectDisplay(element)) {
setTimeout(function () {
tryInject(element, attempts - 1);
}, 500);
}
}
function init() {
var userID = getUserID();
if (!userID) return;
var url =
'https://api.torn.com/user/' +
userID +
'?selections=personalstats&stat=networth&key=' +
API_KEY;
fetch(url)
.then(function (res) {
return res.json();
})
.then(function (data) {
if (data.error) {
var display = createDisplay(null, 'API error: ' + data.error.error);
tryInject(display, 10);
return;
}
var networth = null;
// Handle different response structures
if (data.personalstats && data.personalstats.networth) {
networth = data.personalstats.networth;
} else if (data.personalstats && typeof data.personalstats.networth === 'number') {
networth = data.personalstats.networth;
}
var display;
if (networth !== null) {
display = createDisplay(networth, 'ok');
} else {
display = createDisplay(null, 'Unavailable');
}
tryInject(display, 10);
})
.catch(function (err) {
var display = createDisplay(null, 'Fetch failed');
tryInject(display, 10);
});
}
init();
})();