Monster Lab floating panel + page detection, Beast recommendation

- Monster Lab page detected via ss=ml
- Floating draggable panel replaces inline UI (was messing layout)
- Feed All + Happy Pills All buttons
- Class recommendation for first monster
- Drag-to-move via header grab
This commit is contained in:
GaboGG 2026-07-20 20:35:14 -04:00
parent e8c3f465d2
commit 4bc90d9332
5 changed files with 267 additions and 72 deletions

View file

@ -269,6 +269,7 @@ function detectPage() {
'ss=rf': 'reforge',
'ss=sf': 'soulfuse',
'ss=ab': 'abilities',
'ss=ml': 'monster',
'ss=it': 'invitems',
'ss=se': 'settings',
'ss=ss': 'spiritshop',
@ -1805,38 +1806,101 @@ function enhanceTraining() {
if (ta) ta.insertBefore(d, ta.firstChild);
}
// ── Monster Lab: feed all ──
// ── Monster Lab: floating info panel + feed buttons ──
let _mlDragOffset = { x: 0, y: 0 };
function enhanceMonsterLab() {
const m = document.getElementById('mainpane');
if (!m || document.getElementById('hv-lab-enhance')) return;
// Create floating draggable panel
if (document.getElementById('hv-monster')) return;
const r = document.createElement('div');
r.id = 'hv-lab-enhance';
r.style.cssText = 'margin:8px;padding:8px;display:flex;gap:8px';
const panel = document.createElement('div');
panel.id = 'hv-monster';
panel.style.cssText = css({
position: 'fixed',
top: '80px',
right: '4px',
zIndex: '9999',
background: '#111827',
color: '#d1d5db',
padding: '8px 10px',
borderRadius: '8px',
fontSize: '10px',
fontFamily: 'monospace',
maxWidth: '320px',
boxShadow: '0 0 15px rgba(0,0,0,0.6)',
border: '1px solid #374151',
cursor: 'move',
userSelect: 'none',
});
const f = document.createElement('input');
f.type = 'button';
f.value = '🍖 Feed All';
f.style.cssText = 'padding:4px 10px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:11px';
f.onclick = () => { $$('input[value="Feed"]', m).forEach(b => b.click()); };
const body = `<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;cursor:move" id="hv-monster-header">
<b style="color:#fdcb00;font-size:11px">🧬 Monster Lab</b>
<span id="hv-monster-toggle" style="color:#888;font-size:14px;cursor:pointer"></span>
</div>
<div id="hv-monster-body">
<div style="margin-bottom:6px;display:flex;gap:4px">
<input type="button" value="🍖 Feed All" style="padding:4px 10px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:11px" id="hv-feed-all">
<input type="button" value="💊 Happy Pills All" style="padding:4px 10px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:11px" id="hv-pill-all">
</div>
<div style="color:#9ca3af;font-size:9px;border-top:1px solid #374151;padding-top:4px">
New to ML? Pick a <b style="color:#fdcb00">Beast-class</b> (Dog/Cow/Pig) for STR/END crystals.<br>
<span style="color:#888">Click + drag header to move.</span>
</div>
</div>`;
const p = document.createElement('input');
p.type = 'button';
p.value = '💊 Happy Pills All';
p.style.cssText = 'padding:4px 10px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:11px';
p.onclick = () => {
const pills = $$('option', m).filter(o => (o.textContent || '').includes('Happy Pill'));
if (pills.length > 0) {
pills[0].selected = true;
$$('input[value="Feed"]', m).forEach(b => b.click());
panel.innerHTML = body;
document.body.appendChild(panel);
// ── Feed All ──
panel.querySelector('#hv-feed-all').onclick = () => {
const m = document.getElementById('mainpane');
if (m) $$('input[value="Feed"]', m).forEach(b => b.click());
};
// ── Happy Pills All ──
panel.querySelector('#hv-pill-all').onclick = () => {
const m = document.getElementById('mainpane');
if (m) {
const pills = $$('option', m).filter(o => (o.textContent || '').includes('Happy Pill'));
if (pills.length > 0) {
pills[0].selected = true;
$$('input[value="Feed"]', m).forEach(b => b.click());
}
}
};
r.appendChild(f);
r.appendChild(p);
const ta = m.querySelector('div');
if (ta) ta.insertBefore(r, ta.firstChild);
// ── Toggle ──
panel.querySelector('#hv-monster-toggle').onclick = () => {
const body = panel.querySelector('#hv-monster-body');
const isHidden = body.style.display === 'none';
body.style.display = isHidden ? 'block' : 'none';
panel.querySelector('#hv-monster-toggle').textContent = isHidden ? '' : '+';
};
// ── Make draggable ──
const header = panel.querySelector('#hv-monster-header');
if (header) {
header.addEventListener('mousedown', (e) => {
_mlDragOffset.x = e.clientX - panel.getBoundingClientRect().left;
_mlDragOffset.y = e.clientY - panel.getBoundingClientRect().top;
const onMove = (ev) => {
panel.style.left = (ev.clientX - _mlDragOffset.x) + 'px';
panel.style.right = 'auto';
panel.style.top = (ev.clientY - _mlDragOffset.y) + 'px';
};
const onUp = () => {
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
};
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
});
}
// Remove the old inline bar if it exists
const oldBar = document.getElementById('hv-lab-enhance');
if (oldBar) oldBar.remove();
}
// ── Config button (bottom-right) ──
@ -2803,6 +2867,7 @@ function init() {
if (STATE.page === 'character') showGuidancePanel();
if (STATE.page === 'armory') enhanceArmory();
if (STATE.page === 'abilities') enhanceAbilities();
if (STATE.page === 'monster') enhanceMonsterLab();
}
// Dawn initialization

View file

@ -269,6 +269,7 @@ function detectPage() {
'ss=rf': 'reforge',
'ss=sf': 'soulfuse',
'ss=ab': 'abilities',
'ss=ml': 'monster',
'ss=it': 'invitems',
'ss=se': 'settings',
'ss=ss': 'spiritshop',
@ -1805,38 +1806,101 @@ function enhanceTraining() {
if (ta) ta.insertBefore(d, ta.firstChild);
}
// ── Monster Lab: feed all ──
// ── Monster Lab: floating info panel + feed buttons ──
let _mlDragOffset = { x: 0, y: 0 };
function enhanceMonsterLab() {
const m = document.getElementById('mainpane');
if (!m || document.getElementById('hv-lab-enhance')) return;
// Create floating draggable panel
if (document.getElementById('hv-monster')) return;
const r = document.createElement('div');
r.id = 'hv-lab-enhance';
r.style.cssText = 'margin:8px;padding:8px;display:flex;gap:8px';
const panel = document.createElement('div');
panel.id = 'hv-monster';
panel.style.cssText = css({
position: 'fixed',
top: '80px',
right: '4px',
zIndex: '9999',
background: '#111827',
color: '#d1d5db',
padding: '8px 10px',
borderRadius: '8px',
fontSize: '10px',
fontFamily: 'monospace',
maxWidth: '320px',
boxShadow: '0 0 15px rgba(0,0,0,0.6)',
border: '1px solid #374151',
cursor: 'move',
userSelect: 'none',
});
const f = document.createElement('input');
f.type = 'button';
f.value = '🍖 Feed All';
f.style.cssText = 'padding:4px 10px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:11px';
f.onclick = () => { $$('input[value="Feed"]', m).forEach(b => b.click()); };
const body = `<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;cursor:move" id="hv-monster-header">
<b style="color:#fdcb00;font-size:11px">🧬 Monster Lab</b>
<span id="hv-monster-toggle" style="color:#888;font-size:14px;cursor:pointer"></span>
</div>
<div id="hv-monster-body">
<div style="margin-bottom:6px;display:flex;gap:4px">
<input type="button" value="🍖 Feed All" style="padding:4px 10px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:11px" id="hv-feed-all">
<input type="button" value="💊 Happy Pills All" style="padding:4px 10px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:11px" id="hv-pill-all">
</div>
<div style="color:#9ca3af;font-size:9px;border-top:1px solid #374151;padding-top:4px">
New to ML? Pick a <b style="color:#fdcb00">Beast-class</b> (Dog/Cow/Pig) for STR/END crystals.<br>
<span style="color:#888">Click + drag header to move.</span>
</div>
</div>`;
const p = document.createElement('input');
p.type = 'button';
p.value = '💊 Happy Pills All';
p.style.cssText = 'padding:4px 10px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:11px';
p.onclick = () => {
const pills = $$('option', m).filter(o => (o.textContent || '').includes('Happy Pill'));
if (pills.length > 0) {
pills[0].selected = true;
$$('input[value="Feed"]', m).forEach(b => b.click());
panel.innerHTML = body;
document.body.appendChild(panel);
// ── Feed All ──
panel.querySelector('#hv-feed-all').onclick = () => {
const m = document.getElementById('mainpane');
if (m) $$('input[value="Feed"]', m).forEach(b => b.click());
};
// ── Happy Pills All ──
panel.querySelector('#hv-pill-all').onclick = () => {
const m = document.getElementById('mainpane');
if (m) {
const pills = $$('option', m).filter(o => (o.textContent || '').includes('Happy Pill'));
if (pills.length > 0) {
pills[0].selected = true;
$$('input[value="Feed"]', m).forEach(b => b.click());
}
}
};
r.appendChild(f);
r.appendChild(p);
const ta = m.querySelector('div');
if (ta) ta.insertBefore(r, ta.firstChild);
// ── Toggle ──
panel.querySelector('#hv-monster-toggle').onclick = () => {
const body = panel.querySelector('#hv-monster-body');
const isHidden = body.style.display === 'none';
body.style.display = isHidden ? 'block' : 'none';
panel.querySelector('#hv-monster-toggle').textContent = isHidden ? '' : '+';
};
// ── Make draggable ──
const header = panel.querySelector('#hv-monster-header');
if (header) {
header.addEventListener('mousedown', (e) => {
_mlDragOffset.x = e.clientX - panel.getBoundingClientRect().left;
_mlDragOffset.y = e.clientY - panel.getBoundingClientRect().top;
const onMove = (ev) => {
panel.style.left = (ev.clientX - _mlDragOffset.x) + 'px';
panel.style.right = 'auto';
panel.style.top = (ev.clientY - _mlDragOffset.y) + 'px';
};
const onUp = () => {
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
};
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
});
}
// Remove the old inline bar if it exists
const oldBar = document.getElementById('hv-lab-enhance');
if (oldBar) oldBar.remove();
}
// ── Config button (bottom-right) ──
@ -2803,6 +2867,7 @@ function init() {
if (STATE.page === 'character') showGuidancePanel();
if (STATE.page === 'armory') enhanceArmory();
if (STATE.page === 'abilities') enhanceAbilities();
if (STATE.page === 'monster') enhanceMonsterLab();
}
// Dawn initialization

View file

@ -26,6 +26,7 @@ function init() {
if (STATE.page === 'character') showGuidancePanel();
if (STATE.page === 'armory') enhanceArmory();
if (STATE.page === 'abilities') enhanceAbilities();
if (STATE.page === 'monster') enhanceMonsterLab();
}
// Dawn initialization

View file

@ -228,38 +228,101 @@ function enhanceTraining() {
if (ta) ta.insertBefore(d, ta.firstChild);
}
// ── Monster Lab: feed all ──
// ── Monster Lab: floating info panel + feed buttons ──
let _mlDragOffset = { x: 0, y: 0 };
function enhanceMonsterLab() {
const m = document.getElementById('mainpane');
if (!m || document.getElementById('hv-lab-enhance')) return;
// Create floating draggable panel
if (document.getElementById('hv-monster')) return;
const r = document.createElement('div');
r.id = 'hv-lab-enhance';
r.style.cssText = 'margin:8px;padding:8px;display:flex;gap:8px';
const panel = document.createElement('div');
panel.id = 'hv-monster';
panel.style.cssText = css({
position: 'fixed',
top: '80px',
right: '4px',
zIndex: '9999',
background: '#111827',
color: '#d1d5db',
padding: '8px 10px',
borderRadius: '8px',
fontSize: '10px',
fontFamily: 'monospace',
maxWidth: '320px',
boxShadow: '0 0 15px rgba(0,0,0,0.6)',
border: '1px solid #374151',
cursor: 'move',
userSelect: 'none',
});
const f = document.createElement('input');
f.type = 'button';
f.value = '🍖 Feed All';
f.style.cssText = 'padding:4px 10px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:11px';
f.onclick = () => { $$('input[value="Feed"]', m).forEach(b => b.click()); };
const body = `<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;cursor:move" id="hv-monster-header">
<b style="color:#fdcb00;font-size:11px">🧬 Monster Lab</b>
<span id="hv-monster-toggle" style="color:#888;font-size:14px;cursor:pointer"></span>
</div>
<div id="hv-monster-body">
<div style="margin-bottom:6px;display:flex;gap:4px">
<input type="button" value="🍖 Feed All" style="padding:4px 10px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:11px" id="hv-feed-all">
<input type="button" value="💊 Happy Pills All" style="padding:4px 10px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:11px" id="hv-pill-all">
</div>
<div style="color:#9ca3af;font-size:9px;border-top:1px solid #374151;padding-top:4px">
New to ML? Pick a <b style="color:#fdcb00">Beast-class</b> (Dog/Cow/Pig) for STR/END crystals.<br>
<span style="color:#888">Click + drag header to move.</span>
</div>
</div>`;
const p = document.createElement('input');
p.type = 'button';
p.value = '💊 Happy Pills All';
p.style.cssText = 'padding:4px 10px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:11px';
p.onclick = () => {
const pills = $$('option', m).filter(o => (o.textContent || '').includes('Happy Pill'));
if (pills.length > 0) {
pills[0].selected = true;
$$('input[value="Feed"]', m).forEach(b => b.click());
panel.innerHTML = body;
document.body.appendChild(panel);
// ── Feed All ──
panel.querySelector('#hv-feed-all').onclick = () => {
const m = document.getElementById('mainpane');
if (m) $$('input[value="Feed"]', m).forEach(b => b.click());
};
// ── Happy Pills All ──
panel.querySelector('#hv-pill-all').onclick = () => {
const m = document.getElementById('mainpane');
if (m) {
const pills = $$('option', m).filter(o => (o.textContent || '').includes('Happy Pill'));
if (pills.length > 0) {
pills[0].selected = true;
$$('input[value="Feed"]', m).forEach(b => b.click());
}
}
};
r.appendChild(f);
r.appendChild(p);
const ta = m.querySelector('div');
if (ta) ta.insertBefore(r, ta.firstChild);
// ── Toggle ──
panel.querySelector('#hv-monster-toggle').onclick = () => {
const body = panel.querySelector('#hv-monster-body');
const isHidden = body.style.display === 'none';
body.style.display = isHidden ? 'block' : 'none';
panel.querySelector('#hv-monster-toggle').textContent = isHidden ? '' : '+';
};
// ── Make draggable ──
const header = panel.querySelector('#hv-monster-header');
if (header) {
header.addEventListener('mousedown', (e) => {
_mlDragOffset.x = e.clientX - panel.getBoundingClientRect().left;
_mlDragOffset.y = e.clientY - panel.getBoundingClientRect().top;
const onMove = (ev) => {
panel.style.left = (ev.clientX - _mlDragOffset.x) + 'px';
panel.style.right = 'auto';
panel.style.top = (ev.clientY - _mlDragOffset.y) + 'px';
};
const onUp = () => {
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
};
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
});
}
// Remove the old inline bar if it exists
const oldBar = document.getElementById('hv-lab-enhance');
if (oldBar) oldBar.remove();
}
// ── Config button (bottom-right) ──

View file

@ -33,6 +33,7 @@ function detectPage() {
'ss=rf': 'reforge',
'ss=sf': 'soulfuse',
'ss=ab': 'abilities',
'ss=ml': 'monster',
'ss=it': 'invitems',
'ss=se': 'settings',
'ss=ss': 'spiritshop',