Torn Efficiency Manager

Efficiency suite. Monitors Education, Organized Crimes, and Life/Energy waste using persistent settings.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Torn Efficiency Manager
// @namespace    http://torn.efficiency
// @version      1.0
// @description  Efficiency suite. Monitors Education, Organized Crimes, and Life/Energy waste using persistent settings.
// @author       Nicholas_Herr [3863644]
// @license MIT
// @match        https://www.torn.com/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    let DEBUG_FORCE_ALL = false;

    const getSettings = () => {
        const defaults = { edu: true, oc: true, life: true, xanax: true };
        const saved = localStorage.getItem('EfficiencySettings');
        return saved ? JSON.parse(saved) : defaults;
    };

    const saveSettings = (settings) => {
        localStorage.setItem('EfficiencySettings', JSON.stringify(settings));
    };

    const CONFIG = {
        CHECK_INTERVAL: 15000,
        SELECTORS: {
            SIDEBAR_MENU: '.toggle-content___BJ9Q9',
            STATUS_BAR: 'ul[class*="status-icons"]',
            LIFE_BAR: 'a[class*="life"]',
            ENERGY_BAR: 'a[class*="energy"]',
            EDU_LINK: 'a[href*="sid=education"]',
            OC_LINK: 'a[href*="tab=crimes"]',
            DRUG_CD: 'li[class*="icon49"]',
            MAIN_CONTAINER: '#mainContainer',
            ACTUAL_BAR: 'div[class*="progress-line"]:not([class*="timer"])'
        },
        COLORS: {
            RED: "#ff4444", DARK_RED: "#cc0000", ORANGE: "#ffa500",
            YELLOW: "#e3af00", GREEN: "#37b24d", GRAY: "#444444"
        }
    };

    const EfficiencyManager = {
        getAlerts() {
            if (DEBUG_FORCE_ALL) {
                return [
                    { text: "DEBUG: NO EDUCATION COURSE", color: CONFIG.COLORS.RED, url: "#" },
                    { text: "DEBUG: NO ORGANIZED CRIME", color: CONFIG.COLORS.ORANGE, url: "#" },
                    { text: "DEBUG: LIFE FULL: MAKE BLOOD BAGS!", color: CONFIG.COLORS.DARK_RED, url: "#" },
                    { text: "DEBUG: ENERGY AT 500: TAKE A XANAX!", color: CONFIG.COLORS.GREEN, url: "#" },
                    { text: "DEBUG: WASTE WARNING: BURN 50 ENERGY!", color: CONFIG.COLORS.YELLOW, url: "#" }
                ];
            }

            const settings = getSettings();
            const alerts = [];
            const isEduPage = window.location.href.includes('sid=education');
            const eduActive = !!document.querySelector(`${CONFIG.SELECTORS.STATUS_BAR} ${CONFIG.SELECTORS.EDU_LINK}`);
            const ocActive = !!document.querySelector(`${CONFIG.SELECTORS.STATUS_BAR} ${CONFIG.SELECTORS.OC_LINK}`);

            if (settings.edu && !isEduPage && !eduActive) {
                alerts.push({ text: "NO EDUCATION COURSE", color: CONFIG.COLORS.RED, url: "/page.php?sid=education" });
            }
            if (settings.oc && !ocActive) {
                alerts.push({ text: "NO ORGANIZED CRIME", color: CONFIG.COLORS.ORANGE, url: "/factions.php?step=your#/tab=crimes" });
            }

            const lifeBar = document.querySelector(CONFIG.SELECTORS.LIFE_BAR);
            const progress = lifeBar?.querySelector(CONFIG.SELECTORS.ACTUAL_BAR);
            if (settings.life && progress) {
                const healthPct = parseInt(progress.style.width) || 0;
                if (healthPct === 100) {
                    alerts.push({ text: "LIFE FULL: MAKE BLOOD BAGS!", color: CONFIG.COLORS.DARK_RED, url: "/item.php#v=blood" });
                } else if (healthPct >= 33) {
                    alerts.push({ text: `Life ${healthPct}%: You could make bags`, color: CONFIG.COLORS.GRAY, url: "/item.php#v=blood" });
                }
            }

            if (settings.xanax) {
                const energyBar = document.querySelector(CONFIG.SELECTORS.ENERGY_BAR);
                const energyVal = energyBar?.querySelector('p[class*="bar-value"]')?.textContent || "0/0";
                const currentEnergy = parseInt(energyVal.split('/')[0].replace(/[^0-9]/g, '')) || 0;
                const onCooldown = !!document.querySelector(CONFIG.SELECTORS.DRUG_CD);

                if (!onCooldown && currentEnergy < 1000) {
                    if (currentEnergy > 750) {
                        const waste = (currentEnergy + 250) - 1000;
                        alerts.push({ text: `WASTE WARNING: BURN ${waste} ENERGY!`, color: CONFIG.COLORS.YELLOW, url: "/gym.php" });
                    } else {
                        alerts.push({ text: `ENERGY AT ${currentEnergy}: TAKE A XANAX!`, color: CONFIG.COLORS.GREEN, url: "/item.php#v=drugs" });
                    }
                }
            }
            return alerts;
        }
    };

    const UIManager = {
        renderAlerts() {
            const alerts = EfficiencyManager.getAlerts();
            let container = document.getElementById('torn-efficiency-bar');
            if (container) container.remove();
            if (alerts.length === 0) return;

            container = document.createElement('div');
            container.id = 'torn-efficiency-bar';
            Object.assign(container.style, { display: 'flex', flexDirection: 'column', width: '100%', zIndex: '999999', position: 'relative', gap: '2px' });

            alerts.forEach(alert => {
                const div = document.createElement('div');
                div.innerHTML = `⚠️ ${alert.text}`;
                Object.assign(div.style, { background: alert.color, color: '#fff', textAlign: 'center', padding: '14px', fontWeight: 'bold', fontSize: '14px', cursor: 'pointer', boxShadow: '0 2px 5px rgba(0,0,0,0.1)', textShadow: '1px 1px 2px rgba(0,0,0,0.5)' });
                div.onclick = () => { if(alert.url !== "#") window.location.href = alert.url; };
                container.appendChild(div);
            });
            document.querySelector(CONFIG.SELECTORS.MAIN_CONTAINER)?.before(container);
        },

        injectSettingsMenu() {
            const menu = document.querySelector(CONFIG.SELECTORS.SIDEBAR_MENU);
            if (!menu || document.getElementById('nav-efficiency-settings')) return;

            const settings = getSettings();
            const container = document.createElement('div');
            container.id = 'nav-efficiency-settings';
            container.className = 'area-desktop___bpqAS';
            container.style.borderLeft = "4px solid #37b24d";

            container.innerHTML = `
                <div id="settings-header" style="padding: 10px; cursor: pointer; background: rgba(55, 178, 77, 0.1); display: flex; justify-content: space-between; align-items: center;">
                    <span style="color: #37b24d; font-size: 11px; font-weight: bold;">EFFICIENCY SETTINGS</span>
                    <span id="settings-chevron">▼</span>
                </div>
                <div id="settings-content" style="display: none; padding: 10px; flex-direction: column; gap: 8px; background: rgba(0,0,0,0.2);">
                    ${['edu', 'oc', 'life', 'xanax'].map(key => `
                        <label style="display: flex; justify-content: space-between; color: #ccc; font-size: 11px; cursor: pointer;">
                            ${key.toUpperCase()} ALERTS
                            <input type="checkbox" data-key="${key}" ${settings[key] ? 'checked' : ''} style="cursor: pointer;">
                        </label>
                    `).join('')}
                    <button id="debug-show-all" style="margin-top: 5px; background: #444; color: #00ffcc; border: 1px solid #00ffcc; padding: 5px; font-size: 10px; cursor: pointer; font-weight: bold; border-radius: 3px;">
                        DEBUG: SHOW ALL ALERTS
                    </button>
                    <div id="debug-info-tray" style="display: none; margin-top: 10px; padding-top: 10px; border-top: 1px solid #555; text-align: center; flex-direction: column; gap: 10px;">
                        <a href="https://www.torn.com/profiles.php?XID=3863644" target="_blank" style="color: #37b24d; font-size: 10px; font-weight: bold; text-decoration: none; display: block;">
                            💸 Support Efficiency Logic?
                        </a>
                        <a href="https://www.torn.com/profiles.php?XID=3863644" target="_blank" style="color: #aaa; font-size: 9px; text-decoration: none; display: block; font-style: italic;">
                            Want a custom script? Message me.
                        </a>
                    </div>
                </div>
            `;

            menu.prepend(container);

            const header = document.getElementById('settings-header');
            const content = document.getElementById('settings-content');
            const chevron = document.getElementById('settings-chevron');
            const debugBtn = document.getElementById('debug-show-all');
            const infoTray = document.getElementById('debug-info-tray');

            header.onclick = () => {
                const active = content.style.display === 'flex';
                content.style.display = active ? 'none' : 'flex';
                chevron.style.transform = active ? 'rotate(0deg)' : 'rotate(180deg)';
            };

            debugBtn.onclick = (e) => {
                e.stopPropagation();
                DEBUG_FORCE_ALL = !DEBUG_FORCE_ALL;
                debugBtn.style.background = DEBUG_FORCE_ALL ? "#00ffcc" : "#444";
                debugBtn.style.color = DEBUG_FORCE_ALL ? "#000" : "#00ffcc";
                debugBtn.textContent = DEBUG_FORCE_ALL ? "DEBUG: ACTIVE" : "DEBUG: SHOW ALL ALERTS";
                infoTray.style.display = DEBUG_FORCE_ALL ? "flex" : "none";
                UIManager.renderAlerts();
            };

            content.onchange = (e) => {
                if(e.target.tagName !== "INPUT") return;
                const key = e.target.getAttribute('data-key');
                const current = getSettings();
                current[key] = e.target.checked;
                saveSettings(current);
                UIManager.renderAlerts();
            };
        }
    };

    const run = () => {
        UIManager.renderAlerts();
        UIManager.injectSettingsMenu();
    };

    setTimeout(run, 2000);
    setInterval(() => UIManager.renderAlerts(), CONFIG.CHECK_INTERVAL);
    window.addEventListener('hashchange', () => setTimeout(run, 1000));
    new MutationObserver(() => { if (!document.getElementById('nav-efficiency-settings')) UIManager.injectSettingsMenu(); })
        .observe(document.body, { childList: true, subtree: true });
})();