Provide you with the task of the mission before accepting, and sometimes also an additional hint.
// ==UserScript==
// @name TORN: TornTools - Mission Hints
// @namespace torntools.mission-hints
// @version 1.1.1
// @author DeKleineKobini [2114440] and the TornTools team
// @description Provide you with the task of the mission before accepting, and sometimes also an additional hint.
// @license GPL-3.0-or-later
// @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @supportURL https://github.com/Mephiles/torntools_extension/issues
// @match https://*.torn.com/page.php?sid=missions*
// @grant GM.info
// @grant GM_addStyle
// @grant unsafeWindow
// @run-at document-end
// @contributionURL https://buymeacoffee.com/dekleinekobini
// ==/UserScript==
(function() {
"use strict";
var s = new Set();
var _css = async (t) => {
if (s.has(t)) return;
s.add(t);
((c) => {
if (typeof GM_addStyle === "function") GM_addStyle(c);
else (document.head || document.documentElement).appendChild(document.createElement("style")).append(c);
})(t);
};
var FEATURE_MANAGER;
var ttStorage;
var SCRIPT_INJECTOR;
var RUNTIME_INFORMATION;
var EVENT_HANDLER;
function setFeatureManager(featureManager) {
FEATURE_MANAGER = featureManager;
}
function setScriptInjector(scriptInjector) {
SCRIPT_INJECTOR = scriptInjector;
}
function setRuntimeInformation(runtimeInformation) {
RUNTIME_INFORMATION = runtimeInformation;
}
function setEventHandler(eventHandler) {
EVENT_HANDLER = eventHandler;
}
_css(".tt-loading-placeholder{margin:0 auto;padding:10px}body:not(.dark-mode) .tt-loading-placeholder{content:url(https://www.torn.com/images/v2/main/ajax-loader.gif)}body.dark-mode .tt-loading-placeholder{content:url(https://www.torn.com/images/v2/main/ajax-loader-white.gif)}.tt-loading-placeholder:not(.active){display:none}.tt-sidebar-information{padding-block:4px}");
function requireDOMInteractive() {
return new Promise((resolve) => {
if (document.readyState === "loading") document.addEventListener("readystatechange", () => resolve(), { once: true });
else resolve();
});
}
var mobile;
var tablet;
var hasSidebar;
var tabletHorizontal;
var tabletVertical;
function elementBuilder(options) {
if (typeof options === "string") return document.createElement(options);
else if (typeof options === "object") {
options = {
id: void 0,
class: void 0,
text: void 0,
html: void 0,
value: void 0,
href: void 0,
children: [],
attributes: {},
events: {},
style: {},
dataset: {},
...options
};
const newElement = document.createElement(options.type);
if (options.id) newElement.id = options.id;
if (options.class) newElement.className = Array.isArray(options.class) ? options.class.filter((name) => !!name).join(" ") : options.class.trim();
if (options.text !== void 0) newElement.textContent = options.text.toString();
if (options.html) newElement.innerHTML = options.html;
if (options.value && "value" in newElement) {
if (typeof options.value === "function") newElement.value = options.value();
else newElement.value = options.value;
}
if (options.href && "href" in newElement) newElement.href = options.href;
for (const child of options.children?.filter((child) => !!child) || []) if (typeof child === "string") newElement.appendChild(document.createTextNode(child));
else newElement.appendChild(child);
if (options.attributes) {
let attributes = options.attributes;
if (typeof attributes === "function") attributes = attributes();
for (const attribute in attributes) newElement.setAttribute(attribute, attributes[attribute].toString());
}
for (const event in options.events) newElement.addEventListener(event, options.events[event]);
for (const key in options.style) newElement.style[key] = options.style[key];
for (const key in options.dataset) if (typeof options.dataset[key] === "object") newElement.dataset[key] = JSON.stringify(options.dataset[key]);
else newElement.dataset[key] = options.dataset[key].toString();
return newElement;
} else throw new Error("Invalid options provided to newElement.");
}
function findAllElements(selector, parent = document) {
return Array.from(parent.querySelectorAll(selector));
}
async function checkDevice() {
await requireDOMInteractive();
const innerWidth = window.innerWidth;
mobile = innerWidth <= 600;
tablet = innerWidth <= 1e3 && innerWidth >= 600;
hasSidebar = innerWidth > 1e3;
tabletHorizontal = tablet && innerWidth >= 784;
tabletVertical = tablet && !tabletHorizontal;
return {
mobile,
tablet,
tabletHorizontal,
tabletVertical,
hasSidebar
};
}
function findParent(element, partialOptions = {}) {
const options = {
tag: void 0,
class: void 0,
partialClass: void 0,
id: void 0,
hasAttribute: void 0,
maxAttempts: -1,
currentAttempt: 1,
...partialOptions
};
if (!element?.parentElement) return void 0;
if (options.maxAttempts !== -1 && options.currentAttempt > options.maxAttempts) return void 0;
if (options.tag && element.parentElement.tagName === options.tag) return element.parentElement;
if (options.id && element.parentElement.id === options.id) return element.parentElement;
if (options.class && element.parentElement && (Array.isArray(options.class) && options.class.some((c) => element.parentElement.classList.contains(c)) || !Array.isArray(options.class) && element.parentElement.classList.contains(options.class))) return element.parentElement;
if (options.partialClass && Array.from(element.parentElement.classList).some((c) => c.startsWith(options.partialClass))) return element.parentElement;
if (options.hasAttribute && element.parentElement.getAttribute(options.hasAttribute) !== null) return element.parentElement;
return findParent(element.parentElement, {
...options,
currentAttempt: (options.currentAttempt ?? 0) + 1
});
}
function isCustomEvent(event) {
return event instanceof CustomEvent;
}
(() => {
if (typeof window === "undefined" || window.location.href.endsWith("/_generated_background_page.html")) return "BACKGROUND";
else if (typeof browser === "object" && browser.action) return "POPUP";
else if (typeof location !== "undefined" && location.protocol?.includes("extension")) return "INTERNAL_CONTENT";
else return "CONTENT";
})();
function isIntNumber(number) {
if (number === null) return false;
if (number.match(/[a-zA-Z]/)) return false;
const _number = parseFloat(number);
return !Number.isNaN(_number) && Number.isFinite(_number) && _number % 1 === 0;
}
function isTabFocused() {
return document.hasFocus();
}
var EVENT_CHANNELS = function(EVENT_CHANNELS) {
EVENT_CHANNELS["CHAT_MESSAGE"] = "chat-message";
EVENT_CHANNELS["CHAT_NEW"] = "chat-box-new";
EVENT_CHANNELS["CHAT_OPENED"] = "chat-box-opened";
EVENT_CHANNELS["CHAT_PEOPLE_MENU_OPENED"] = "chat-people-menu-opened";
EVENT_CHANNELS["CHAT_SETTINGS_MENU_OPENED"] = "chat-settings-menu-opened";
EVENT_CHANNELS["CHAT_REFRESHED"] = "chat-refreshed";
EVENT_CHANNELS["CHAT_RECONNECTED"] = "chat-reconnected";
EVENT_CHANNELS["CHAT_CLOSED"] = "chat-closed";
EVENT_CHANNELS["COMPANY_EMPLOYEES_PAGE"] = "company-employees-page";
EVENT_CHANNELS["COMPANY_STOCK_PAGE"] = "company-stock-page";
EVENT_CHANNELS["FACTION_ARMORY_TAB"] = "faction-armory-tab";
EVENT_CHANNELS["FACTION_CRIMES"] = "faction-crimes";
EVENT_CHANNELS["FACTION_CRIMES2"] = "faction-crimes2";
EVENT_CHANNELS["FACTION_CRIMES2_TAB"] = "faction-crimes2-tab";
EVENT_CHANNELS["FACTION_CRIMES2_REFRESH"] = "faction-crimes2-refresh";
EVENT_CHANNELS["FACTION_GIVE_TO_USER_PAGE"] = "faction-give-to-user-page";
EVENT_CHANNELS["FACTION_UPGRADE_INFO"] = "faction-upgrade-info";
EVENT_CHANNELS["FACTION_INFO"] = "faction-info";
EVENT_CHANNELS["FACTION_MAIN"] = "faction-main";
EVENT_CHANNELS["FACTION_NATIVE_FILTER"] = "faction-filter_native";
EVENT_CHANNELS["FACTION_NATIVE_SORT"] = "faction-sort_native";
EVENT_CHANNELS["FACTION_NATIVE_ICON_UPDATE"] = "faction-icon_update_native";
EVENT_CHANNELS["FF_SCOUTER_GAUGE"] = "ff-scouter-gauge";
EVENT_CHANNELS["FF_SCOUTER_FACTION_LIST"] = "ff-scouter-faction-list";
EVENT_CHANNELS["ITEM_AMOUNT"] = "item-amount";
EVENT_CHANNELS["ITEM_EQUIPPED"] = "item-equipped";
EVENT_CHANNELS["ITEM_ITEMS_LOADED"] = "item-items-loaded";
EVENT_CHANNELS["ITEM_SWITCH_TAB"] = "item-switch-tab";
EVENT_CHANNELS["HOSPITAL_SWITCH_PAGE"] = "hospital-switch-page";
EVENT_CHANNELS["JAIL_SWITCH_PAGE"] = "jail-switch-page";
EVENT_CHANNELS["USERLIST_SWITCH_PAGE"] = "userlist-switch-page";
EVENT_CHANNELS["TRAVEL_SELECT_TYPE"] = "travel-select-type";
EVENT_CHANNELS["TRAVEL_SELECT_COUNTRY"] = "travel-select-country";
EVENT_CHANNELS["TRAVEL_DESTINATION_UPDATE"] = "travel-destination-update";
EVENT_CHANNELS["TRAVEL_ABROAD__SHOP_LOAD"] = "TRAVEL_ABROAD__SHOP_LOAD";
EVENT_CHANNELS["TRAVEL_ABROAD__SHOP_REFRESH"] = "TRAVEL_ABROAD__SHOP_REFRESH";
EVENT_CHANNELS["FEATURE_ENABLED"] = "feature-enabled";
EVENT_CHANNELS["FEATURE_RELOADED"] = "feature-reloaded";
EVENT_CHANNELS["STATE_CHANGED"] = "state-changed";
EVENT_CHANNELS["SHOP__LOAD"] = "SHOP__LOAD";
EVENT_CHANNELS["GYM_LOAD"] = "gym-load";
EVENT_CHANNELS["GYM_TRAIN"] = "gym-train";
EVENT_CHANNELS["CRIMES_LOADED"] = "crimes-loaded";
EVENT_CHANNELS["CRIMES_CRIME"] = "crimes-crime";
EVENT_CHANNELS["CRIMES2_HOME_LOADED"] = "crimes2-home-loaded";
EVENT_CHANNELS["CRIMES2_BURGLARY_LOADED"] = "crimes2-burglary-loaded";
EVENT_CHANNELS["CRIMES2_CRIME_LOADED"] = "crimes2-crime-loaded";
EVENT_CHANNELS["MISSION_LOAD"] = "mission-load";
EVENT_CHANNELS["MISSION_REWARDS"] = "mission-rewards";
EVENT_CHANNELS["TRADE"] = "trade";
EVENT_CHANNELS["PROFILE_FETCHED"] = "profile-fetched";
EVENT_CHANNELS["FILTER_APPLIED"] = "filter-applied";
EVENT_CHANNELS["STATS_ESTIMATED"] = "stats-estimated";
EVENT_CHANNELS["SWITCH_PAGE"] = "switch-page";
EVENT_CHANNELS["AUCTION_SWITCH_TYPE"] = "auction-switch-type";
EVENT_CHANNELS["ITEMMARKET_CATEGORY_ITEMS"] = "itemmarket-category-items";
EVENT_CHANNELS["ITEMMARKET_CATEGORY_ITEMS_UPDATE"] = "itemmarket-category-items-update";
EVENT_CHANNELS["ITEMMARKET_ITEMS"] = "itemmarket-items";
EVENT_CHANNELS["ITEMMARKET_ITEMS_UPDATE"] = "itemmarket-items-update";
EVENT_CHANNELS["ITEMMARKET_ITEM_DETAILS"] = "itemmarket-item-details";
EVENT_CHANNELS["WINDOW__FOCUS"] = "WINDOW__FOCUS";
EVENT_CHANNELS["PROPERTIES__ROUTE"] = "PROPERTIES__ROUTE";
EVENT_CHANNELS["PROPERTIES__ROUTE_PAGE"] = "PROPERTIES__ROUTE_PAGE";
EVENT_CHANNELS["EFFICIENT_REHAB"] = "EFFICIENT_REHAB";
EVENT_CHANNELS["EFFICIENT_REHAB__INJECTED"] = "EFFICIENT_REHAB__INJECTED";
EVENT_CHANNELS["CITY_ITEMS_MAP__SET_ITEMS"] = "CITY_ITEMS_MAP__SET_ITEMS";
EVENT_CHANNELS["CITY_ITEMS_MAP__REQUEST_MODEL_ITEMS"] = "CITY_ITEMS_MAP__REQUEST_MODEL_ITEMS";
EVENT_CHANNELS["CITY_ITEMS_MAP__MODEL_ITEMS"] = "CITY_ITEMS_MAP__MODEL_ITEMS";
EVENT_CHANNELS["CITY_ITEMS_MAP__CLEAR"] = "CITY_ITEMS_MAP__CLEAR";
EVENT_CHANNELS["RACING__CUSTOM_RACES__LIST"] = "RACING__CUSTOM_RACES__LIST";
EVENT_CHANNELS["RACING__SELECT_CAR_CUSTOM"] = "RACING__SELECT_CAR_CUSTOM";
EVENT_CHANNELS["RACING__SELECT_CAR_CUSTOM_CREATED"] = "RACING__SELECT_CAR_CUSTOM_CREATED";
EVENT_CHANNELS["RACING__CHANGE_CAR"] = "RACING__CHANGE_CAR";
return EVENT_CHANNELS;
}({});
var ANTI_SCRAPE_EVENTS = [
"TRAVEL_ABROAD__SHOP_LOAD",
"chat-message",
"chat-box-opened",
"chat-closed",
"chat-refreshed",
"chat-reconnected",
"itemmarket-category-items",
"itemmarket-category-items-update",
"itemmarket-items",
"itemmarket-items-update"
];
function triggerCustomListener(channel, payload) {
if (ANTI_SCRAPE_EVENTS.includes(channel) && !isTabFocused()) return;
EVENT_HANDLER.triggerEvent(channel, payload);
}
function addCustomListener(channel, listener) {
EVENT_HANDLER.registerListener(channel, listener);
}
var EVENT_CHANNEL_XHR = "tt-xhr";
function hasEventDetail(event) {
return typeof event.detail !== "undefined";
}
function addXHRListener(callback) {
SCRIPT_INJECTOR.injectXHR();
window.addEventListener(EVENT_CHANNEL_XHR, (event) => {
if (!hasEventDetail(event)) return;
callback(event);
});
}
function setupMissionsPage() {
addXHRListener(async ({ detail: { page, xhr, ...detail } }) => {
if (page !== "page" || !("uri" in detail)) return;
const { uri } = detail;
let sid = new URLSearchParams(xhr.requestBody).get("sid");
if (!sid && uri && (uri.sid || uri["?sid"])) sid = uri.sid || uri["?sid"];
if (sid === "missionsRewards") new MutationObserver((_mutations, observer) => {
triggerCustomListener(EVENT_CHANNELS.MISSION_REWARDS);
observer.disconnect();
}).observe(document.querySelector("#viewMissionsRewardsContainer"), { childList: true });
else if (sid === "missions" || sid === "completeContract" || sid === "acceptMission") new MutationObserver((_mutations, observer) => {
triggerCustomListener(EVENT_CHANNELS.MISSION_LOAD);
observer.disconnect();
}).observe(document.querySelector("#missionsMainContainer"), { childList: true });
});
}
_css(".tt-mission-information{margin-top:16px}.tt-mission-information>span{display:block}.tt-mission-title{text-align:center;color:var(--tt-color-light-green);margin-bottom:4px}");
var TornToolsCache = class {
_cache;
persistTimer = null;
pendingChanges = new Map();
constructor() {
this._cache = {};
}
set cache(value) {
this._cache = value || {};
this.pendingChanges.clear();
}
syncCache(value) {
this._cache = value || {};
for (const { section, key, cacheValue, deleted } of this.pendingChanges.values()) if (section) {
if (deleted) {
if (this._cache[section]) delete this._cache[section][key];
} else {
if (!(section in this._cache)) this._cache[section] = {};
this._cache[section][key] = cacheValue;
}
} else if (deleted) delete this._cache[key];
else this._cache[key] = cacheValue;
}
get cache() {
return this._cache;
}
get(section, key) {
return this.getCacheValue(section, key)?.value;
}
remove(section, key) {
const actualKey = key ?? section;
const actualSection = key ? section : null;
if (actualSection && !this.hasValue(actualSection, actualKey) || !actualSection && !this.hasValue(actualKey.toString())) return;
if (actualSection) delete this.cache[actualSection][actualKey];
else delete this.cache[actualKey];
this.pendingChanges.set(this.changeKey(actualSection ?? void 0, actualKey.toString()), {
section: actualSection ?? void 0,
key: actualKey.toString(),
deleted: true
});
this.schedulePersist();
}
hasValue(section, key) {
return this.getCacheValue(section, key) !== null;
}
getCacheValue(section, key) {
const actualKey = key ?? section;
const actualSection = key ? section : null;
let value = null;
if (actualSection) {
if (section in this.cache && actualKey in this.cache[actualSection]) value = this.cache[actualSection][actualKey];
} else if (actualKey in this.cache) value = this.cache[actualKey];
if (value === null || !("value" in value)) return null;
if ("indefinite" in value) return value;
else return value.timeout > Date.now() ? value : null;
}
set(object, ttl, section) {
return this._set(object, ttl, section);
}
setIndefinite(object, section) {
return this._set(object, null, section);
}
_set(object, ttl, section) {
const timeout = ttl === null ? null : Date.now() + ttl;
if (section) {
if (!(section in this.cache)) this.cache[section] = {};
for (const [key, value] of Object.entries(object)) {
const cacheValue = this.createCacheValue(value, timeout);
this.cache[section][key] = cacheValue;
this.pendingChanges.set(this.changeKey(section, key), {
section,
key,
cacheValue
});
}
} else for (const [key, value] of Object.entries(object)) {
const cacheValue = this.createCacheValue(value, timeout);
this.cache[key] = cacheValue;
this.pendingChanges.set(this.changeKey(void 0, key), {
key,
cacheValue
});
}
this.schedulePersist();
}
createCacheValue(value, timeout) {
if (timeout === null) return {
value,
indefinite: true
};
else return {
value,
timeout
};
}
async clear(section) {
if (section) {
delete this.cache[section];
for (const key of Array.from(this.pendingChanges.keys())) if (key.startsWith(`${section}|`)) this.pendingChanges.delete(key);
await ttStorage.clearCache(section);
} else {
this.cache = {};
if (this.persistTimer) clearTimeout(this.persistTimer);
this.persistTimer = null;
await ttStorage.clearCache();
}
}
async refresh() {
let hasChanged = false;
const now = Date.now();
const refreshObject = (object, section) => {
for (const key in object) {
const value = object[key];
if ("value" in value) {
const cacheValue = value;
if ("indefinite" in cacheValue || cacheValue.timeout > now) continue;
hasChanged = true;
delete object[key];
this.pendingChanges.set(this.changeKey(section, key), {
section,
key,
deleted: true
});
} else refreshObject(value, key);
}
};
refreshObject(this.cache);
for (const section in this.cache) if (!Object.keys(this.cache[section]).length) delete this.cache[section];
if (hasChanged) await this.persist();
}
schedulePersist() {
if (this.persistTimer) clearTimeout(this.persistTimer);
this.persistTimer = setTimeout(() => {
this.persistTimer = null;
this.persist().catch((err) => console.error("Failed to persist cache.", err));
}, 500);
}
async persist() {
if (this.persistTimer) clearTimeout(this.persistTimer);
if (!this.pendingChanges.size) return;
const changes = Array.from(this.pendingChanges.values());
await ttStorage.setCacheEntries(changes);
for (const change of changes) {
const key = this.changeKey(change.section, change.key);
if (this.pendingChanges.get(key) === change) this.pendingChanges.delete(key);
}
this.persistTimer = null;
}
changeKey(section, key) {
return `${section ?? ""}|${key}`;
}
};
new TornToolsCache();
var DefaultSetting = class {
type;
defaultValue;
constructor(type, defaultValue) {
this.type = type;
this.defaultValue = defaultValue ?? null;
}
};
new DefaultSetting("string", () => RUNTIME_INFORMATION.getVersion()), new DefaultSetting("string", () => RUNTIME_INFORMATION.getVersion()), new DefaultSetting("string"), new DefaultSetting("boolean", true), new DefaultSetting("string"), new DefaultSetting("boolean", true), new DefaultSetting("string"), new DefaultSetting("number"), new DefaultSetting("string"), new DefaultSetting("string"), new DefaultSetting("string"), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("string", "bottom-left"), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("string", "eu"), new DefaultSetting("string", "eu"), new DefaultSetting("string", ""), new DefaultSetting("string", "none"), new DefaultSetting("string", "default"), new DefaultSetting("string", ""), new DefaultSetting("boolean", false), new DefaultSetting("string", "default"), new DefaultSetting("number", 1), new DefaultSetting("boolean", true), new DefaultSetting("number", 100), new DefaultSetting("boolean", false), new DefaultSetting("boolean", () => globalThis.Notification?.permission === "granted"), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("array", ["100%"]), new DefaultSetting("array", ["100%"]), new DefaultSetting("array", ["100%"]), new DefaultSetting("array", ["100%"]), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("object", {}), new DefaultSetting("boolean", false), new DefaultSetting("string", ""), new DefaultSetting("boolean", false), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("string", ""), new DefaultSetting("boolean", true), new DefaultSetting("string", ""), new DefaultSetting("string", "TornTools"), new DefaultSetting("number", 30), new DefaultSetting("number", 120), new DefaultSetting("number", 3600), new DefaultSetting("number", 30), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("string", "default"), new DefaultSetting("string", "default"), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("string", ";"), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("string", ""), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("number", 12), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("array", [{
name: "$player",
color: "#7ca900"
}]), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("number", 0), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("string", "tornstats"), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("string", "dashboard"), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("string", "none"), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("number", 18), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("object", {}), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("string", "day"), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("number|empty", ""), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("number", 1500), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("number", 100), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("number", 1), new DefaultSetting("boolean", true), new DefaultSetting("number", 2), new DefaultSetting("boolean", true), new DefaultSetting("number", 1), new DefaultSetting("boolean", true), new DefaultSetting("number", 2), new DefaultSetting("boolean", true), new DefaultSetting("number", 1), new DefaultSetting("boolean", true), new DefaultSetting("number", 1), new DefaultSetting("boolean", true), new DefaultSetting("number", 2), new DefaultSetting("boolean", true), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("string", ""), new DefaultSetting("array", []), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("string", "All"), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("number", 1), new DefaultSetting("number", 100), new DefaultSetting("number", 0), new DefaultSetting("number", 5e3), new DefaultSetting("number", -1), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("number", 0), new DefaultSetting("number", 48), new DefaultSetting("number", 2), new DefaultSetting("number", 100), new DefaultSetting("number", 1), new DefaultSetting("number", 100), new DefaultSetting("array", []), new DefaultSetting("string", ""), new DefaultSetting("array", []), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("boolean", false), new DefaultSetting("string", "basic"), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("string", ""), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("array", []), new DefaultSetting("number", null), new DefaultSetting("number", null), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("boolean", false), new DefaultSetting("string", "none"), new DefaultSetting("string", "none"), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("number", 100), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("number", 1), new DefaultSetting("number", 100), new DefaultSetting("string", "all"), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("array", []), new DefaultSetting("number", null), new DefaultSetting("number", null), new DefaultSetting("boolean", true), new DefaultSetting("string", ""), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("number", 1), new DefaultSetting("number", 100), new DefaultSetting("number", 0), new DefaultSetting("number", -1), new DefaultSetting("array", []), new DefaultSetting("string", ""), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("string", "both"), new DefaultSetting("number", null), new DefaultSetting("number", null), new DefaultSetting("array", []), new DefaultSetting("boolean", true), new DefaultSetting("boolean", false), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("array", []), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("number", 1), new DefaultSetting("number", 100), new DefaultSetting("array", []), new DefaultSetting("number", null), new DefaultSetting("number", null), new DefaultSetting("boolean", false), new DefaultSetting("array", []), new DefaultSetting("number", 1), new DefaultSetting("number", 100), new DefaultSetting("array", []), new DefaultSetting("boolean", false), new DefaultSetting("boolean", false), new DefaultSetting("boolean", true), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("array", []), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("string", ""), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("array", []), new DefaultSetting("number", null), new DefaultSetting("number", null), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("number", 0), new DefaultSetting("number", 100), new DefaultSetting("array", []), new DefaultSetting("number", null), new DefaultSetting("number", null), new DefaultSetting("boolean", true), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("object", { date: -1 }), new DefaultSetting("object", { date: -2 }), new DefaultSetting("number", 0), new DefaultSetting("array", []), new DefaultSetting("object", {}), new DefaultSetting("number", 0), new DefaultSetting("array", []), new DefaultSetting("boolean", false), new DefaultSetting("string", ""), new DefaultSetting("number", 0), new DefaultSetting("number", 0), new DefaultSetting("number", 0), new DefaultSetting("number", 0), new DefaultSetting("number", 0), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("array", []), new DefaultSetting("boolean", false), new DefaultSetting("object", {
list: [],
date: 0
}), new DefaultSetting("object", {
list: [],
date: 0
}), new DefaultSetting("boolean", true), new DefaultSetting("number", 0), new DefaultSetting("object", {}), new DefaultSetting("string", ""), new DefaultSetting("string", "22px"), new DefaultSetting("object", {}), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("array", []), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("array", []), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("object", {}), new DefaultSetting("array", []);
function capitalizeText(text, partialOptions = {}) {
if (!{
everyWord: false,
...partialOptions
}.everyWord) return text[0].toUpperCase() + text.slice(1);
return text.trim().split(" ").map((word) => capitalizeText(word)).join(" ").trim();
}
var LINKS = {
auction: "https://www.torn.com/amarket.php",
bank: "https://www.torn.com/bank.php",
bazaar: "https://www.torn.com/bazaar.php",
bounties: "https://www.torn.com/bounties.php#!p=main",
chain: "https://www.torn.com/factions.php?step=your#/war/chain",
church: "https://www.torn.com/church.php",
committee: "https://www.torn.com/committee.php",
companies: "https://www.torn.com/companies.php",
companyEmployees: "https://www.torn.com/companies.php#/option=employees",
crimes: "https://www.torn.com/crimes.php",
donator: "https://www.torn.com/donator.php",
education: "https://www.torn.com/page.php?sid=education",
events: "https://www.torn.com/events.php#/step=all",
faction: "https://www.torn.com/factions.php",
faction__ranked_war: "https://www.torn.com/factions.php?step=your&type=1#/war/rank",
faction_oc: "https://www.torn.com/factions.php?step=your#/tab=crimes",
gym: "https://www.torn.com/gym.php",
home: "https://www.torn.com/index.php",
homepage: "https://www.torn.com/index.php",
hospital: "https://www.torn.com/hospitalview.php",
itemmarket: "https://www.torn.com/page.php?sid=ItemMarket",
items: "https://www.torn.com/item.php",
items_booster: "https://www.torn.com/item.php#boosters-items",
items_candy: "https://www.torn.com/item.php#candy-items",
items_drug: "https://www.torn.com/item.php#drugs-items",
items_medical: "https://www.torn.com/item.php#medical-items",
jailview: "https://www.torn.com/jailview.php",
jobs: "https://www.torn.com/companies.php",
loan: "https://www.torn.com/loan.php",
messages: "https://www.torn.com/messages.php",
missions: "https://www.torn.com/page.php?sid=missions",
organizedCrimes: "https://www.torn.com/factions.php?step=your#/tab=crimes",
pc: "https://www.torn.com/pc.php",
points: "https://www.torn.com/page.php?sid=points",
pointsmarket: "https://www.torn.com/pmarket.php",
properties: "https://www.torn.com/properties.php",
property_upkeep: "https://www.torn.com/properties.php#/p=options&tab=upkeep",
property_vault: "https://www.torn.com/properties.php#/p=options&tab=vault",
raceway: "https://www.torn.com/page.php?sid=racing",
staff: "https://www.torn.com/staff.php",
stocks: "https://www.torn.com/page.php?sid=stocks",
trade: "https://www.torn.com/trade.php",
travelagency: "https://www.torn.com/page.php?sid=travel"
};
LINKS.donator, LINKS.donator, LINKS.staff, LINKS.committee, LINKS.church, LINKS.jobs, LINKS.jobs, LINKS.jobs, LINKS.jobs, LINKS.jobs, LINKS.jobs, LINKS.companies, LINKS.companies, LINKS.companies, LINKS.faction, LINKS.faction, LINKS.faction, LINKS.faction, LINKS.faction, LINKS.education, LINKS.education, LINKS.bank, LINKS.bank, LINKS.travelagency, LINKS.property_vault, LINKS.loan, LINKS.auction, LINKS.bazaar, LINKS.itemmarket, LINKS.pointsmarket, LINKS.stocks, LINKS.stocks, LINKS.trade, LINKS.homepage, LINKS.raceway, LINKS.raceway, LINKS.faction_oc, LINKS.faction_oc, LINKS.faction_oc, LINKS.faction_oc, LINKS.bounties, LINKS.bank, LINKS.auction, LINKS.auction, LINKS.hospital, LINKS.hospital, LINKS.hospital, LINKS.jailview, LINKS.hospital, LINKS.items_booster, LINKS.items_booster, LINKS.items_booster, LINKS.items_booster, LINKS.items_booster, LINKS.items_medical, LINKS.items_medical, LINKS.items_medical, LINKS.items_medical, LINKS.items_medical, LINKS.items_drug, LINKS.items_drug, LINKS.items_drug, LINKS.items_drug, LINKS.items_drug, LINKS.travelagency, LINKS.travelagency, LINKS.travelagency, LINKS.travelagency, LINKS.travelagency, LINKS.items_medical, LINKS.items_medical, LINKS.items_medical, LINKS.items_medical, LINKS.items_medical, LINKS.property_upkeep, LINKS.property_upkeep, LINKS.property_upkeep;
[
{
id: 1,
reason: "Admin"
},
{
id: 4,
reason: "NPC"
},
{
id: 7,
reason: "NPC"
},
{
id: 9,
reason: "NPC"
},
{
id: 10,
reason: "NPC"
},
{
id: 15,
reason: "NPC"
},
{
id: 17,
reason: "NPC"
},
{
id: 19,
reason: "NPC"
},
{
id: 20,
reason: "NPC"
},
{
id: 21,
reason: "NPC"
}
].map(({ id }) => id);
function is2FACheckPage() {
return !!document.querySelector(".content-wrapper.logged-out .two-factor-auth-container");
}
function getPageStatus() {
const infoMessage = document.querySelector(".content-wrapper .info-msg-cont");
if (infoMessage?.classList.contains("red")) {
if (infoMessage.textContent.includes("items in your inventory")) return { access: true };
else if (findParent(infoMessage, { class: "no-parcel-wrap" })?.style?.display === "none") return { access: true };
return {
access: false,
message: infoMessage.textContent
};
}
if (document.querySelector(".captcha")) return {
access: false,
message: "Captcha required"
};
else if (document.querySelector(".dirty-bomb")) return {
access: false,
message: "Dirty bomb screen"
};
else if (is2FACheckPage()) return {
access: false,
message: "2 Factor Authentication"
};
return { access: true };
}
globalThis.browser?.runtime?.id ? globalThis.browser : globalThis.chrome;
var settings;
var Feature = class {
name;
scope;
executionTiming;
constructor(name, scope, executionTiming = "CONTENT_LOADED") {
this.name = name;
this.scope = scope;
this.executionTiming = executionTiming;
}
precondition() {
return true;
}
initialise() {}
execute() {}
reload() {}
storageKeys() {
return [];
}
requirements() {
return true;
}
shouldTriggerEvents() {
return false;
}
requiresScreenInformation() {
return true;
}
};
function initialise() {
addCustomListener(EVENT_CHANNELS.MISSION_LOAD, async () => {
if (!FEATURE_MANAGER.isEnabled(MissionHintsFeature)) return;
await showHints();
});
}
async function showHints() {
const MISSION_HINTS = {
a_good_day_to_get_hard: {
task: "Achieve a killstreak of 3 - 10.",
hint: "Buying losses is a valid strategy."
},
a_kimpossible_task: {
task: "Defeat (P) using only melee and temporary weapons.",
hint: "Guns can stay equipped."
},
a_problem_at_the_tracks: {
task: "Defeat 3 (P) using only fist or melee weapons.",
hint: "Other weapons can stay equipped. Using any other weapon will fail this mission!"
},
a_thor_loser: {
task: "Use Duke's hammer to hit 6 - 14 unique body parts",
hint: "Stalemating is a good way to achieve this."
},
against_the_odds: { task: "Defeat 2 (P)." },
an_honorary_degree: {
task: "Defeat (P) without using any guns",
hint: "Guns can stay equipped. Using a gun will fail this mission!"
},
army_of_one: {
task: "Attack (P) 3 times with various masks.",
hint: "Duke will send you the two masks to wear. Make sure that one of the attacks is without any mask. You just need to attack the target, defeating them isn't a requirement."
},
bakeout_breakout: { task: "Combine a fruitcake and the lock pick, and send 'special fruitcake' to someone in jail." },
bare_knuckle: {
task: "Defeat (P) with no weapons or armor equipped.",
hint: "Unequip everything. Residual effects from previous fights will fail this mission!"
},
batshit_crazy: {
task: "Inflict damage with Penelope.",
hint: "You'll receive Penelope from Duke. Amount of damage is apparently based on your maximum life."
},
battering_ram: { task: "Attack (P) 3 times." },
big_tub_of_muscle: { task: "Defeat (P) despite their gargantuan strength." },
birthday_surprise: {
task: "Obtain and send a specific item as a present to Duke.",
hint: "Place the item in an empty box, then gift wrap it to get it as a parcel."
},
bonnie_and_clyde: { task: "Defeat (P), and their spouse." },
bountiful: {
task: "Successfully claim 2 - 5 bounties",
hint: "Make sure to hospitalize the target."
},
bounty_on_the_mutiny: {
task: "Bounty (P) and wait for the bounty to be claimed.",
hint: "You cannot claim your own bounties."
},
bring_it: {
task: "Defeat Duke in a group attack",
hint: "Unlike other missions, you'll have a week to finish this one. Doesn't have to be the finishing hit, so just join when people try to loot him."
},
candy_from_babies: {
task: "Collect $50,000 - $250,000 in bounties.",
hint: "Doesn't have to be in a single bounty. Make sure to hospitalize the target(s)."
},
charity_work: {
task: "Mug 2 (P)",
hint: "Must be a successful mug. Sending them a small amount will guarantee a mug."
},
cracking_up: {
task: "Defeat and interrogate (P) for the code to unlock Duke's safe and send the content to Duke after opening it.",
hint: "Can take a few times to get the code."
},
critical_education: { task: "Achieve 3 - 9 critical hits" },
cut_them_down_to_size: { task: "Defeat any player of your level or higher." },
dirty_little_secret: {
task: "Put a bounty on (P), then attack the person who claimed it.",
hint: "If the claimer is anonymous, their ID # still shows up in the mission screen."
},
double_jeopardy: {
task: "Put a bounty on someone and defeat them.",
hint: "Bounty can be any amount as it doesn't have to be claimed."
},
drug_problem: { task: "Defeat 4 - 7 (P)." },
emotional_debt: { task: "Hit (P) with tear gas or pepper spray." },
estranged: {
task: "Injure one of (P)'s legs.",
hint: "Feet count as legs in this instance."
},
family_ties: { task: "Hospitalize (P) 3 times" },
field_trip: { task: "Win $100 - $1,000,000 on 3 casino games." },
fireworks: { task: "Expend 250 - 1250 rounds of ammunition" },
forgotten_bills: { task: "Defeat (P)" },
frenzy: {
task: "Defeat any 5 - 15 players.",
hint: "You must initiate the attacks; buying losses will not work for this mission"
},
get_things_jumping: {
task: "Deal and receive damage.",
hint: "Values are apparently based on your maximum life."
},
graffiti: {
task: "Hit (P) with pepper spray.",
hint: "Even if it's ineffective, it still counts."
},
guardian: { task: "Defeat (P)." },
hammer_time: {
task: "Defeat (P) with a hammer.",
hint: "Guns can stay equipped. Dual hammers don't count."
},
hands_off: { task: "Defeat 3 - 5 (P)." },
hare_meet_tortoise: {
task: "Defeat (P) despite their lightning fast speed.",
hint: "Flash and smoke grenades will reduce their speed."
},
hide_and_seek: {
task: "Find (P) from 3 - 5 listed and defeat them.",
hint: "Given clues make it easy to identify the target."
},
hiding_in_plain_view: { task: "Defeat (P) in a random country." },
high_fliers: { task: "Defeat 3 (P) in random countries" },
hobgoblin: { task: "Defeat a player of your choice 5 times" },
immovable_object: { task: "Defeat (P) despite their impenetrable defense." },
inside_job: {
task: "Attack (P) and secrete an item on them.",
hint: "Duke will send you the item. The Secrete option will appear after defeating (P)."
},
introduction_duke: { task: "Complete 10 Duke contracts." },
keeping_up_appearances: {
task: "Mug (P) and send them back the money.",
hint: "Must be a successful mug. Sending them a small amount will guarantee a mug."
},
kiss_of_death: { task: "Defeat (P) and use the kiss option." },
lack_of_awareness: { task: "Defeat (P)." },
lost_and_found: { task: "Put (P) in the hospital for 12 hours." },
loud_and_clear: {
task: "Use 3 - 11 explosive grenades.",
hint: "Some explosive grenades are 'Flash Grenade', 'HEG', 'Grenade', <a href='https://wiki.torn.com/wiki/Explosive_Grenade' target='_blank'>and more</a>."
},
loyal_customer: { task: "Defeat (P)." },
make_it_slow: {
task: "Defeat (P) in no fewer than 5 - 9 turns in a single attack.",
hint: "Survive for said amount of turns then defeat the target. You can keep retrying if it fails."
},
marriage_counseling: { task: "Defeat (P)'s spouse." },
massacrist: { task: "Defeat (P)." },
meeting_the_challenge: { task: "Mug people for a total of $10,000 - $16,000,000." },
motivator: {
task: "Lose or stalemate to (P) on the first attempt.",
hint: "You can get your health low by using the wrong blood bag. Make yourself weak by unequipping armor and equip a rusty sword."
},
new_kid_on_the_block: { task: "Defeat 5 players." },
no_man_is_an_island: {
task: "Mug 2 out of 3 (P).",
hint: "You can select which of the targets to hit, as long as you mug 2 different ones."
},
no_second_chances: { task: "Defeat (P) on the first attempt." },
out_of_the_frying_pan: { task: "Go to the jail, use Felovax to go to the hospital, then use Zylkene." },
painleth_dentitht: {
task: "Defeat (P) with a baseball bat.",
hint: "Other weapons can stay equipped."
},
party_tricks: { task: "Defeat (P) despite their nimble dexterity." },
pass_the_word: {
task: "Send a message including keyword to (P).",
hint: "It's easy to achieve this by copying the mission description."
},
peak_experience: { task: "Defeat (P)." },
proof_of_the_pudding: {
task: "Use a specific weapon on (P), then send the weapon to them.",
hint: "You don't have to send the exact same gun you used to attack with, just same type."
},
rabbit_response: {
task: "Defeat 3 (P) within 30 - 10 minutes.",
hint: "Timer starts after attacking one of the targets, so make sure they are all out of the hospital."
},
reconstruction: {
task: "Equip kitchen knife and leather gloves, defeat (P) then dump both items.",
hint: "Don't have to actually use the kitchen knife."
},
red_faced: { task: "Defeat (P) with a trout on the finishing hit." },
rising_costs: {
task: "Hit (P) with a brick.",
hint: "Brick has to hit, a miss won't count."
},
rolling_in_it: {
task: "Mug (P).",
hint: "Must be a successful mug. Sending them a small amount will guarantee a mug."
},
safari: {
task: "Defeat (P) with a rifle in South Africa.",
hint: "All hits need to be done with a rifle weapon type. Other weapons can stay equipped."
},
scammer: {
task: "Defeat (P).",
hint: "Target might have some nice cash on them, mugging could be beneficial."
},
sellout_slayer: {
task: "Buy a gun, use the gun on any 2 - 6 players, then sell it again.",
hint: "Not every non-melee weapon is a gun. As example, a blowgun might not work."
},
sending_a_message: { task: "Defeat (P)." },
show_some_muscle: {
task: "Attack (P).",
hint: "You just need to attack the target, defeating them isn't a requirement."
},
sleep_aid: { task: "Defeat (P)." },
some_people: { task: "Send any item as a parcel to (P)." },
standard_routine: { task: "Defeat (P) with a clubbed weapon, fists or kick." },
stomach_upset: { task: "Injure (P)'s stomach." },
swan_step_too_far: {
task: "Get an item from the dump and defeat its previous owner.",
hint: "You can keep searching till you find an item previously owned by someone you can actually defeat."
},
the_executive_game: {
task: "Defeat (P) using only fists or kick.",
hint: "Weapons can stay equipped."
},
the_tattoo_artist: {
task: "Defeat (P) using only a slashing or piercing weapon.",
hint: "Guns can stay equipped."
},
three_peat: { task: "Leave any player, mug any player and hospitalize any player." },
training_day: { task: "Use 250 - 1,250 energy in the gym." },
tree_huggers: { task: "Defeat 5 - 8 (P)." },
undercutters: { task: "Defeat 3 (P)." },
unwanted_attention: { task: "Hospitalize 4 (P)." },
withdrawal: {
task: "Injure (P)'s both arms.",
hint: "Hands count as arms in this case."
},
wrath_of_duke: { task: "Defeat 4 (P)." }
};
for (const context of findAllElements(".giver-cont-wrap > div[id^=mission]:not(.tt-modified)")) {
let title;
if (context.dataset.originalTitle) title = context.dataset.originalTitle;
else title = context.querySelector(".title-black").childNodes[0].textContent;
title = title?.trim();
const key = transformTitle(title);
let task, hint;
if (key in MISSION_HINTS) {
const mission = MISSION_HINTS[key];
task = mission.task;
hint = mission.hint ? elementBuilder({
type: "span",
html: mission.hint
}) : null;
} else if (title.includes("{name}")) {
task = "You are using a conflicting script.";
hint = "Please remove the script that changes the mission title or contact the TornTools developers.";
} else {
task = "Couldn't find information for this mission. One known cause would be a conflicting script.";
hint = "Please remove the script that changes the mission title or contact the TornTools developers. Otherwise, contact the TornTools developers.";
}
const children = [elementBuilder({
type: "h6",
class: "tt-mission-title",
text: "TornTools Mission Information"
}), elementBuilder({
type: "span",
children: [elementBuilder({
type: "b",
text: "Task: "
}), task]
})];
if (hint) children.push(elementBuilder("br"), elementBuilder({
type: "span",
children: [elementBuilder({
type: "b",
text: "Hint: "
}), hint]
}));
context.querySelector(".max-height-fix").appendChild(elementBuilder({
type: "div",
class: "tt-mission-information",
children
}));
context.classList.add("tt-modified");
}
function transformTitle(title) {
return title.toLowerCase().replaceAll(" ", "_").replaceAll(":", "").replaceAll("-", "_").replaceAll("!", "").replaceAll(",", "");
}
}
var MissionHintsFeature = class extends Feature {
constructor() {
super("Mission Hints", "missions");
}
precondition() {
return getPageStatus().access;
}
isEnabled() {
return settings.pages.missions.hints;
}
initialise() {
initialise();
}
async execute() {
await showHints();
}
storageKeys() {
return ["settings.pages.missions.hints"];
}
};
_css(".tt-hidden{display:none!important}.tt-black-overlay{z-index:100;background-color:#00000059;width:100%;height:100%;position:fixed;top:0;left:0}.no-margin{margin:0}.tt-delimiter{border-top:#ccc;border-left:none;border-right:none;border-top:1px solid var(--sidebar-horizontal-divider-bg-color);border-bottom:#fff;border-bottom:1px solid var(--sidebar-horizontal-divider-shadow-color);height:0;margin-bottom:5px;overflow:hidden}.tt-overlay{z-index:1000000;background-color:#00000059;width:100%;height:100%;position:fixed;top:0;left:0}.tt-overlay-item,.tt-overlay-item-notbroken{z-index:999999999;position:relative}.tt-overlay-item .tt-overlay-ignore{z-index:0;pointer-events:none}.tt-overlay-item .tt-overlay-ignore:before{content:\"\";z-index:1000000;background-color:#00000059;width:100%;height:100%;position:absolute;top:0;left:0}.relative{position:relative}.flex-break{border:0;height:0;margin:0;flex-basis:100%!important}.mt10{margin-top:10px}.mb10{margin-bottom:10px}.t-flex{display:flex}[class*=torn-icon-]{vertical-align:middle;background:url(https://www.torn.com/images/v2/city/location_icons_34x34px.svg) no-repeat;width:34px;height:34px;display:inline-block}.torn-icon-item-market{background-position:-68px -34px}.tt-sidebar-area{margin-top:2px;overflow:hidden}.tt-sidebar-area>div{cursor:pointer;vertical-align:top;background-color:var(--default-bg-panel-color);border-top-right-radius:5px;border-bottom-right-radius:5px;position:relative;overflow:hidden}.tt-sidebar-area a{color:var(--default-content-font-color);justify-content:flex-start;align-items:center;height:100%;text-decoration:none;display:flex;overflow:hidden}.tt-sidebar-area a span{float:none;vertical-align:middle;margin-left:10px;display:inline-block}.tt-button-link{cursor:pointer;color:var(--default-blue-color)}.tt-btn{background-color:var(--tt-color-light-green);color:#000;border-radius:6px;width:fit-content}.tt-btn:not([disabled]){cursor:pointer}.tt-btn[disabled]{cursor:not-allowed;opacity:.4}.tt-msg-box{background:var(--info-msg-grey-gradient);box-shadow:var(--info-msg-box-shadow);color:var(--info-msg-font-color);border-radius:5px;margin-top:10px;font-size:0;line-height:16px}.tt-msg-box .tt-msg-div{background:var(--info-msg-horizontal-gradient);border-radius:5px;justify-content:flex-start;display:flex}.tt-msg-box .tt-msg{vertical-align:middle;background-color:var(--default-bg-panel-active-color);background:var(--info-msg-delimiter-gradient);border-radius:0 5px 5px 0;flex-grow:1;width:1px;height:auto}.tt-msg-box .tt-content{vertical-align:middle;color:var(--info-msg-font-color);background-color:var(--default-bg-panel-active-color);background:var(--info-msg-bg-gradient);border-radius:0 5px 5px 0;padding:10px;font-size:13px;position:relative}.tt-message-box{color:var(--info-msg-font-color);box-shadow:var(--info-msg-box-shadow);border-radius:5px;margin-top:10px;font-size:13px;display:flex}.tt-message-box .tt-message-icon-wrap{background:var(--info-msg-grey-gradient);border-radius:5px 0 0 5px;width:34px}.tt-message-box .tt-message-icon{background:var(--info-msg-horizontal-gradient);border-radius:5px 0 0 5px;justify-content:center;width:34px;height:100%;display:flex}.tt-message-box .tt-svg{width:34px;height:34px}.tt-message-box .tt-message-wrap{background-color:var(--default-bg-panel-active-color);background:var(--info-msg-bg-gradient);border-radius:0 5px 5px 0;flex-grow:1;align-items:center;padding:10px;display:flex}.tt-message-box .tt-message{flex-grow:1}.tt-svg{width:128px;height:128px}.tt-svg .tt-svg-upper{stroke:#000;fill:#000}.tt-svg .tt-svg-lower{stroke:#568725;fill:#568725}#sidebarroot .pill{cursor:pointer;background-color:var(--default-bg-panel-color);min-height:22px;color:var(--default-font-color);border-top-right-radius:5px;border-bottom-right-radius:5px;align-items:center;margin-top:2px;text-decoration:none;display:flex;overflow:hidden}#sidebarroot .pill:not([icon]){box-sizing:border-box;padding-top:5px;padding-bottom:5px}#sidebarroot .pill:not([icon]),#sidebarroot .pill[icon] span{height:100%;color:var(--default-font-color);justify-content:flex-start;align-items:center;padding-left:8px;text-decoration:none;display:flex;overflow:hidden}body.tt-tablet #sidebarroot .pill{min-height:34px}body[data-layout=hospital] #sidebarroot .pill{margin-top:0;margin-bottom:1px}#sidebarroot .pill:hover{background-color:var(--default-bg-panel-active-color)!important}.tt-sidebar-information{flex-direction:column;display:flex}.tt-sidebar-information .title{color:inherit;margin:inherit;font-weight:700;text-decoration:none}.tt-sidebar-information .countdown.short{color:var(--tt-color-red)}.tt-sidebar-information .countdown.medium{color:var(--tt-color-orange)}.tt-top-icons{gap:10px;display:flex}");
_css(":root{--tt-color-green:#00a500;--tt-color-light-green:#acea00;--tt-color-red:#d83500;--tt-color-green--20:#00a50033;--tt-color-green--30:#00a5004d;--tt-color-green--40:#00a50066;--tt-background-torn-gray:repeating-linear-gradient(90deg, #627e0d, #627e0d 2px, #6e8820 0, #6e8820 4px);--tt-background-green:repeating-linear-gradient(90deg, #627e0d, #627e0d 2px, #6e8820 0, #6e8820 4px);--tt-background-alternative:repeating-linear-gradient(90deg, #242424, #242424 2px, #2e2e2e 0, #2e2e2e 4px)}body:not(.dark-mode){--tt-color-blue:blue;--tt-color-orange:orange;--tt-color-item-text:#678c00;--tt-color-item-quantity:black;--tt-background-popup:#f1f1f1;--tt-shadow-popup:unset}body.dark-mode{--tt-color-blue:#058cff;--tt-color-orange:gold;--tt-color-item-text:#9c0;--tt-color-item-quantity:#ddd;--tt-background-popup:#444;--tt-shadow-popup:0 0 10px black}.tt-color-green{color:var(--tt-color-green)}.tt-color-red{color:var(--tt-color-red)}");
function handleDeviceSizeClasses() {
checkDevice().then(({ mobile, tablet }) => {
if (mobile) document.body.classList.add("tt-mobile");
else document.body.classList.remove("tt-mobile");
if (tablet) document.body.classList.add("tt-tablet");
else document.body.classList.remove("tt-tablet");
});
}
var ScriptFeatureManager = class {
constructor() {
this.getScriptState();
}
createPopup() {}
isEnabled(featureConstructor) {
return this.getScriptState().enabled[new featureConstructor().name];
}
registerFeature(feature) {
if (feature.requiresScreenInformation()) handleDeviceSizeClasses();
feature.initialise();
feature.execute();
this.getScriptState().enabled[feature.name] = true;
if (feature.shouldTriggerEvents()) triggerCustomListener(EVENT_CHANNELS.FEATURE_ENABLED, { name: feature.name });
}
getScriptState() {
const win = RUNTIME_INFORMATION.getWindow();
if (!win.ttScriptState) {
const newState = { enabled: {} };
win.ttScriptState = newState;
return newState;
}
return win.ttScriptState;
}
};
function isPDA() {
return typeof PDA_evaluateJavascript === "function";
}
function registerCoreUserscriptContext() {
setRuntimeInformation(UserscriptRuntimeInformation);
setFeatureManager(new ScriptFeatureManager());
setEventHandler(ScriptEventHandler);
initializeScriptTheme();
}
function initializeScriptTheme() {
document.documentElement.style.setProperty("--tt-theme-color", "#fff");
document.documentElement.style.setProperty("--tt-theme-background", "var(--tt-background-green)");
}
var UserscriptRuntimeInformation = {
getWindow() {
return unsafeWindow;
},
getVersion() {
return GM.info.version;
},
isUserscript() {
return true;
},
reloadWindow(force) {
if (isPDA()) window.flutter_inappwebview.callHandler("reloadPage");
else location.reload(force);
}
};
var ScriptEventHandler = {
triggerEvent(channel, payload) {
document.dispatchEvent(new CustomEvent(`TT_${channel}`, { detail: payload }));
},
registerListener(channel, listener) {
document.addEventListener(`TT_${channel}`, (event) => {
if (!isCustomEvent(event)) return;
listener(event.detail);
});
},
get eventRoot() {
return document;
},
triggerEventCrossWorld(target, channel, payload) {
target.dispatchEvent(new CustomEvent(`TT_${channel}`, { detail: payload }));
},
registerListenerCrossWorld(target, channel, listener) {
target.addEventListener(`TT_${channel}`, (event) => {
if (!isCustomEvent(event)) return;
listener(event.detail);
});
}
};
var RequestListenerInjector = class {
injectListeners;
id;
constructor(injectListeners) {
this.injectListeners = injectListeners;
this.id = capitalizeText(injectListeners.name);
}
inject() {
if (this.isInjected()) return;
this.injectListeners();
this.setInjected();
}
isInjected() {
return document.documentElement.dataset[`tt${this.id}`] === "true";
}
setInjected() {
document.documentElement.dataset[`tt${this.id}`] = "true";
}
};
function injectFetchListeners() {
const oldFetch = RUNTIME_INFORMATION.getWindow().fetch;
RUNTIME_INFORMATION.getWindow().fetch = (input, init) => new Promise((resolve, reject) => {
oldFetch(input, init).then(async (response) => {
const page = response.url.slice(response.url.indexOf("torn.com/") + 9, response.url.indexOf(".php"));
let json = {};
try {
json = await response.clone().json();
} catch {}
let body = null;
if (init) {
if (typeof init.body === "string" && isJsonString(init.body)) try {
body = JSON.parse(init.body);
} catch {}
else if (typeof init?.body === "object" && init.body?.constructor?.name === "FormData") {
const newBody = {};
for (const [key, value] of init.body) if (isIntNumber(value)) newBody[key] = parseFloat(value);
else newBody[key] = value;
body = newBody;
} else body = init.body;
}
const url = response.url || input;
const detail = {
page,
json,
text: await response.clone().text(),
fetch: {
url,
body,
status: response.status
}
};
window.dispatchEvent(new CustomEvent("tt-fetch", { detail }));
resolve(response);
}).catch((error) => {
reject(error);
});
});
}
function injectXhrListeners() {
const oldXHROpen = window.XMLHttpRequest.prototype.open;
const oldXHRSend = window.XMLHttpRequest.prototype.send;
window.XMLHttpRequest.prototype.open = function(method, url) {
this["method"] = method;
this["url"] = url;
this["params"] = this["params"] ?? {};
this.addEventListener("readystatechange", function() {
if (this.readyState > 3 && this.status === 200) {
const page = this.responseURL.slice(this.responseURL.indexOf("torn.com/") + 9, this.responseURL.indexOf(".php"));
let json, uri;
if (isJsonString(this.response)) json = JSON.parse(this.response);
else uri = getUrlParams(this.responseURL);
let text;
if (this.responseType === "" || this.responseType === "text") text = this.responseText;
window.dispatchEvent(new CustomEvent("tt-xhr", { detail: {
page,
json,
uri,
xhr: {
requestBody: this["requestBody"],
response: this.response,
responseType: this.responseType,
responseText: text,
responseURL: this.responseURL
}
} }));
}
});
arguments[0] = method;
arguments[1] = url;
return oldXHROpen.apply(this, arguments);
};
window.XMLHttpRequest.prototype.send = function(body) {
this["params"] = this["params"] ?? {};
if ("xhrSendAdjustments" in window && typeof window.xhrSendAdjustments === "object") for (const key in window.xhrSendAdjustments) {
if (typeof window.xhrSendAdjustments[key] !== "function") continue;
body = window.xhrSendAdjustments[key](Object.assign({}, this), body);
}
this["requestBody"] = body;
arguments[0] = body;
return oldXHRSend.apply(this, arguments);
};
}
function getUrlParams(url, prop) {
if (!url) url = location.href;
const definitions = decodeURIComponent(url.slice(url.indexOf("?") + 1)).split("&");
const params = {};
definitions.forEach((val) => {
const parts = val.split("=", 2);
params[parts[0]] = parts[1];
});
return prop && prop in params ? params[prop] : params;
}
function isJsonString(str) {
if (!str || str === "") return false;
try {
JSON.parse(str);
} catch {
return false;
}
return true;
}
var BASE_HIGHLIGHT_SIZE = 38;
var SYNC_ATTEMPT_INTERVAL = 250;
var SYNC_ATTEMPT_LIMIT = 80;
function injectCityItemsMapListeners(pageWindow = window) {
if (pageWindow.__ttCityItemsMap?.injected) return;
const state = {
injected: true,
entries: [],
overlays: new Map()
};
pageWindow.__ttCityItemsMap = state;
EVENT_HANDLER.registerListenerCrossWorld(pageWindow, EVENT_CHANNELS.CITY_ITEMS_MAP__SET_ITEMS, ({ entries }) => {
state.entries = Array.isArray(entries) ? entries.filter(isCityItemsMapEntry) : [];
scheduleSync();
});
EVENT_HANDLER.registerListenerCrossWorld(pageWindow, EVENT_CHANNELS.CITY_ITEMS_MAP__REQUEST_MODEL_ITEMS, () => {
const items = getModelItems();
EVENT_HANDLER.triggerEventCrossWorld(pageWindow, EVENT_CHANNELS.CITY_ITEMS_MAP__MODEL_ITEMS, { items });
});
EVENT_HANDLER.registerListenerCrossWorld(pageWindow, EVENT_CHANNELS.CITY_ITEMS_MAP__CLEAR, clearOverlays);
function scheduleSync() {
let attempts = 0;
syncOverlays();
if (state.syncTimer) return;
state.syncTimer = pageWindow.setInterval(() => {
attempts++;
if (syncOverlays() || attempts >= SYNC_ATTEMPT_LIMIT || !state.entries.length) {
if (state.syncTimer) pageWindow.clearInterval(state.syncTimer);
state.syncTimer = void 0;
}
}, SYNC_ATTEMPT_INTERVAL);
}
function syncOverlays() {
const map = getMap();
const leaflet = pageWindow.L;
if (!map || !isLeafletOverlayRuntime(leaflet)) return false;
const activeEntryIds = new Set(state.entries.map((entry) => entry.entryId));
for (const [entryId, record] of state.overlays) if (!activeEntryIds.has(entryId)) {
removeOverlay(record);
state.overlays.delete(entryId);
}
for (const entry of state.entries) {
let record = state.overlays.get(entry.entryId);
const latLng = getLatLngForEntry(entry);
if (!latLng) continue;
if (!record) {
record = {
entry,
marker: null,
latLng
};
state.overlays.set(entry.entryId, record);
} else {
record.entry = entry;
record.latLng = latLng;
}
ensureOverlay(record, map, leaflet);
}
return state.entries.every((entry) => !!state.overlays.get(entry.entryId)?.marker);
}
function ensureOverlay(record, map, leaflet) {
const latLng = record.latLng;
if (!latLng) return;
try {
if (record.marker?._map && record.marker._map !== map) removeOverlay(record);
if (record.marker) {
record.marker.setLatLng?.(latLng);
updateOverlayElement(record);
return;
}
const icon = leaflet.divIcon({
className: "tt-city-item-overlay city-item",
html: `<span class="tt-city-item-overlay-content"><img src="${getItemImageUrl(record.entry.itemId)}" alt=""></span>`,
iconSize: [BASE_HIGHLIGHT_SIZE, BASE_HIGHLIGHT_SIZE],
iconAnchor: [BASE_HIGHLIGHT_SIZE / 2, BASE_HIGHLIGHT_SIZE / 2]
});
const marker = leaflet.marker(latLng, {
icon,
interactive: true,
keyboard: false,
zIndexOffset: 1e3
});
if (typeof marker.addTo !== "function") return;
marker.addTo(map);
record.marker = marker;
updateOverlayElement(record);
} catch {
record.marker = null;
}
}
function updateOverlayElement(record) {
const element = record.marker?.getElement?.();
if (!element) return;
element.classList.add("tt-city-item-overlay", "city-item");
element.dataset.id = record.entry.itemId.toString();
element.dataset.itemId = record.entry.itemId.toString();
element.dataset.entryId = record.entry.entryId;
element.dataset.td = record.entry.td;
element.removeAttribute("title");
}
function clearOverlays() {
state.entries = [];
if (state.syncTimer) {
pageWindow.clearInterval(state.syncTimer);
state.syncTimer = void 0;
}
for (const record of state.overlays.values()) removeOverlay(record);
state.overlays.clear();
}
function removeOverlay(record) {
if (!record.marker) return;
try {
if (record.marker.remove) record.marker.remove();
else record.marker.removeFrom?.(getMap());
} catch {
try {
record.marker._map?.removeLayer?.(record.marker);
} catch {}
}
record.marker = null;
}
function getMap() {
const mapElement = pageWindow.document.querySelector("#map");
const map = getTornRuntime()?.map?.lmap ?? mapElement?._leaflet_map;
return isLeafletMap(map) ? map : null;
}
function getLatLngForEntry(entry) {
if (!Number.isFinite(entry.x) || !Number.isFinite(entry.y)) return null;
const tornMap = getTornRuntime()?.map;
const leaflet = pageWindow.L;
try {
if (tornMap?.getLPoint && leaflet?.CRS?.EPSG3857?.pointToLatLng) {
const point = [entry.x / 2, entry.y / 2];
const leafletPoint = tornMap.getLPoint(point);
return normalizeLatLng(leaflet.CRS.EPSG3857.pointToLatLng(leafletPoint, tornMap.minZoom));
}
} catch {}
return null;
}
function getModelItems() {
const model = getTornRuntime()?.model;
if (!model) return [];
try {
const fullModel = model.get();
if (Array.isArray(fullModel?.territoryUserItems)) return fullModel.territoryUserItems;
} catch {}
try {
const userItems = model.get("territoryUserItems");
if (Array.isArray(userItems)) return userItems;
} catch {}
return [];
}
function getTornRuntime() {
const torn = pageWindow.torn;
return isTornRuntime(torn) ? torn : null;
}
}
function isCityItemsMapEntry(value) {
return isRecord(value) && typeof value.entryId === "string" && typeof value.itemId === "number" && Number.isFinite(value.itemId) && typeof value.name === "string" && typeof value.td === "string" && typeof value.x === "number" && Number.isFinite(value.x) && typeof value.y === "number" && Number.isFinite(value.y);
}
function isRecord(value) {
return typeof value === "object" && value !== null;
}
function isTornRuntime(value) {
return isRecord(value) && (!("map" in value) || value.map == null || isTornMapRuntime(value.map)) && (!("model" in value) || value.model == null || isTornModelRuntime(value.model));
}
function isTornMapRuntime(value) {
return isRecord(value) && (!("lmap" in value) || value.lmap == null || isLeafletMap(value.lmap)) && (!("minZoom" in value) || value.minZoom == null || typeof value.minZoom === "number") && (!("getLPoint" in value) || value.getLPoint == null || typeof value.getLPoint === "function");
}
function isTornModelRuntime(value) {
return isRecord(value) && typeof value.get === "function";
}
function isLeafletMap(value) {
return isRecord(value) && typeof value.addLayer === "function";
}
function isLeafletOverlayRuntime(value) {
return isRecord(value) && typeof value.divIcon === "function" && typeof value.marker === "function";
}
function normalizeLatLng(latLng) {
if (!latLng) return null;
if (Array.isArray(latLng)) {
const [lat, lng] = latLng;
return Number.isFinite(lat) && Number.isFinite(lng) ? latLng : null;
}
return Number.isFinite(latLng.lat) && Number.isFinite(latLng.lng) ? latLng : null;
}
function getItemImageUrl(itemId) {
return `https://www.torn.com/images/items/${itemId}/small.png`;
}
function injectEfficientRehabListeners(pageWindow = window) {
EVENT_HANDLER.registerListenerCrossWorld(pageWindow, EVENT_CHANNELS.EFFICIENT_REHAB, ({ ticks }) => {
const $slider = $("#rehub-progress .ui-slider");
const rehabPercentages = JSON.parse($slider.attr("data-percentages")) || [];
if (!(ticks in rehabPercentages)) {
console.warn("TornTools - Failed to update the rehab amount due to it being an invalid amount of ticks");
return;
}
const percentage = rehabPercentages[ticks];
$slider.slider("value", percentage).slider("option", "slide")({}, { value: $slider.slider("value") });
});
EVENT_HANDLER.triggerEventCrossWorld(pageWindow, EVENT_CHANNELS.EFFICIENT_REHAB__INJECTED);
}
function registerInjectorUserscriptContext() {
setScriptInjector(UserscriptScriptInjector);
}
function injectUserscriptCityItemsMapListeners() {
injectCityItemsMapListeners(unsafeWindow);
}
function injectUserscriptEfficientRehabListeners() {
injectEfficientRehabListeners(unsafeWindow);
}
var fetchListenerInjector = new RequestListenerInjector(injectFetchListeners);
var xhrListenerInjector = new RequestListenerInjector(injectXhrListeners);
var cityItemsMapListenerInjector = new RequestListenerInjector(injectUserscriptCityItemsMapListeners);
var efficientRehabInjector = new RequestListenerInjector(injectUserscriptEfficientRehabListeners);
var UserscriptScriptInjector = {
injectFetch() {
fetchListenerInjector.inject();
},
injectXHR() {
xhrListenerInjector.inject();
},
injectCityItemsMap() {
cityItemsMapListenerInjector.inject();
},
injectEfficientRehab() {
efficientRehabInjector.inject();
}
};
(async () => {
registerCoreUserscriptContext();
registerInjectorUserscriptContext();
setupMissionsPage();
FEATURE_MANAGER.registerFeature(new MissionHintsFeature());
})();
})();