// Game dashboard: load character profile and populate stats. let energyInterval = null; async function loadCharacter() { try { const data = await api.get('/character'); if (!data) { // No character yet — redirect to create-hero window.location.href = '/create-hero.html'; return; } const { character, derived, energy } = data; // Show stats, hide loading document.getElementById('hero-loading').style.display = 'none'; document.getElementById('hero-stats').style.display = 'block'; // Basic info document.getElementById('player-name').textContent = character.name; document.getElementById('char-name').textContent = character.name; document.getElementById('char-class').textContent = character.class.charAt(0).toUpperCase() + character.class.slice(1); document.getElementById('char-level').textContent = character.level; document.getElementById('char-hp').textContent = `${character.hp_current} / ${derived.maxHp}`; document.getElementById('char-energy').textContent = `${energy.current} / ${energy.max}`; document.getElementById('char-gold').textContent = character.gold; document.getElementById('char-xp').textContent = `${character.xp} / ${xpToNext(character.level)}`; document.getElementById('char-str').textContent = character.str; document.getElementById('char-agi').textContent = character.agi; document.getElementById('char-int').textContent = character.int; document.getElementById('char-vit').textContent = character.vit; document.getElementById('derived-atk').textContent = derived.attack; document.getElementById('derived-def').textContent = derived.defense; document.getElementById('derived-spd').textContent = derived.speed; document.getElementById('derived-crit').textContent = derived.critChance; // Update energy bar updateEnergyBar(energy.current, energy.max, energy.nextTickInSec); } catch (err) { // Not authenticated — redirect to login window.location.href = '/login.html'; } } function xpToNext(level) { return Math.floor(100 * Math.pow(level, 1.5)); } function updateEnergyBar(current, max, nextTickSec) { // Update text const energyEl = document.getElementById('char-energy'); if (energyEl) energyEl.textContent = `${current} / ${max}`; // Update bar fill const barEl = document.getElementById('energy-bar'); if (barEl) { const pct = Math.round((current / max) * 100); barEl.style.width = `${pct}%`; barEl.title = `${current}/${max} energy`; } // Update countdown const timerEl = document.getElementById('energy-timer'); if (timerEl) { if (current >= max) { timerEl.textContent = 'Energy full'; } else { const mins = Math.floor(nextTickSec / 60); const secs = nextTickSec % 60; timerEl.textContent = `Next +1 in ${mins}:${secs.toString().padStart(2, '0')}`; } } // Start countdown if (energyInterval) clearInterval(energyInterval); if (current < max && nextTickSec > 0) { energyInterval = setInterval(() => { nextTickSec--; if (nextTickSec <= 0) { clearInterval(energyInterval); loadCharacter(); return; } const mins = Math.floor(nextTickSec / 60); const secs = nextTickSec % 60; if (timerEl) timerEl.textContent = `Next +1 in ${mins}:${secs.toString().padStart(2, '0')}`; }, 1000); } } // Logout handler document.getElementById('logout-btn')?.addEventListener('click', async (e) => { e.preventDefault(); try { await api.post('/auth/logout', {}); } catch (_) {} window.location.href = '/login.html'; }); document.addEventListener('DOMContentLoaded', loadCharacter);