Drop item log — draggable, tooltip, removes deleted items
// ==UserScript==
// @name IdleHacking Drop Log Panel moveable
// @author Fusi0n + claude
// @namespace http://tampermonkey.net/
// @version 6.0
// @description Drop item log — draggable, tooltip, removes deleted items
// @match *://*.idlehacking.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function () {
'use strict';
const seenItems = new Map();
let isDraggable = false;
let dragging = false;
let dragOffX = 0, dragOffY = 0;
let panel = null;
function waitForInventory() {
const grid = document.querySelector('#inventory-grid');
if (!grid) { setTimeout(waitForInventory, 1000); return; }
createPanel();
startScanner();
}
function createPanel() {
if (document.getElementById('drop-log-panel')) return;
panel = document.createElement('div');
panel.id = 'drop-log-panel';
panel.innerHTML = `
<div id="drop-log-header">
<span id="drop-log-title">Drop Log</span>
<button id="drop-log-drag-btn" title="Toggle free drag">⬜</button>
</div>
<div id="drop-log-content"></div>
`;
Object.assign(panel.style, {
position: 'fixed',
bottom: '20px',
right: '5px', // nudged right
width: '260px',
height: '300px',
background: '#0b0f1a',
border: '1px solid #1f2a44',
borderRadius: '10px',
zIndex: 1000,
display: 'flex',
flexDirection: 'column',
boxShadow: '0 0 15px rgba(0,0,0,0.6)',
fontSize: '13px',
color: '#cdd6f4',
fontFamily: 'sans-serif',
boxSizing: 'border-box',
overflow: 'hidden',
transition: 'box-shadow 0.2s'
});
const header = panel.querySelector('#drop-log-header');
Object.assign(header.style, {
padding: '6px 8px',
borderBottom: '1px solid #1f2a44',
fontWeight: 'bold',
background: '#121a2b',
borderRadius: '10px 10px 0 0',
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
userSelect: 'none',
cursor: 'default'
});
const btn = panel.querySelector('#drop-log-drag-btn');
Object.assign(btn.style, {
background: 'transparent',
border: '1px solid #2a3a5a',
borderRadius: '4px',
color: '#5a7ab5',
cursor: 'pointer',
fontSize: '11px',
padding: '2px 5px',
lineHeight: '1',
transition: 'color 0.2s, border-color 0.2s'
});
btn.onmouseenter = () => { btn.style.color = '#89b4fa'; btn.style.borderColor = '#89b4fa'; };
btn.onmouseleave = () => {
if (!isDraggable) { btn.style.color = '#5a7ab5'; btn.style.borderColor = '#2a3a5a'; }
};
const content = panel.querySelector('#drop-log-content');
Object.assign(content.style, {
padding: '6px 6px 6px 8px',
overflowY: 'auto',
overflowX: 'hidden',
flex: '1',
minWidth: '0'
});
document.body.appendChild(panel);
btn.addEventListener('click', toggleDrag);
}
// ── Drag toggle ────────────────────────────────────────────────────────────
function toggleDrag() {
isDraggable = !isDraggable;
const btn = document.getElementById('drop-log-drag-btn');
const header = document.getElementById('drop-log-header');
if (isDraggable) {
const rect = panel.getBoundingClientRect();
panel.style.top = rect.top + 'px';
panel.style.left = rect.left + 'px';
panel.style.bottom = '';
panel.style.right = '';
btn.innerHTML = '✔';
btn.title = 'Lock back to bottom-right';
btn.style.color = '#89b4fa';
btn.style.borderColor = '#89b4fa';
panel.style.boxShadow = '0 0 20px rgba(137,180,250,0.35)';
header.style.cursor = 'grab';
enableDrag();
} else {
disableDrag();
panel.style.bottom = '20px';
panel.style.right = '5px';
panel.style.top = '';
panel.style.left = '';
btn.innerHTML = '⬜';
btn.title = 'Toggle free drag';
btn.style.color = '#5a7ab5';
btn.style.borderColor = '#2a3a5a';
panel.style.boxShadow = '0 0 15px rgba(0,0,0,0.6)';
header.style.cursor = 'default';
}
}
function enableDrag() {
document.getElementById('drop-log-header').addEventListener('mousedown', onDragStart);
}
function disableDrag() {
document.getElementById('drop-log-header').removeEventListener('mousedown', onDragStart);
}
function onDragStart(e) {
if (e.target.id === 'drop-log-drag-btn') return;
dragging = true;
const rect = panel.getBoundingClientRect();
dragOffX = e.clientX - rect.left;
dragOffY = e.clientY - rect.top;
document.getElementById('drop-log-header').style.cursor = 'grabbing';
e.preventDefault();
}
document.addEventListener('mousemove', e => {
if (!dragging) return;
panel.style.left = (e.clientX - dragOffX) + 'px';
panel.style.top = (e.clientY - dragOffY) + 'px';
});
document.addEventListener('mouseup', () => {
if (!dragging) return;
dragging = false;
if (isDraggable) document.getElementById('drop-log-header').style.cursor = 'grab';
});
// ── Scanner — unchanged v5.2 logic ────────────────────────────────────────
function startScanner() {
setInterval(() => {
const items = document.querySelectorAll('#inventory-grid .inventory-slot');
const currentItems = new Set();
items.forEach(node => {
const itemId = node.getAttribute('data-item-id');
if (!itemId) return;
currentItems.add(itemId);
if (!seenItems.has(itemId)) {
seenItems.set(itemId, node);
const name = node.querySelector('.item-name')?.innerText || 'Unknown';
const level = node.querySelector('.inventory-item-level-top')?.innerText || '';
const rarityClass = [...node.classList].find(c => c.startsWith('rarity-')) || 'rarity-common';
const rarity = rarityClass.replace('rarity-', '');
addToLog(name, level, rarity, itemId);
}
});
// Remove deleted items
seenItems.forEach((_, itemId) => {
if (!currentItems.has(itemId)) {
removeFromLog(itemId);
seenItems.delete(itemId);
}
});
}, 1000);
}
// ── Rarity colours ────────────────────────────────────────────────────────
function getRarityColor(rarity) {
return {
common: '#aaa',
uncommon: '#4caf50',
rare: '#2196f3',
epic: '#9c27b0',
legendary: '#ff9800'
}[rarity] || '#fff';
}
// ── Log entry ─────────────────────────────────────────────────────────────
function addToLog(name, level, rarity, itemId) {
const content = document.getElementById('drop-log-content');
if (!content) return;
const entry = document.createElement('div');
entry.dataset.itemId = itemId;
entry.style.marginBottom = '6px';
const rarityEl = document.createElement('div');
rarityEl.textContent = rarity.toUpperCase();
Object.assign(rarityEl.style, {
color: getRarityColor(rarity),
fontWeight: 'bold',
fontSize: '11px'
});
const nameEl = document.createElement('div');
nameEl.textContent = name;
Object.assign(nameEl.style, {
cursor: 'pointer',
textDecoration: 'underline dotted',
textUnderlineOffset: '2px',
color: '#cdd6f4'
});
nameEl.title = 'Click to show tooltip';
nameEl.onmouseenter = () => nameEl.style.color = '#fff';
nameEl.onmouseleave = () => nameEl.style.color = '#cdd6f4';
nameEl.addEventListener('click', () => {
const node = seenItems.get(itemId);
if (node) {
node.scrollIntoView({ behavior: 'smooth', block: 'center' });
node.click();
}
});
const levelEl = document.createElement('div');
levelEl.textContent = level ? `Lv ${level}` : '';
Object.assign(levelEl.style, { fontSize: '11px', opacity: '0.7' });
const hr = document.createElement('hr');
Object.assign(hr.style, { border: '0', borderTop: '1px solid #1f2a44', margin: '4px 0 0' });
entry.appendChild(rarityEl);
entry.appendChild(nameEl);
if (level) entry.appendChild(levelEl);
entry.appendChild(hr);
content.prepend(entry);
if (content.children.length > 100) content.removeChild(content.lastChild);
}
function removeFromLog(itemId) {
const entry = document.querySelector(`#drop-log-content [data-item-id="${itemId}"]`);
if (entry) {
entry.style.transition = 'opacity 0.3s';
entry.style.opacity = '0';
setTimeout(() => entry.remove(), 300);
}
}
waitForInventory();
})();