Torn Company Loadouts

Save, load, export, and import worker presets. Hide unnecessary info messages.

// ==UserScript==
// @name         Torn Company Loadouts
// @namespace    Apo
// @version      4.1
// @description  Save, load, export, and import worker presets. Hide unnecessary info messages.
// @author       Apollyon [445323]
// @match        https://www.torn.com/companies.php*
// @match        https://pda.torn.com/companies.php*
// @icon         https://www.google.com/s2/favicons?domain=torn.com
// @license      MIT
// @grant        none
// ==/UserScript==

(function () {
    "use strict";

    // Adding styles for buttons
    const addStyles = () => {
        const style = document.createElement("style");
        style.innerHTML = `
      .button-3 {
        appearance: none;
        background-color: #2ea44f;
        border: 1px solid rgba(27, 31, 35, .15);
        border-radius: 6px;
        box-shadow: rgba(27, 31, 35, .1) 0 1px 0;
        box-sizing: border-box;
        color: #fff;
        cursor: pointer;
        display: inline-block;
        font-family: -apple-system,system-ui,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
        font-size: 14px;
        font-weight: 600;
        line-height: 20px;
        padding: 6px 16px;
        position: relative;
        text-align: center;
        text-decoration: none;
        user-select: none;
        -webkit-user-select: none;
        touch-action: manipulation;
        vertical-align: middle;
        white-space: nowrap;
        margin-right: 10px;
        margin-top: 10px;
      }

      .button-3:focus:not(:focus-visible):not(.focus-visible) {
        box-shadow: none;
        outline: none;
      }

      .button-3:hover {
        background-color: #2c974b;
      }

      .button-3:focus {
        box-shadow: rgba(46, 164, 79, .4) 0 0 0 3px;
        outline: none;
      }

      .button-3:disabled {
        background-color: #94d3a2;
        border-color: rgba(27, 31, 35, .1);
        color: rgba(255, 255, 255, .8);
        cursor: default;
      }

      .button-3:active {
        background-color: #298e46;
        box-shadow: rgba(20, 70, 32, .2) 0 1px 0 inset;
      }

      .button-green {
        background-color: #2ea44f;
      }

      .button-green:hover {
        background-color: #2c974b;
      }

      .button-red {
        background-color: #d73a49;
      }

      .button-red:hover {
        background-color: #c23540;
      }

      .button-blue {
        background-color: #0366d6;
      }

      .button-blue:hover {
        background-color: #035fc4;
      }

      .button-orange {
        background-color: #f66a0a;
      }

      .button-orange:hover {
        background-color: #e36209;
      }

      .button-custom {
        background-color: #00cc99; /* Custom color for Save button */
      }

      .button-custom:hover {
        background-color: #00b386; /* Darker shade for hover */
      }

      /* Dropdown Styles */
      #presetDropdown {
        background-color: #525252; /* Dropdown background color */
        color: #ffffff; /* Dropdown text color */
        border: 1px solid rgba(27, 31, 35, .15);
        border-radius: 6px;
        padding: 6px 16px; /* Adjust padding to match buttons */
        font-family: inherit; /* Inherit font family */
        font-size: 14px; /* Match button font size */
        font-weight: 600; /* Match button font weight */
        cursor: pointer; /* Pointer cursor */
        margin-top: 10px; /* Match button margin */
      }
    `;
        document.head.appendChild(style);
    };

    // Function to save presets to localStorage
    const savePresetsToLocalStorage = () => {
        localStorage.setItem("tornPresets", JSON.stringify(presets));
    };

    // Function to load presets from localStorage
    const loadPresetsFromLocalStorage = () => {
        const storedPresets = localStorage.getItem("tornPresets");
        return storedPresets ? JSON.parse(storedPresets) : [];
    };

    // Array to store presets
    let presets = loadPresetsFromLocalStorage();

    // Function to save presets
    const savePresets = () => {
        const presetName = prompt("Enter a name for the preset:");
        if (!presetName) return; // Cancelled or empty name

        const workerDivs = document.querySelectorAll(".employee-list>li");
        if (!workerDivs.length) {
            console.error("No worker divs found.");
            return;
        }

        const preset = { name: presetName, workers: [] };
        workerDivs.forEach((workerDiv) => {
            const employeeId = workerDiv.getAttribute("data-user");
            const rankDiv = workerDiv.querySelector(".employee-rank");

            if (!rankDiv) {
                console.error("Rank information not found for a worker.");
                return;
            }

            const selectedRank = rankDiv.value;
            preset.workers.push({ employeeId, selectedRank });
        });

        presets.push(preset);
        savePresetsToLocalStorage();
        alert(`Preset '${presetName}' saved successfully!`);

        // Update the dropdown immediately after saving the preset
        updatePresetDropdown();
    };

    // Function to update worker rank
    const updateWorker = (employeeId, selectedRank) => {
        const workerDiv = document.querySelector(`li[data-user='${employeeId}']`);
        if (!workerDiv) {
            console.error(`Worker with ID ${employeeId} not found.`);
            return;
        }
        const rankDiv = workerDiv.querySelector(".employee-rank");
        if (rankDiv) {
            rankDiv.value = selectedRank; // Update the rank
            // Trigger change event if necessary
            rankDiv.dispatchEvent(new Event('change', { bubbles: true }));
        } else {
            console.error(`Rank element not found for worker ID ${employeeId}.`);
        }
    };

    // Function to load presets
    const loadPresets = () => {
        const presetDropdown = document.getElementById("presetDropdown");
        const selectedPresetIndex = presetDropdown.selectedIndex;
        if (selectedPresetIndex === -1) {
            console.log("No preset selected.");
            return; // No preset selected
        }

        const selectedPreset = presets[selectedPresetIndex];
        console.log("Loading preset:", selectedPreset); // Log selected preset
        selectedPreset.workers.forEach(({ employeeId, selectedRank }) => {
            console.log(`Updating worker ID ${employeeId} to rank ${selectedRank}`); // Log updates
            updateWorker(employeeId, selectedRank);
        });
        alert(`Preset '${selectedPreset.name}' loaded successfully!`);
    };

    // Function to delete the selected preset
    const deletePreset = () => {
        const presetDropdown = document.getElementById("presetDropdown");
        const selectedPresetIndex = presetDropdown.selectedIndex;
        if (selectedPresetIndex === -1) return; // No preset selected

        const deletedPresetName = presets[selectedPresetIndex].name;
        presets.splice(selectedPresetIndex, 1);
        savePresetsToLocalStorage();
        alert(`Preset '${deletedPresetName}' deleted successfully!`);
        updatePresetDropdown();
    };

    // Function to export presets
    const exportPresets = () => {
        const presetData = JSON.stringify(presets);
        const textArea = document.createElement("textarea");
        textArea.value = presetData;
        document.body.appendChild(textArea);
        textArea.select();
        document.execCommand("copy");
        document.body.removeChild(textArea);
        alert("Presets exported and copied to clipboard!");
    };

    // Function to import presets
    const importPresets = () => {
        const importedData = prompt("Paste the preset data here:");
        if (!importedData) return; // Cancelled or empty input

        try {
            const importedPresets = JSON.parse(importedData);
            presets = importedPresets;
            savePresetsToLocalStorage();
            alert("Presets imported successfully!");
            updatePresetDropdown();
        } catch (error) {
            alert("Invalid preset data! Please check and try again.");
        }
    };

    // Function to update the preset dropdown menu
    const updatePresetDropdown = () => {
        const existingDropdown = document.getElementById("presetDropdown");
        if (existingDropdown) {
            existingDropdown.parentNode.removeChild(existingDropdown);
        }

        const presetDropdown = document.createElement("select");
        presetDropdown.id = "presetDropdown";

        presets.forEach((preset) => {
            const option = document.createElement("option");
            option.value = preset.name;
            option.text = preset.name;
            presetDropdown.add(option);
        });

        const existingButtonsContainer = document.getElementById("presetButtonsContainer");
        if (existingButtonsContainer) {
            existingButtonsContainer.parentNode.removeChild(existingButtonsContainer);
        }

        const infoMessage = document.querySelector(".info-msg");
        if (infoMessage) {
            const buttonsContainer = document.createElement("div");
            buttonsContainer.id = "presetButtonsContainer";

            // Creating buttons in the desired order
            const loadButton = document.createElement("button");
            loadButton.textContent = "Load Presets";
            loadButton.className = "button-3 button-green"; // Green for Load
            loadButton.addEventListener("click", loadPresets);

            const saveButton = document.createElement("button");
            saveButton.textContent = "Save Presets";
            saveButton.className = "button-3 button-custom"; // Custom color for Save
            saveButton.addEventListener("click", savePresets);

            const importButton = document.createElement("button");
            importButton.textContent = "Import Presets";
            importButton.className = "button-3 button-blue"; // Blue for Import
            importButton.addEventListener("click", importPresets);

            const exportButton = document.createElement("button");
            exportButton.textContent = "Export Presets";
            exportButton.className = "button-3 button-orange"; // Orange for Export
            exportButton.addEventListener("click", exportPresets);

            const deleteButton = document.createElement("button");
            deleteButton.textContent = "Delete Preset";
            deleteButton.className = "button-3 button-red"; // Red for Delete
            deleteButton.addEventListener("click", deletePreset);

            // Append buttons in the specified order
            buttonsContainer.appendChild(loadButton);
            buttonsContainer.appendChild(saveButton);
            buttonsContainer.appendChild(importButton);
            buttonsContainer.appendChild(exportButton);
            buttonsContainer.appendChild(deleteButton);

            infoMessage.parentNode.insertBefore(buttonsContainer, infoMessage.nextSibling);
            infoMessage.parentNode.insertBefore(presetDropdown, buttonsContainer.nextSibling);
        }
    };

    // Function to hide the info message
    const hideInfoMessage = () => {
        const infoMessage = document.querySelector(".info-msg");
        if (infoMessage) {
            infoMessage.style.display = "none";
        }
    };

    // Run the script
    addStyles();         // Add the button styles to the document
    updatePresetDropdown(); // Update the dropdown
    hideInfoMessage();   // Hide the info message
})();