diff --git a/game.js b/game.js index 94d1af7..cfb1eb8 100644 --- a/game.js +++ b/game.js @@ -1433,6 +1433,7 @@ function render() { renderStats(); updateEducation(); renderAlignment(); + checkUnlocks(); } function renderAlignment() { @@ -1456,6 +1457,63 @@ function renderAlignment() { } } +// === UNLOCK NOTIFICATIONS === +function showUnlockToast(type, name) { + const container = document.getElementById('unlock-toast'); + if (!container) return; + + const el = document.createElement('div'); + el.className = `unlock-toast-item ${type}`; + + const icon = type === 'building' ? 'BUILDING' : type === 'project' ? 'RESEARCH' : 'MILESTONE'; + el.innerHTML = `${icon}: ${name}`; + + container.appendChild(el); + // Trigger reflow, then show + void el.offsetHeight; + el.classList.add('show'); + + // Auto-remove after 4 seconds + setTimeout(() => { + el.classList.remove('show'); + setTimeout(() => { if (el.parentNode) el.parentNode.removeChild(el); }, 400); + }, 4000); +} + +// Track what the player has already seen (so we don't re-notify) +function ensureSeenSets() { + if (!G._seenBuildings) G._seenBuildings = []; + if (!G._seenProjects) G._seenProjects = []; +} + +function checkUnlocks() { + ensureSeenSets(); + + // Check for newly visible buildings + for (const def of BDEF) { + if (!def.unlock()) continue; + if (def.phase > G.phase + 1) continue; + if (G._seenBuildings.includes(def.id)) continue; + G._seenBuildings.push(def.id); + // Don't notify on the very first building (autocoder) — player just started + if (G.totalCode > 10) { + showUnlockToast('building', def.name); + } + } + + // Check for newly available projects + if (G.activeProjects) { + for (const id of G.activeProjects) { + if (G._seenProjects.includes(id)) continue; + G._seenProjects.push(id); + const pDef = PDEFS.find(p => p.id === id); + if (pDef) { + showUnlockToast('project', pDef.name); + } + } + } +} + // === SAVE / LOAD === function showSaveToast() { const el = document.getElementById('save-toast'); @@ -1489,6 +1547,8 @@ function saveGame() { milestones: G.milestones, completedProjects: G.completedProjects, activeProjects: G.activeProjects, totalClicks: G.totalClicks, startedAt: G.startedAt, flags: G.flags, + _seenBuildings: G._seenBuildings || [], + _seenProjects: G._seenProjects || [], rescues: G.rescues || 0, totalRescues: G.totalRescues || 0, drift: G.drift || 0, driftEnding: G.driftEnding || false, beaconEnding: G.beaconEnding || false, pendingAlignment: G.pendingAlignment || false, lastEventAt: G.lastEventAt || 0, diff --git a/index.html b/index.html index 6f6a2e8..db7995f 100644 --- a/index.html +++ b/index.html @@ -59,6 +59,13 @@ body{background:var(--bg);color:var(--text);font-family:'SF Mono','Cascadia Code #drift-ending button{margin-top:20px;background:#1a0808;border:1px solid #f44336;color:#f44336;padding:10px 24px;border-radius:4px;cursor:pointer;font-family:inherit;font-size:11px} #drift-ending button:hover{background:#2a1010} ::-webkit-scrollbar{width:4px}::-webkit-scrollbar-track{background:var(--bg)}::-webkit-scrollbar-thumb{background:var(--border);border-radius:2px} +#save-toast{display:none;position:fixed;top:16px;right:16px;background:#0e1420;border:1px solid #2a3a4a;color:#4a9eff;font-size:10px;padding:6px 12px;border-radius:4px;z-index:50;opacity:0;transition:opacity 0.4s;pointer-events:none} +#unlock-toast{position:fixed;top:56px;right:16px;z-index:50;display:flex;flex-direction:column;gap:6px;pointer-events:none} +.unlock-toast-item{background:#0e1420;border:1px solid #2a3a4a;font-size:10px;padding:6px 12px;border-radius:4px;opacity:0;transition:opacity 0.4s,transform 0.4s;transform:translateX(20px);pointer-events:auto;max-width:280px} +.unlock-toast-item.show{opacity:1;transform:translateX(0)} +.unlock-toast-item.building{border-color:#4a9eff;color:#4a9eff} +.unlock-toast-item.project{border-color:#ffd700;color:#ffd700} +.unlock-toast-item.milestone{border-color:#4caf50;color:#4caf50}
@@ -128,7 +135,8 @@ Drift: 0You became very good at what you do.