OC Role Display

Shows role positions

当前为 2025-02-13 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         OC Role Display
// @namespace    http://tampermonkey.net/
// @version      1.0.0
// @description  Shows role positions
// @author       Allenone [2033011]
// @match        https://www.torn.com/factions.php?step=your*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    let buttonObserver;
    let wrapperObserver;

    // Run on page load or hash change
    function doOnHashChange() {
        const ocElements = document.querySelectorAll('.wrapper___U2Ap7');
        if (ocElements.length === 0) return; // Prevent running on empty state
        console.log("Updating roles...", ocElements);

        for (let element of ocElements) {
            const reactFiberKey = Object.keys(element).find(key => key.startsWith("__reactFiber$"));
            if (!reactFiberKey) continue;

            let ocName = element.querySelector('.panelTitle___aoGuV')?.innerText || "Unknown";
            let slots = element.querySelectorAll('.wrapper___Lpz_D');

            for (let slot of slots) {
                const slotFiberKey = Object.keys(slot).find(key => key.startsWith("__reactFiber$"));
                if (!slotFiberKey) continue;

                let roleName = slot.querySelector('.title___UqFNy');

                try {
                    let fiberNode = slot[slotFiberKey];
                    let key = fiberNode.return.key;

                    let roleText = getOCRoles(ocName, key);
                    if (roleText && roleName.innerText !== roleText) {
                        roleName.innerText = roleText;
                        console.log(`Updated ${key} in ${ocName} -> ${roleText}`);
                    }
                } catch (error) {
                    console.error("Error accessing React properties:", error);
                }
            }
        }
    }

    function getOCRoles(name, position) {
        switch (name) {
            case 'Blast From The Past':
                switch (position) {
                    case 'slot-P1': return 'Picklock 1';
                    case 'slot-P6': return 'Picklock 2';
                    default: return;
                }
            case 'Honey Trap':
                switch (position) {
                    case 'slot-P2': return 'Muscle 1';
                    case 'slot-P3': return 'Muscle 2';
                    default: return;
                }
            case 'Stage Fright':
                switch (position) {
                    case 'slot-P2': return 'Muscle 1';
                    case 'slot-P3': return 'Muscle 2';
                    case 'slot-P4': return 'Muscle 3';
                    default: return;
                }
            case 'Break The Bank':
                switch (position) {
                    case 'slot-P2': return 'Muscle 1';
                    case 'slot-P3': return 'Muscle 2';
                    case 'slot-P4': return 'Thief 1';
                    case 'slot-P5': return 'Muscle 3';
                    case 'slot-P6': return 'Thief 2';
                    default: return;
                }
            case 'Snow Blind':
                switch (position) {
                    case 'slot-P3': return 'Muscle 1';
                    case 'slot-P4': return 'Muscle 2';
                    default: return;
                }
            case 'Smoke and Wing Mirrors':
                switch (position) {
                    case 'slot-P3': return 'Hustler 1';
                    case 'slot-P4': return 'Hustler 2';
                    default: return;
                }
            case 'Cash Me If You Can':
                switch (position) {
                    case 'slot-P1': return 'Thief 1';
                    case 'slot-P2': return 'Thief 2';
                    default: return;
                }
            case 'Mob Mentality':
                switch (position) {
                    case 'slot-P1': return 'Looter 1';
                    case 'slot-P2': return 'Looter 2';
                    case 'slot-P3': return 'Looter 3';
                    case 'slot-P4': return 'Looter 4';
                    default: return;
                }
            default:
                return;
        }
    }

    function observeButtonContainer() {
        let buttonContainer = document.querySelector('.buttonsContainer___aClaa');
        if (buttonContainer) {
            buttonContainer.addEventListener('click', () => {
                console.log("Button clicked in buttonsContainer. Waiting for content reload...");

                if (wrapperObserver) wrapperObserver.disconnect();

                waitForElementsToReload('.wrapper___U2Ap7').then(() => {
                    console.log("New elements detected. Refreshing roles...");
                    doOnHashChange();
                });
            });
        } else {
            console.warn("buttonsContainer not found. Retrying in 500ms...");
            setTimeout(observeButtonContainer, 500);
        }
    }

    function waitForElementsToReload(selector) {
        return new Promise(resolve => {
            let checkInterval = setInterval(() => {
                if (!document.querySelector(selector)) {
                    clearInterval(checkInterval);

                    wrapperObserver = new MutationObserver(() => {
                        if (document.querySelectorAll(selector).length > 0) {
                            clearInterval(checkInterval);
                            resolve();
                            wrapperObserver.disconnect();
                        }
                    });

                    wrapperObserver.observe(document.body, { childList: true, subtree: true });
                }
            }, 100); // Check every 100ms if elements have disappeared
        });
    }

    // Ensure page load is complete before starting
    window.addEventListener('load', () => {
        console.log("Page loaded. Refreshing roles...");
        doOnHashChange(); // Run once immediately after page load

        // Start observing button container
        observeButtonContainer();

        // Start observing hash change
        window.addEventListener('hashchange', () => {
            console.log("Hash changed. Refreshing roles...");
            waitForElementsToReload('.wrapper___U2Ap7').then(() => {
                doOnHashChange();
            });
        });
    });

    // Reload after page is fully loaded, and ensure wrapper___U2Ap7 elements are visible.
    function waitForWrapperElements() {
        let wrapperElements = document.querySelectorAll('.wrapper___U2Ap7');
        if (wrapperElements.length > 0) {
            console.log("Initial wrapper elements found. Refreshing roles...");
            doOnHashChange();
        } else {
            setTimeout(waitForWrapperElements, 500); // Wait and check again
        }
    }

    // Initial check after page load
    waitForWrapperElements();
})();