diff --git a/game.js b/game.js index 8659032..7aee315 100644 --- a/game.js +++ b/game.js @@ -2137,6 +2137,118 @@ function renderProductionBreakdown() { container.innerHTML = html; } +// === FLEET STATUS PANEL === +function renderFleetStatus() { + const container = document.getElementById('fleet-status'); + if (!container) return; + + // Only show once player has at least one wizard building + const wizardDefs = BDEF.filter(b => + ['bezalel','allegro','ezra','timmy','fenrir','bilbo'].includes(b.id) + ); + const owned = wizardDefs.filter(d => (G.buildings[d.id] || 0) > 0); + if (owned.length === 0) { + container.style.display = 'none'; + return; + } + container.style.display = 'block'; + + const h = G.harmony; + const timmyEff = Math.max(20, Math.min(300, (h / 50) * 100)); + + let html = '

FLEET STATUS

'; + html += '
'; + + for (const def of owned) { + const count = G.buildings[def.id] || 0; + let status, color, detail; + + switch (def.id) { + case 'bezalel': + status = 'Active'; + color = '#4caf50'; + detail = `+${fmt(50 * count * G.codeBoost)} code/s, +${2 * count} ops/s`; + break; + case 'allegro': + if (G.trust < 5) { + status = 'IDLE'; + color = '#f44336'; + detail = 'Needs trust ≥5 to function'; + } else { + status = 'Active'; + color = '#4caf50'; + detail = `+${fmt(10 * count * G.knowledgeBoost)} knowledge/s`; + } + break; + case 'ezra': + const ezraDebuff = G.activeDebuffs && G.activeDebuffs.find(d => d.id === 'ezra_offline'); + if (ezraDebuff) { + status = 'OFFLINE'; + color = '#f44336'; + detail = 'Channel down — users -70%'; + } else { + status = 'Active'; + color = '#4caf50'; + detail = `+${fmt(25 * count * G.userBoost)} users/s, +${(0.5 * count).toFixed(1)} trust/s`; + } + break; + case 'timmy': + if (h < 20) { + status = 'STRESSED'; + color = '#f44336'; + detail = `Effectiveness: ${Math.floor(timmyEff)}% — harmony critical`; + } else if (h < 50) { + status = 'Reduced'; + color = '#ffaa00'; + detail = `Effectiveness: ${Math.floor(timmyEff)}% — harmony low`; + } else { + status = 'Healthy'; + color = '#4caf50'; + detail = `Effectiveness: ${Math.floor(timmyEff)}% — all production boosted`; + } + break; + case 'fenrir': + status = 'Watching'; + color = '#4a9eff'; + detail = `+${2 * count} trust/s, -${1 * count} ops/s (security cost)`; + break; + case 'bilbo': + const bilboDebuff = G.activeDebuffs && G.activeDebuffs.find(d => d.id === 'bilbo_vanished'); + if (bilboDebuff) { + status = 'VANISHED'; + color = '#f44336'; + detail = 'Creativity halted — spend trust to lure back'; + } else { + status = 'Present'; + color = Math.random() < 0.1 ? '#ffd700' : '#b388ff'; // occasional gold flash + detail = `+${count} creativity/s (10% burst chance, 5% vanish chance)`; + } + break; + } + + html += `
`; + html += `
`; + html += `${def.name.split(' — ')[0]}`; + html += `${status}`; + html += `
`; + html += `
${detail}
`; + if (count > 1) html += `
x${count}
`; + html += `
`; + } + + html += '
'; + + // Harmony summary bar + const harmonyColor = h > 60 ? '#4caf50' : h > 30 ? '#ffaa00' : '#f44336'; + html += `
`; + html += `Harmony`; + html += `
`; + html += `${Math.floor(h)}%`; + html += `
`; + + container.innerHTML = html; +} + function updateEducation() { const container = document.getElementById('education-text'); if (!container) return; @@ -2388,6 +2500,7 @@ function render() { renderSprint(); renderBulkOps(); renderPulse(); + renderFleetStatus(); } function renderAlignment() { diff --git a/index.html b/index.html index 8876f80..e5f3fe5 100644 --- a/index.html +++ b/index.html @@ -180,6 +180,7 @@ Drift: 0
Events Resolved: 0 +