Torn Display Case Sets Tracker (Detailed)

Track flower and plushie sets in display case, show breakdown with available and missing counts.

当前为 2025-10-01 提交的版本,查看 最新版本

// ==UserScript==
// @name         Torn Display Case Sets Tracker (Detailed)
// @namespace    http://tampermonkey.net/
// @version      1.1
// @description  Track flower and plushie sets in display case, show breakdown with available and missing counts.
// @author       Nova
// @match        https://www.torn.com/displaycase.php*
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';

    // Define required sets
    const FLOWERS = [
        "Dahlia", "Orchid", "African Violet", "Cherry Blossom", "Peony", "Ceibo Flower",
        "Edelweiss", "Crocus", "Heather", "Tribulus Omanense", "Banana Orchid"
    ];

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

    // Panel styling
    GM_addStyle(`
      #setTrackerPanel {
        position: fixed;
        top: 100px;
        left: 20px;
        width: 350px;
        background: #fff;
        color: #000;
        font-family: monospace;
        font-size: 12px;
        border: 1px solid #444;
        border-radius: 6px;
        padding: 8px;
        z-index: 9999;
        box-shadow: 0 0 10px rgba(0,0,0,0.4);
        max-height: 500px;
        overflow-y: auto;
      }
      #setTrackerPanel b { font-size: 13px; }
      #setTrackerPanel ul { margin: 2px 0 6px 15px; padding: 0; }
      #setTrackerPanel li { margin: 0; list-style: none; }
    `);

    const panel = document.createElement("div");
    panel.id = "setTrackerPanel";
    panel.innerHTML = `<b>Loading sets...</b>`;
    document.body.appendChild(panel);

    // Parse items in display case
    function parseCase() {
        const items = {};
        document.querySelectorAll(".item-wrap .title").forEach(el => {
            const name = el.textContent.trim();
            const qtyEl = el.closest(".item-wrap").querySelector(".qty");
            const qty = qtyEl ? parseInt(qtyEl.textContent.replace("x","").trim()) : 1;
            items[name] = (items[name] || 0) + qty;
        });
        return items;
    }

    // Calculate sets and per-item details
    function calcSets(required, items) {
        const counts = required.map(name => items[name] || 0);
        const complete = Math.min(...counts);

        // Remaining stock after full sets are used
        const remaining = {};
        required.forEach(name => {
            remaining[name] = (items[name] || 0) - complete;
        });

        // Missing for next set
        const missing = {};
        required.forEach(name => {
            const need = 1;
            const have = remaining[name];
            missing[name] = have >= need ? 0 : need - have;
        });

        return { complete, remaining, missing };
    }

    // Update floating panel
    function updatePanel() {
        const items = parseCase();

        const flowers = calcSets(FLOWERS, items);
        const plushies = calcSets(PLUSHIES, items);

        let html = `
          <b>Flower Sets:</b> ${flowers.complete}<br>
          <b>Plushie Sets:</b> ${plushies.complete}<br><br>
          <b>Flowers Breakdown:</b><br>
          <ul>
            ${FLOWERS.map(name => {
                const total = items[name] || 0;
                const av = flowers.remaining[name];
                const ms = flowers.missing[name];
                return `<li>${name}: ${total} (av ${av}, ms ${ms})</li>`;
            }).join("")}
          </ul>
          <b>Plushies Breakdown:</b><br>
          <ul>
            ${PLUSHIES.map(name => {
                const total = items[name] || 0;
                const av = plushies.remaining[name];
                const ms = plushies.missing[name];
                return `<li>${name}: ${total} (av ${av}, ms ${ms})</li>`;
            }).join("")}
          </ul>
        `;

        panel.innerHTML = html;
    }

    // Run after page loads
    setTimeout(updatePanel, 1000);
})();