loop: baseline
This commit is contained in:
+80
-42
@@ -1,6 +1,82 @@
|
||||
// Game dashboard: load character profile and populate stats.
|
||||
|
||||
let energyInterval = null;
|
||||
let energyData = null; // store latest server energy data for sync
|
||||
|
||||
/**
|
||||
* Refresh energy state from the server at a fixed interval.
|
||||
* Keeps client-side countdown in sync with the authoritative server.
|
||||
*/
|
||||
function startEnergySync() {
|
||||
if (energyInterval) clearInterval(energyInterval);
|
||||
// Sync every 60s (2/3 of a regen tick) to stay in sync with server
|
||||
energyInterval = setInterval(() => {
|
||||
loadCharacter();
|
||||
}, 60000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the energy bar and countdown display.
|
||||
* @param {number} current - current energy value
|
||||
* @param {number} max - max energy
|
||||
* @param {number} nextTickSec - seconds until next +1 energy tick (server-derived)
|
||||
*/
|
||||
function updateEnergyBar(current, max, nextTickSec) {
|
||||
energyData = { 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 a client-side countdown that decrements until the next energy tick.
|
||||
* When it reaches zero, refetch from server to get authoritative state.
|
||||
*/
|
||||
function startCountdown() {
|
||||
if (!energyData || energyData.current >= energyData.max || energyData.nextTickSec <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let remaining = energyData.nextTickSec;
|
||||
|
||||
if (energyInterval) clearInterval(energyInterval);
|
||||
energyInterval = setInterval(() => {
|
||||
remaining--;
|
||||
if (remaining <= 0) {
|
||||
clearInterval(energyInterval);
|
||||
energyInterval = null;
|
||||
loadCharacter();
|
||||
return;
|
||||
}
|
||||
const mins = Math.floor(remaining / 60);
|
||||
const secs = remaining % 60;
|
||||
const timerEl = document.getElementById('energy-timer');
|
||||
if (timerEl) {
|
||||
timerEl.textContent = `Next +1 in ${mins}:${secs.toString().padStart(2, '0')}`;
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
async function loadCharacter() {
|
||||
try {
|
||||
@@ -35,8 +111,9 @@ async function loadCharacter() {
|
||||
document.getElementById('derived-spd').textContent = derived.speed;
|
||||
document.getElementById('derived-crit').textContent = derived.critChance;
|
||||
|
||||
// Update energy bar
|
||||
// Update energy bar and start countdown
|
||||
updateEnergyBar(energy.current, energy.max, energy.nextTickInSec);
|
||||
startCountdown();
|
||||
} catch (err) {
|
||||
// Not authenticated — redirect to login
|
||||
window.location.href = '/login.html';
|
||||
@@ -47,47 +124,8 @@ 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);
|
||||
}
|
||||
}
|
||||
// Start periodic energy sync from server (every 60s)
|
||||
startEnergySync();
|
||||
|
||||
// Logout handler
|
||||
document.getElementById('logout-btn')?.addEventListener('click', async (e) => {
|
||||
|
||||
Reference in New Issue
Block a user