Show plushie/flower set counts + missing items + how many more you need for next set (sorted) with null checks
// ==UserScript==
// @name Displaycase Item Sets (enhanced + sorted + safe) By Papanad
// @namespace http://tampermonkey.net/
// @version 0.8
// @description Show plushie/flower set counts + missing items + how many more you need for next set (sorted) with null checks
// @author Papanad
// @match https://www.torn.com/displaycase*
// @icon https://www.google.com/s2/favicons?sz=64&domain=torn.com
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// wait for page
window.addEventListener(
"load",
function () {
// sometimes Torn is slow to render the displaycase items, so give it a bit
setTimeout(doIt, 400);
},
false
);
const plushieIds = [258, 261, 266, 268, 269, 273, 274, 281, 384, 618];
const flowerIds = [260, 263, 264, 267, 271, 272, 276, 277, 282, 385, 617];
const plushieNames = {
258: "Teddy Bear",
261: "Kitten Plushie",
266: "Jaguar Plushie",
268: "Lion Plushie",
269: "Monkey Plushie",
273: "Penguin Plushie",
274: "Panda Plushie",
281: "Dragon Plushie",
384: "Cheshire Cat Plushie",
618: "Kappa Plushie"
};
const flowerNames = {
260: "Dahlia",
263: "Orchid",
264: "Peony",
267: "Crocus",
271: "Canna Lily",
272: "Edelweiss",
276: "Tribulus Omanense",
277: "Ceibo Flower",
282: "Banana Orchid",
385: "African Violet",
617: "Maple Leaf"
};
function doIt() {
const infoBoxEl = document.querySelector(".display-main-page");
if (!infoBoxEl) {
// page structure different / still loading
return;
}
const container = document.createElement("div");
container.style.padding = "10px";
container.style.background = "rgba(0,0,0,0.2)";
container.style.marginBottom = "10px";
container.style.border = "1px solid rgba(255,255,255,0.05)";
container.style.color = "#fff";
container.style.fontSize = "12px";
// sometimes the items list is empty at first
const items = Array.from(document.querySelectorAll("li.torn-divider"));
const plushieResult = getSetInfo(items, plushieIds, plushieNames);
const flowerResult = getSetInfo(items, flowerIds, flowerNames);
const plushieHtml = renderSection("Plushie sets", plushieResult);
const flowerHtml = renderSection("Flower sets", flowerResult);
container.innerHTML = plushieHtml + "<hr>" + flowerHtml;
infoBoxEl.insertBefore(container, infoBoxEl.firstChild);
}
/**
* Build counts, figure out current sets, missing items, and what we need for next set.
*/
function getSetInfo(allItemsEls, requiredIds, nameMap) {
// start with all required items at 0
const counts = requiredIds.map((id) => ({ id, count: 0 }));
allItemsEls.forEach((itemEl) => {
// image might not exist on some weird nodes
const img = itemEl.querySelector("img.torn-item");
if (!img || !img.src) return;
// extract numeric ID from src
const src = img.src;
const numeric = src.replace(/\D/g,'');
if (!numeric) return;
const id = Number(numeric);
const idx = counts.findIndex((x) => x.id === id);
if (idx === -1) return; // not one of the set items
// some items might not have the amount span (then assume 1)
const countEl = itemEl.querySelector(".b-item-amount");
let count = 1;
if (countEl && countEl.innerText) {
const num = Number(countEl.innerText.replace(/\D/g,''));
if (!isNaN(num) && num > 0) {
count = num;
}
}
counts[idx] = { id, count };
});
// calculate current full sets
let fullSets = 0;
if (counts.length > 0) {
// find lowest count among required items
const lowest = counts.reduce((min, cur) => cur.count < min ? cur.count : min, counts[0].count);
fullSets = typeof lowest === "number" && lowest >= 0 ? lowest : 0;
}
// which items are totally missing for 1 set
const missingForFirst = counts
.filter((x) => x.count === 0)
.map((x) => nameMap[x.id] || String(x.id));
// how many we need to reach the NEXT set
const target = fullSets + 1;
const neededForNext = counts
.map((x) => {
const need = target - x.count;
return {
id: x.id,
name: nameMap[x.id] || String(x.id),
need: need > 0 ? need : 0
};
})
.filter((x) => x.need > 0)
// sort biggest need first
.sort((a, b) => {
if (b.need !== a.need) return b.need - a.need;
return a.name.localeCompare(b.name);
});
return {
fullSets,
missingForFirst,
neededForNext
};
}
function renderSection(title, result) {
let html = `<h3 style="margin:0 0 6px 0;font-size:14px;color:#fff;">${title}: <span style="color:#7fff7f;">${result.fullSets}</span></h3>`;
// only show this line if actually missing something
if (result.missingForFirst.length > 0) {
html += `<div><strong>Missing for 1 full set:</strong> ${result.missingForFirst.join(", ")}</div>`;
} else {
html += `<div><strong>Missing for 1 full set:</strong> none ✅</div>`;
}
if (result.neededForNext.length > 0) {
html += `<div style="margin-top:4px;"><strong>To reach ${result.fullSets + 1} sets:</strong><ul style="margin:4px 0 0 16px;">`;
result.neededForNext.forEach((item) => {
html += `<li>${item.name}: need ${item.need} more</li>`;
});
html += `</ul></div>`;
}
return html;
}
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址