diff --git a/dev-journal.md b/dev-journal.md index fb11bc5..8b6f191 100644 --- a/dev-journal.md +++ b/dev-journal.md @@ -184,6 +184,36 @@ --- +### Session 9 - 2026-08-21 (Afternoon) +**Status:** ✅ Achievement Progress Tracking Added to Stats Panel + +#### What was done: +- Added "Next Achievement" section to the Statistics panel with a progress bar +- Implemented `calculateAchievementProgress()` method that computes progress toward every achievement type: + - Click achievements (firstClick, clicker, spammer, clickMaster) + - Stardust achievements (dustCollector, stardustMagnate, cosmicTycoon, galaxyBaron) + - Building count achievements (firstPlant, gardenStart, gardenCenter, cosmicGarden) + - Specific building achievements (sproutFarmer, bloomGarden, solarPowered, voidWeaver, supernovaGrowth) + - Production achievements (steadyStream, rushingRiver, cosmicFlood) + - Prestige achievements (firstPrestige, stellarAdaptation, cosmicAscension, eternalGardener, quantumGrowth) + - Click power achievements (powerfulHarvester, divineTouch) + - Time-based achievement (dedicatedGardener) +- `updateNextAchievement()` finds the closest unachieved milestone by progress percentage and displays it with a progress bar +- Progress bar updates every game tick via `Stats.update()` +- Shows "All achievements unlocked! 🎉" when all 30 achievements are complete + +#### Files modified: +- `js/stats.js` - Added "Next Achievement" stat item to render(), added updateNextAchievement() and calculateAchievementProgress() methods + +#### Next goals: +- Consider adding a "next essence at X stardust" progress hint in prestige tab (from Session 8 notes) +- Potential new building tiers or prestige milestones +- Sound variations or background music + +--- + +--- + ### Session 8 - 2026-08-21 (Afternoon) **Status:** ✅ Critical Bugfix - Prestige System Now Actually Loads (reported by user) diff --git a/js/stats.js b/js/stats.js index 8bcb340..95909f9 100644 --- a/js/stats.js +++ b/js/stats.js @@ -17,7 +17,7 @@ const Stats = { render() { const container = document.getElementById('stats-content'); if (!container) return; - + container.innerHTML = `
Total Stardust Earned
@@ -51,6 +51,13 @@ const Stats = {
Achievements Unlocked
0/${Object.keys(ACHIEVEMENTS).length}
+
+
Next Achievement
+
Loading...
+
+
+
+
Game Progress
@@ -120,6 +127,127 @@ const Stats = { const progress = this.calculateProgress(); progressBarEl.style.width = `${progress}%`; } + + // Next achievement tracking + this.updateNextAchievement(); + }, + + /** + * Update the next achievement display with progress bar + */ + updateNextAchievement() { + const nextEl = document.getElementById('stat-next-achievement'); + const progressEl = document.getElementById('stat-achievement-progress'); + if (!nextEl) return; + + // Find the closest unachieved milestone + let closest = null; + let closestProgress = -1; + + for (const [id, achievement] of Object.entries(ACHIEVEMENTS)) { + if (Game.state.achievements.includes(id)) continue; + + const result = this.calculateAchievementProgress(achievement); + if (result && result.progress > closestProgress) { + closestProgress = result.progress; + closest = { ...result, name: achievement.name, icon: achievement.icon }; + } + } + + if (closest) { + nextEl.textContent = `${closest.icon} ${closest.name}`; + if (progressEl) { + progressEl.style.width = `${Math.min(100, Math.max(0, closest.progress))}%`; + } + } else { + nextEl.textContent = 'All achievements unlocked! 🎉'; + if (progressEl) { + progressEl.style.width = '100%'; + } + } + }, + + /** + * Calculate progress toward a specific achievement + */ + calculateAchievementProgress(achievement) { + const state = Game.state; + + // Click achievements + if (achievement.id === 'firstClick') return { current: state.totalClicks, target: 1, progress: Math.min(100, (state.totalClicks / 1) * 100) }; + if (achievement.id === 'clicker') return { current: state.totalClicks, target: 100, progress: Math.min(100, (state.totalClicks / 100) * 100) }; + if (achievement.id === 'spammer') return { current: state.totalClicks, target: 1000, progress: Math.min(100, (state.totalClicks / 1000) * 100) }; + if (achievement.id === 'clickMaster') return { current: state.totalClicks, target: 10000, progress: Math.min(100, (state.totalClicks / 10000) * 100) }; + + // Stardust achievements + if (achievement.id === 'dustCollector') return { current: state.totalStardust, target: 1000, progress: Math.min(100, (state.totalStardust / 1000) * 100) }; + if (achievement.id === 'stardustMagnate') return { current: state.totalStardust, target: 100000, progress: Math.min(100, (state.totalStardust / 100000) * 100) }; + if (achievement.id === 'cosmicTycoon') return { current: state.totalStardust, target: 10000000, progress: Math.min(100, (state.totalStardust / 10000000) * 100) }; + if (achievement.id === 'galaxyBaron') return { current: state.totalStardust, target: 1000000000, progress: Math.min(100, (state.totalStardust / 1000000000) * 100) }; + + // Building achievements + if (achievement.id === 'firstPlant') { + const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0); + return { current: totalBuildings, target: 1, progress: Math.min(100, (totalBuildings / 1) * 100) }; + } + if (achievement.id === 'gardenStart') { + const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0); + return { current: totalBuildings, target: 10, progress: Math.min(100, (totalBuildings / 10) * 100) }; + } + if (achievement.id === 'gardenCenter') { + const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0); + return { current: totalBuildings, target: 50, progress: Math.min(100, (totalBuildings / 50) * 100) }; + } + if (achievement.id === 'cosmicGarden') { + const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0); + return { current: totalBuildings, target: 100, progress: Math.min(100, (totalBuildings / 100) * 100) }; + } + + // Specific building achievements + if (achievement.id === 'sproutFarmer') return { current: state.buildings.starSprout || 0, target: 25, progress: Math.min(100, ((state.buildings.starSprout || 0) / 25) * 100) }; + if (achievement.id === 'bloomGarden') return { current: state.buildings.moonBloom || 0, target: 25, progress: Math.min(100, ((state.buildings.moonBloom || 0) / 25) * 100) }; + if (achievement.id === 'solarPowered') return { current: state.buildings.solarLeaf || 0, target: 25, progress: Math.min(100, ((state.buildings.solarLeaf || 0) / 25) * 100) }; + if (achievement.id === 'voidWeaver') return { current: state.buildings.voidFern || 0, target: 25, progress: Math.min(100, ((state.buildings.voidFern || 0) / 25) * 100) }; + if (achievement.id === 'supernovaGrowth') return { current: state.buildings.supernovaSeed || 0, target: 25, progress: Math.min(100, ((state.buildings.supernovaSeed || 0) / 25) * 100) }; + + // Production achievements + if (achievement.id === 'steadyStream') { + const prod = Game.getProductionPerSecond(); + return { current: prod, target: 100, progress: Math.min(100, (prod / 100) * 100) }; + } + if (achievement.id === 'rushingRiver') { + const prod = Game.getProductionPerSecond(); + return { current: prod, target: 1000, progress: Math.min(100, (prod / 1000) * 100) }; + } + if (achievement.id === 'cosmicFlood') { + const prod = Game.getProductionPerSecond(); + return { current: prod, target: 100000, progress: Math.min(100, (prod / 100000) * 100) }; + } + + // Prestige achievements + if (achievement.id === 'firstPrestige') return { current: state.prestigeCount || 0, target: 1, progress: Math.min(100, ((state.prestigeCount || 0) / 1) * 100) }; + if (achievement.id === 'stellarAdaptation') return { current: state.prestigeCount || 0, target: 5, progress: Math.min(100, ((state.prestigeCount || 0) / 5) * 100) }; + if (achievement.id === 'cosmicAscension') return { current: state.prestigeCount || 0, target: 10, progress: Math.min(100, ((state.prestigeCount || 0) / 10) * 100) }; + if (achievement.id === 'eternalGardener') return { current: state.totalPrestigeEssence || 0, target: 100, progress: Math.min(100, ((state.totalPrestigeEssence || 0) / 100) * 100) }; + if (achievement.id === 'quantumGrowth') return { current: state.totalPrestigeEssence || 0, target: 1000, progress: Math.min(100, ((state.totalPrestigeEssence || 0) / 1000) * 100) }; + + // Click power achievements + if (achievement.id === 'powerfulHarvester') { + const cp = Game.getClickPower(); + return { current: cp, target: 1000, progress: Math.min(100, (cp / 1000) * 100) }; + } + if (achievement.id === 'divineTouch') { + const cp = Game.getClickPower(); + return { current: cp, target: 10000, progress: Math.min(100, (cp / 10000) * 100) }; + } + + // Time-based achievement + if (achievement.id === 'dedicatedGardener') { + const elapsed = Date.now() - state.startTime; + return { current: elapsed, target: 3600000, progress: Math.min(100, (elapsed / 3600000) * 100) }; + } + + return null; }, /**