feat: Add achievement tracking and persistence (#42)

This commit is contained in:
demenik
2025-12-11 17:26:19 +01:00
parent 1e7e4e7b95
commit 172f32a4d8
9 changed files with 139 additions and 4 deletions

View File

@@ -0,0 +1,65 @@
use crate::{features::phase::components::SessionTracker, prelude::*};
use std::collections::HashMap;
use strum_macros::EnumIter;
/// Represents an unlockable achievement.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, EnumIter)]
pub enum AchievementId {
// Berry achievements
FirstSteps,
MasterFarmer,
BerryTycoon,
// Focus achievements,
GettingStarted,
FocusMaster,
ZenMaster,
// Withered achievements
Negligent,
CompostKing,
}
impl AchievementId {
/// Label to be displayed ingame
pub fn label(&self) -> String {
match self {
AchievementId::FirstSteps => "Erste Schritte: Verdiene eine Beere.",
AchievementId::MasterFarmer => "Meisterbauer: Verdiene 100 Beeren.",
AchievementId::BerryTycoon => "Beeren-Tycoon: Verdiene 1.000 Beeren.",
AchievementId::GettingStarted => "Aller Anfang: Schließe deine erste Fokus-Phase ab.",
AchievementId::FocusMaster => "Fokus-Meister: Schließe 10 Fokus-Phasen ab.",
AchievementId::ZenMaster => "Zen-Meister: Schließe 50 Fokus-Phasen ab.",
AchievementId::Negligent => "Nachlässig: Lasse eine Pflanze verdorren.",
AchievementId::CompostKing => "Kompost-König: Lasse 10 Pflanzen verdorren.",
}
.into()
}
/// Checks if an achievement's conditions are met
pub fn conditions_met(&self, tracker: &SessionTracker) -> bool {
match self {
AchievementId::FirstSteps => tracker.total_berries_earned >= 1,
AchievementId::MasterFarmer => tracker.total_berries_earned >= 100,
AchievementId::BerryTycoon => tracker.total_berries_earned >= 1000,
AchievementId::GettingStarted => tracker.completed_focus_phases >= 1,
AchievementId::FocusMaster => tracker.completed_focus_phases >= 10,
AchievementId::ZenMaster => tracker.completed_focus_phases >= 50,
AchievementId::Negligent => tracker.total_plants_withered >= 1,
AchievementId::CompostKing => tracker.total_plants_withered >= 10,
}
}
}
#[derive(Resource, Default, Debug, Serialize, Deserialize, Clone)]
pub struct AchievementProgress {
pub unlocked: HashMap<AchievementId, bool>,
}
impl AchievementProgress {
pub fn is_unlocked(&self, id: &AchievementId) -> bool {
*self.unlocked.get(id).unwrap_or(&false)
}
pub fn unlock(&mut self, id: AchievementId) {
self.unlocked.insert(id, true);
}
}