v0.13.3 - Auto-sell/salvage preset on settings page

- New settings-page.js: adds a toolbar above the auto-salvage table
  on Character Settings (ss=se) with bulk preset buttons
- Preset 1: Sell <=Fair (value 2) / Salvage <=Average (value 3)
- Preset 2: Sell <=Crude (value 1) / Salvage <=Fair (value 2)
- Disable All: reset both to No Auto-Sell/Salvage
- Shows current state summary (Sell X | Salvage Y)
- Also fixes init.js and build.sh to include new file
This commit is contained in:
GaboGG 2026-07-26 12:42:56 -04:00
parent 2f680a630d
commit badfcde640
5 changed files with 351 additions and 0 deletions

View file

@ -33,6 +33,7 @@ FILES=(
armory.js
battle-logger.js
re-timer.js
settings-page.js
public-api.js
init.js
)

View file

@ -2789,6 +2789,27 @@ function enhanceArmory() {
clear.onclick = clearAll;
toolbar.appendChild(clear);
// Select All / Invert Selection (useful on any screen)
const selAll = document.createElement('input');
selAll.type = 'button';
selAll.value = '☐ All';
selAll.style.cssText = 'padding:2px 6px;cursor:pointer;background:#3a4a6a;color:#fff;border:none;border-radius:3px;font-size:10px';
selAll.onclick = () => {
items.forEach(item => { item.checkbox.checked = true; });
if (typeof update_selected_count === 'function') update_selected_count();
};
toolbar.appendChild(selAll);
const invert = document.createElement('input');
invert.type = 'button';
invert.value = '⊞ Invert';
invert.style.cssText = 'padding:2px 6px;cursor:pointer;background:#444;color:#fff;border:none;border-radius:3px;font-size:10px';
invert.onclick = () => {
items.forEach(item => { item.checkbox.checked = !item.checkbox.checked; });
if (typeof update_selected_count === 'function') update_selected_count();
};
toolbar.appendChild(invert);
// ── Insert into page ──
const eqSelect = document.getElementById('equipselect_outer') ||
document.querySelector('#equipselect_left, #armory_right > div');
@ -2965,6 +2986,108 @@ function updateRETimer() {
}
}
// ── Settings page: auto-sell/salvage defaults ──
function enhanceSettings() {
if (document.getElementById('hv-settings-enh')) return;
const autoTable = document.getElementById('settings_autosalvage');
if (!autoTable) return;
// Check current state
const rows = [];
$$('tr', autoTable).forEach(tr => {
const sellSelect = tr.querySelector('select[name^="as_c_"]');
const salvSelect = tr.querySelector('select[name^="as_s_"]');
if (!sellSelect || !salvSelect) return;
const itemName = (tr.querySelector('td:first-child')?.textContent || '').trim();
rows.push({
name: itemName,
sell: sellSelect,
salv: salvSelect,
sellVal: parseInt(sellSelect.value),
salvVal: parseInt(salvSelect.value),
});
});
if (rows.length === 0) return;
// Build toolbar
const bar = document.createElement('div');
bar.id = 'hv-settings-enh';
bar.style.cssText = css({
margin: '8px 0',
padding: '6px 8px',
background: '#1a1a2e',
borderRadius: '4px',
fontSize: '10px',
fontFamily: 'monospace',
display: 'flex',
gap: '4px',
flexWrap: 'wrap',
alignItems: 'center',
border: '1px solid #374151',
});
const label = document.createElement('span');
label.style.cssText = 'color:#fdcb00;font-weight:bold;margin-right:6px';
label.textContent = '⚙ Auto-Sell/Salvage';
bar.appendChild(label);
// Preset: Sell Fair (2), Salvage Average (3)
const preset1 = document.createElement('input');
preset1.type = 'button';
preset1.value = '💰 Sell ≤Fair / ♻ Salvage ≤Average';
preset1.style.cssText = 'padding:3px 8px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:10px';
preset1.onclick = () => applyPreset(rows, 2, 3);
bar.appendChild(preset1);
// Preset: Sell Crude (1), Salvage Fair (2) — more conservative
const preset2 = document.createElement('input');
preset2.type = 'button';
preset2.value = '💰 Sell ≤Crude / ♻ Salvage ≤Fair';
preset2.style.cssText = 'padding:3px 8px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:10px';
preset2.onclick = () => applyPreset(rows, 1, 2);
bar.appendChild(preset2);
// Reset to No Auto-Sell/Salvage
const resetBtn = document.createElement('input');
resetBtn.type = 'button';
resetBtn.value = '✗ Disable All';
resetBtn.style.cssText = 'padding:3px 8px;cursor:pointer;background:#555;color:#fff;border:none;border-radius:3px;font-size:10px';
resetBtn.onclick = () => applyPreset(rows, 0, 0);
bar.appendChild(resetBtn);
// Summary of current state
const summary = document.createElement('span');
summary.style.cssText = 'color:#888;margin-left:6px';
const sellVals = rows.map(r => r.sellVal);
const salvVals = rows.map(r => r.salvVal);
const minSell = Math.min(...sellVals);
const minSalv = Math.min(...salvVals);
const maxSell = Math.max(...sellVals);
const maxSalv = Math.max(...salvVals);
const sellLabel = minSell === maxSell ? VAL_LABELS_SELL[minSell] : 'mixed';
const salvLabel = minSalv === maxSalv ? VAL_LABELS_SALV[minSalv] : 'mixed';
summary.textContent = `Current: Sell ${sellLabel} | Salvage ${salvLabel}`;
bar.appendChild(summary);
// Insert above the auto-salvage table
autoTable.parentNode.insertBefore(bar, autoTable);
function applyPreset(rows, sellVal, salvVal) {
rows.forEach(r => {
r.sell.value = sellVal;
r.salv.value = salvVal;
});
// Update summary
summary.textContent = `Current: Sell ${VAL_LABELS_SELL[sellVal]} | Salvage ${VAL_LABELS_SALV[salvVal]}`;
}
}
const VAL_LABELS_SELL = ['Off', 'Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary'];
const VAL_LABELS_SALV = ['Off', 'Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary'];
// ═══════════════════════════════════════════════════════════════════════
// PUBLIC API — window.HV for console power users
// ═══════════════════════════════════════════════════════════════════════
@ -3015,6 +3138,7 @@ function init() {
if (STATE.page === 'monsterlab') { enhanceMonsterLab(); autoCheckTask('feed'); }
if (STATE.page === 'arena') { autoCheckTask('arenas'); autoCheckTask('first-blood'); }
if (STATE.page === 'character') showGuidancePanel();
if (STATE.page === 'settings') enhanceSettings();
if (STATE.page === 'armory') enhanceArmory();
if (STATE.page === 'abilities') enhanceAbilities();
if (STATE.page === 'monster') enhanceMonsterLab();

View file

@ -2789,6 +2789,27 @@ function enhanceArmory() {
clear.onclick = clearAll;
toolbar.appendChild(clear);
// Select All / Invert Selection (useful on any screen)
const selAll = document.createElement('input');
selAll.type = 'button';
selAll.value = '☐ All';
selAll.style.cssText = 'padding:2px 6px;cursor:pointer;background:#3a4a6a;color:#fff;border:none;border-radius:3px;font-size:10px';
selAll.onclick = () => {
items.forEach(item => { item.checkbox.checked = true; });
if (typeof update_selected_count === 'function') update_selected_count();
};
toolbar.appendChild(selAll);
const invert = document.createElement('input');
invert.type = 'button';
invert.value = '⊞ Invert';
invert.style.cssText = 'padding:2px 6px;cursor:pointer;background:#444;color:#fff;border:none;border-radius:3px;font-size:10px';
invert.onclick = () => {
items.forEach(item => { item.checkbox.checked = !item.checkbox.checked; });
if (typeof update_selected_count === 'function') update_selected_count();
};
toolbar.appendChild(invert);
// ── Insert into page ──
const eqSelect = document.getElementById('equipselect_outer') ||
document.querySelector('#equipselect_left, #armory_right > div');
@ -2965,6 +2986,108 @@ function updateRETimer() {
}
}
// ── Settings page: auto-sell/salvage defaults ──
function enhanceSettings() {
if (document.getElementById('hv-settings-enh')) return;
const autoTable = document.getElementById('settings_autosalvage');
if (!autoTable) return;
// Check current state
const rows = [];
$$('tr', autoTable).forEach(tr => {
const sellSelect = tr.querySelector('select[name^="as_c_"]');
const salvSelect = tr.querySelector('select[name^="as_s_"]');
if (!sellSelect || !salvSelect) return;
const itemName = (tr.querySelector('td:first-child')?.textContent || '').trim();
rows.push({
name: itemName,
sell: sellSelect,
salv: salvSelect,
sellVal: parseInt(sellSelect.value),
salvVal: parseInt(salvSelect.value),
});
});
if (rows.length === 0) return;
// Build toolbar
const bar = document.createElement('div');
bar.id = 'hv-settings-enh';
bar.style.cssText = css({
margin: '8px 0',
padding: '6px 8px',
background: '#1a1a2e',
borderRadius: '4px',
fontSize: '10px',
fontFamily: 'monospace',
display: 'flex',
gap: '4px',
flexWrap: 'wrap',
alignItems: 'center',
border: '1px solid #374151',
});
const label = document.createElement('span');
label.style.cssText = 'color:#fdcb00;font-weight:bold;margin-right:6px';
label.textContent = '⚙ Auto-Sell/Salvage';
bar.appendChild(label);
// Preset: Sell Fair (2), Salvage Average (3)
const preset1 = document.createElement('input');
preset1.type = 'button';
preset1.value = '💰 Sell ≤Fair / ♻ Salvage ≤Average';
preset1.style.cssText = 'padding:3px 8px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:10px';
preset1.onclick = () => applyPreset(rows, 2, 3);
bar.appendChild(preset1);
// Preset: Sell Crude (1), Salvage Fair (2) — more conservative
const preset2 = document.createElement('input');
preset2.type = 'button';
preset2.value = '💰 Sell ≤Crude / ♻ Salvage ≤Fair';
preset2.style.cssText = 'padding:3px 8px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:10px';
preset2.onclick = () => applyPreset(rows, 1, 2);
bar.appendChild(preset2);
// Reset to No Auto-Sell/Salvage
const resetBtn = document.createElement('input');
resetBtn.type = 'button';
resetBtn.value = '✗ Disable All';
resetBtn.style.cssText = 'padding:3px 8px;cursor:pointer;background:#555;color:#fff;border:none;border-radius:3px;font-size:10px';
resetBtn.onclick = () => applyPreset(rows, 0, 0);
bar.appendChild(resetBtn);
// Summary of current state
const summary = document.createElement('span');
summary.style.cssText = 'color:#888;margin-left:6px';
const sellVals = rows.map(r => r.sellVal);
const salvVals = rows.map(r => r.salvVal);
const minSell = Math.min(...sellVals);
const minSalv = Math.min(...salvVals);
const maxSell = Math.max(...sellVals);
const maxSalv = Math.max(...salvVals);
const sellLabel = minSell === maxSell ? VAL_LABELS_SELL[minSell] : 'mixed';
const salvLabel = minSalv === maxSalv ? VAL_LABELS_SALV[minSalv] : 'mixed';
summary.textContent = `Current: Sell ${sellLabel} | Salvage ${salvLabel}`;
bar.appendChild(summary);
// Insert above the auto-salvage table
autoTable.parentNode.insertBefore(bar, autoTable);
function applyPreset(rows, sellVal, salvVal) {
rows.forEach(r => {
r.sell.value = sellVal;
r.salv.value = salvVal;
});
// Update summary
summary.textContent = `Current: Sell ${VAL_LABELS_SELL[sellVal]} | Salvage ${VAL_LABELS_SALV[salvVal]}`;
}
}
const VAL_LABELS_SELL = ['Off', 'Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary'];
const VAL_LABELS_SALV = ['Off', 'Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary'];
// ═══════════════════════════════════════════════════════════════════════
// PUBLIC API — window.HV for console power users
// ═══════════════════════════════════════════════════════════════════════
@ -3015,6 +3138,7 @@ function init() {
if (STATE.page === 'monsterlab') { enhanceMonsterLab(); autoCheckTask('feed'); }
if (STATE.page === 'arena') { autoCheckTask('arenas'); autoCheckTask('first-blood'); }
if (STATE.page === 'character') showGuidancePanel();
if (STATE.page === 'settings') enhanceSettings();
if (STATE.page === 'armory') enhanceArmory();
if (STATE.page === 'abilities') enhanceAbilities();
if (STATE.page === 'monster') enhanceMonsterLab();

View file

@ -24,6 +24,7 @@ function init() {
if (STATE.page === 'monsterlab') { enhanceMonsterLab(); autoCheckTask('feed'); }
if (STATE.page === 'arena') { autoCheckTask('arenas'); autoCheckTask('first-blood'); }
if (STATE.page === 'character') showGuidancePanel();
if (STATE.page === 'settings') enhanceSettings();
if (STATE.page === 'armory') enhanceArmory();
if (STATE.page === 'abilities') enhanceAbilities();
if (STATE.page === 'monster') enhanceMonsterLab();

101
src/settings-page.js Normal file
View file

@ -0,0 +1,101 @@
// ── Settings page: auto-sell/salvage defaults ──
function enhanceSettings() {
if (document.getElementById('hv-settings-enh')) return;
const autoTable = document.getElementById('settings_autosalvage');
if (!autoTable) return;
// Check current state
const rows = [];
$$('tr', autoTable).forEach(tr => {
const sellSelect = tr.querySelector('select[name^="as_c_"]');
const salvSelect = tr.querySelector('select[name^="as_s_"]');
if (!sellSelect || !salvSelect) return;
const itemName = (tr.querySelector('td:first-child')?.textContent || '').trim();
rows.push({
name: itemName,
sell: sellSelect,
salv: salvSelect,
sellVal: parseInt(sellSelect.value),
salvVal: parseInt(salvSelect.value),
});
});
if (rows.length === 0) return;
// Build toolbar
const bar = document.createElement('div');
bar.id = 'hv-settings-enh';
bar.style.cssText = css({
margin: '8px 0',
padding: '6px 8px',
background: '#1a1a2e',
borderRadius: '4px',
fontSize: '10px',
fontFamily: 'monospace',
display: 'flex',
gap: '4px',
flexWrap: 'wrap',
alignItems: 'center',
border: '1px solid #374151',
});
const label = document.createElement('span');
label.style.cssText = 'color:#fdcb00;font-weight:bold;margin-right:6px';
label.textContent = '⚙ Auto-Sell/Salvage';
bar.appendChild(label);
// Preset: Sell Fair (2), Salvage Average (3)
const preset1 = document.createElement('input');
preset1.type = 'button';
preset1.value = '💰 Sell ≤Fair / ♻ Salvage ≤Average';
preset1.style.cssText = 'padding:3px 8px;cursor:pointer;background:#2a5a2a;color:#fff;border:none;border-radius:3px;font-size:10px';
preset1.onclick = () => applyPreset(rows, 2, 3);
bar.appendChild(preset1);
// Preset: Sell Crude (1), Salvage Fair (2) — more conservative
const preset2 = document.createElement('input');
preset2.type = 'button';
preset2.value = '💰 Sell ≤Crude / ♻ Salvage ≤Fair';
preset2.style.cssText = 'padding:3px 8px;cursor:pointer;background:#5a3a2a;color:#fff;border:none;border-radius:3px;font-size:10px';
preset2.onclick = () => applyPreset(rows, 1, 2);
bar.appendChild(preset2);
// Reset to No Auto-Sell/Salvage
const resetBtn = document.createElement('input');
resetBtn.type = 'button';
resetBtn.value = '✗ Disable All';
resetBtn.style.cssText = 'padding:3px 8px;cursor:pointer;background:#555;color:#fff;border:none;border-radius:3px;font-size:10px';
resetBtn.onclick = () => applyPreset(rows, 0, 0);
bar.appendChild(resetBtn);
// Summary of current state
const summary = document.createElement('span');
summary.style.cssText = 'color:#888;margin-left:6px';
const sellVals = rows.map(r => r.sellVal);
const salvVals = rows.map(r => r.salvVal);
const minSell = Math.min(...sellVals);
const minSalv = Math.min(...salvVals);
const maxSell = Math.max(...sellVals);
const maxSalv = Math.max(...salvVals);
const sellLabel = minSell === maxSell ? VAL_LABELS_SELL[minSell] : 'mixed';
const salvLabel = minSalv === maxSalv ? VAL_LABELS_SALV[minSalv] : 'mixed';
summary.textContent = `Current: Sell ${sellLabel} | Salvage ${salvLabel}`;
bar.appendChild(summary);
// Insert above the auto-salvage table
autoTable.parentNode.insertBefore(bar, autoTable);
function applyPreset(rows, sellVal, salvVal) {
rows.forEach(r => {
r.sell.value = sellVal;
r.salv.value = salvVal;
});
// Update summary
summary.textContent = `Current: Sell ${VAL_LABELS_SELL[sellVal]} | Salvage ${VAL_LABELS_SALV[salvVal]}`;
}
}
const VAL_LABELS_SELL = ['Off', 'Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary'];
const VAL_LABELS_SALV = ['Off', 'Crude', 'Fair', 'Average', 'Superior', 'Exquisite', 'Magnificent', 'Legendary'];