Torn Efficiency Manager

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

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==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 });
})();