102 lines
3.6 KiB
JavaScript
102 lines
3.6 KiB
JavaScript
// 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);
|