using Godot; using System.Collections.Generic; using Mr.BrickAdventures.scripts.Resources; using Mr.BrickAdventures.scripts.State; namespace Mr.BrickAdventures.Autoloads; /// /// Central store for game state - single source of truth. /// Use the static Instance property for easy access. /// public partial class GameStateStore : Node { /// /// Singleton instance. /// public static GameStateStore Instance { get; private set; } /// /// Persistent player state (saved to disk). /// public PlayerState Player { get; set; } = new(); /// /// Current session state (transient, reset on death/level complete). /// public SessionState Session { get; set; } = new(); public override void _Ready() { Instance = this; } public override void _ExitTree() { if (Instance == this) Instance = null; } #region Coin Operations /// /// Gets total coins (saved + session). /// public int GetTotalCoins() => Player.Coins + Session.CoinsCollected; /// /// Adds coins to the session (not saved until level complete). /// public void AddSessionCoins(int amount) { Session.CoinsCollected += amount; EventBus.EmitCoinsChanged(GetTotalCoins()); } /// /// Commits session coins to player state. /// public void CommitSessionCoins() { Player.Coins += Session.CoinsCollected; Session.CoinsCollected = 0; } /// /// Removes coins, first from session then from saved. /// public void RemoveCoins(int amount) { if (amount <= Session.CoinsCollected) { Session.CoinsCollected -= amount; } else { var remaining = amount - Session.CoinsCollected; Session.CoinsCollected = 0; Player.Coins = Mathf.Max(0, Player.Coins - remaining); } EventBus.EmitCoinsChanged(GetTotalCoins()); } #endregion #region Lives Operations /// /// Decrements lives by 1. /// public void RemoveLife() { Player.Lives = Mathf.Max(0, Player.Lives - 1); EventBus.EmitLivesChanged(Player.Lives); } /// /// Adds lives. /// public void AddLives(int amount) { Player.Lives += amount; EventBus.EmitLivesChanged(Player.Lives); } #endregion #region Level Operations /// /// Unlocks a level for access. /// public void UnlockLevel(int levelIndex) { if (!Player.UnlockedLevels.Contains(levelIndex)) Player.UnlockedLevels.Add(levelIndex); } /// /// Marks a level as completed and unlocks the next. /// public void MarkLevelComplete(int levelIndex) { if (!Player.CompletedLevels.Contains(levelIndex)) Player.CompletedLevels.Add(levelIndex); UnlockLevel(levelIndex + 1); } /// /// Checks if a level is unlocked. /// public bool IsLevelUnlocked(int levelIndex) => Player.UnlockedLevels.Contains(levelIndex); #endregion #region Skill Operations /// /// Checks if a skill is unlocked (saved or session). /// public bool IsSkillUnlocked(SkillData skill) { return Player.UnlockedSkills.Contains(skill) || Session.SkillsUnlocked.Contains(skill); } /// /// Unlocks a skill in the session. /// public void UnlockSkillInSession(SkillData skill) { if (!IsSkillUnlocked(skill)) Session.SkillsUnlocked.Add(skill); } /// /// Commits session skills to player state. /// public void CommitSessionSkills() { foreach (var skill in Session.SkillsUnlocked) { if (!Player.UnlockedSkills.Contains(skill)) Player.UnlockedSkills.Add(skill); } Session.SkillsUnlocked.Clear(); } /// /// Gets all unlocked skills from player persistence and current session. /// public List GetAllUnlockedSkills() { var result = new List(Player.UnlockedSkills); foreach (var skill in Session.SkillsUnlocked) { if (!result.Contains(skill)) result.Add(skill); } return result; } #endregion #region Reset Operations /// /// Resets only the session state. /// public void ResetSession() => Session.Reset(); /// /// Resets everything to defaults. /// public void ResetAll() { Player.Reset(); Session.ResetAll(); } #endregion }