Torn Set Trade Helper

Ensures "Max Flower" and "Max Plushie" buttons always stay on the trade page, correctly handling both categories separately.

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Torn Set Trade Helper
// @namespace    http://tampermonkey.net/
// @version      2.5.1
// @description  Ensures "Max Flower" and "Max Plushie" buttons always stay on the trade page, correctly handling both categories separately.
// @license      MIT
// @author       YoYo
// @match        https://www.torn.com/trade.php*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Relevant Flowers & Plushies
    const RELEVANT_FLOWERS = [
        "African Violet", "Banana Orchid", "Ceibo Flower", "Cherry Blossom",
        "Crocus", "Dahlia", "Edelweiss", "Heather", "Orchid", "Peony", "Tribulus Omanense"
    ];

    const RELEVANT_PLUSHIES = [
        "Camel Plushie", "Chamois Plushie", "Jaguar Plushie", "Kitten Plushie",
        "Lion Plushie", "Monkey Plushie", "Nessie Plushie", "Panda Plushie",
        "Red Fox Plushie", "Sheep Plushie", "Stingray Plushie", "Teddy Bear Plushie", "Wolverine Plushie"
    ];

    let userInventory = { flower: [], plushie: [] };
    let lowestItem = { flower: null, plushie: null };

    function checkTradePage() {
        if (window.location.href.includes("trade.php#step=add")) {
            console.log("Trade page detected");
            addTradeButtons();
        }
    }

    function interceptInventoryData() {
        const open = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function (method, url) {
            if (url.includes("inventory.php")) {
                this.addEventListener("load", function () {
                    try {
                        const responseText = this.responseText;
                        const jsonData = JSON.parse(responseText);
                        if (jsonData.list) {
                            processInventory(jsonData.list);
                        }
                    } catch (error) {
                        console.error("Error parsing inventory data:", error);
                    }
                });
            }
            return open.apply(this, arguments);
        };
    }

    function processInventory(items) {
        userInventory = { flower: [], plushie: [] };
        lowestItem = { flower: null, plushie: null };

        for (const item of items) {
            if (item.type2 === "Flower" && RELEVANT_FLOWERS.includes(item.name)) {
                const parsedItem = { name: item.name, quantity: parseInt(item.Qty, 10), id: item.armoryID };
                userInventory.flower.push(parsedItem);

                if (!lowestItem.flower || parsedItem.quantity < lowestItem.flower.quantity) {
                    lowestItem.flower = parsedItem;
                }
            } else if (item.type2 === "Plushie" && RELEVANT_PLUSHIES.includes(item.name)) {
                const parsedItem = { name: item.name, quantity: parseInt(item.Qty, 10), id: item.armoryID };
                userInventory.plushie.push(parsedItem);

                if (!lowestItem.plushie || parsedItem.quantity < lowestItem.plushie.quantity) {
                    lowestItem.plushie = parsedItem;
                }
            }
        }

        console.log("Updated Inventory:", userInventory);
        console.log("Lowest Items:", lowestItem);
    }

    function addTradeButtons() {
        const footerDiv = document.querySelector(".items-footer.clearfix");
        if (!footerDiv) return;

        ["flower", "plushie"].forEach(type => {
            if (!document.getElementById(`max-${type}-btn`)) {
                const button = document.createElement("input");
                button.type = "button";
                button.value = `Max ${type.charAt(0).toUpperCase() + type.slice(1)}`;
                button.classList.add("torn-btn", "left");
                button.id = `max-${type}-btn`;
                button.style.marginLeft = "10px";
                button.addEventListener("click", () => fillMaxItems(type));
                footerDiv.appendChild(button);
            }
        });
    }

    function fillMaxItems(type) {
        if (!lowestItem[type]) {
            alert(`No ${type}s found to add.`);
            console.log(`No ${type}s found.`);
            return;
        }

        const missingItems = (type === "flower" ? RELEVANT_FLOWERS : RELEVANT_PLUSHIES).filter(name =>
            !userInventory[type].some(item => item.name === name)
        );

        if (missingItems.length > 0) {
            alert(`⚠️ Missing: ${missingItems.join(", ")}\nTrade not updated.`);
            console.log(`Missing ${type}s: ${missingItems.join(", ")} - Trade action blocked.`);
            return;
        }

        const lowestQty = lowestItem[type].quantity - 1;
        console.log(`Setting all ${type}s to ${lowestQty}.`);

        document.querySelectorAll("li.clearfix[data-group='child']").forEach(item => {
            const nameElement = item.querySelector(".t-overflow");
            if (!nameElement) return;
            const itemName = nameElement.innerText.trim();

            // Correctly distinguish flowers and plushies
            if ((type === "flower" && !RELEVANT_FLOWERS.includes(itemName)) ||
                (type === "plushie" && !RELEVANT_PLUSHIES.includes(itemName))) {
                console.log(`Skipping non-relevant ${type}: ${itemName}`);
                return;
            }

            const inputField = item.querySelector("input[name='amount']");
            if (inputField) {
                inputField.value = lowestQty;
                inputField.dispatchEvent(new Event("input", { bubbles: true }));
                console.log(`Set ${itemName} to ${lowestQty}`);
            }
        });

        alert(`All ${type}s set to ${lowestQty}.`);
    }

    function observeDOMChanges() {
        const observer = new MutationObserver(() => addTradeButtons());
        observer.observe(document.body, { childList: true, subtree: true });
    }

    window.addEventListener("load", checkTradePage);
    window.addEventListener("hashchange", checkTradePage);
    interceptInventoryData();
    observeDOMChanges();
})();