using Godot;
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();
}
#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
}