Data model for game save serialization. Defines SaveData with gameplay counters, inventory, tank state, legacy single-tank fields, and lists of FishSaveData and DecorSaveData used for JSON file persistence.
namespace NoChillquarium;
/// <summary>
/// Serializable snapshot for FileSystem.Data JSON save.
/// </summary>
public sealed class SaveData
{
public const int CurrentVersion = 5;
public const string FileName = "nochill_save.json";
public int Version { get; set; } = CurrentVersion;
public double Dogecoin { get; set; }
public double LifetimeEarned { get; set; }
public float PlaytimeSeconds { get; set; }
public float Chaos { get; set; }
public float Karma { get; set; } = 40f;
public bool HasWmd { get; set; }
public bool HasWhale { get; set; }
public string EndingReached { get; set; } = "";
public int MethBags { get; set; }
/// <summary>Bought M80 sticks in inventory (0 until purchased from Shady).</summary>
public int M80Bags { get; set; }
/// <summary>Visible glass cracks from failed meth-rush calms (0–5).</summary>
public int TankCracks { get; set; }
public List<string> Achievements { get; set; } = new();
public int LifetimeExplodes { get; set; }
public int TimesFed { get; set; }
public int TimesMeth { get; set; }
public int DecorPlaced { get; set; }
public List<string> UnlockedFoods { get; set; } = new();
/// <summary>Empty until the player buys their first food type.</summary>
public string SelectedFoodId { get; set; } = "";
public int Syringes { get; set; }
public int BattleWins { get; set; }
public int BattleLosses { get; set; }
public List<string> BattlesBeaten { get; set; } = new();
/// <summary>Habitat ids claimed as fight prizes (sewage duct, neighbor pool, …).</summary>
public List<string> PrizeHabitatsWon { get; set; } = new();
public int SharkKills { get; set; }
public int SharkEaten { get; set; }
public bool SharkEverSpawned { get; set; }
// Dual tanks (v2+)
public string FreshTankName { get; set; } = "Starter Fresh Tank";
public string SaltTankName { get; set; } = "Saltwater Tank";
public string FreshHabitatId { get; set; } = "tank_fresh_1";
public string SaltHabitatId { get; set; } = "tank_salt_1";
public int FreshCapacity { get; set; } = TankSim.DefaultCapacity;
public int SaltCapacity { get; set; } = TankSim.DefaultCapacity;
public bool SaltUnlocked { get; set; }
public string ActiveWater { get; set; } = "Fresh";
public List<FishSaveData> FreshFish { get; set; } = new();
public List<FishSaveData> SaltFish { get; set; } = new();
public List<DecorSaveData> FreshDecor { get; set; } = new();
public List<DecorSaveData> SaltDecor { get; set; } = new();
// Legacy single-tank fields (v1 continue support)
public string TankName { get; set; } = "Starter Fresh Tank";
public string Water { get; set; } = "Fresh";
public int Capacity { get; set; } = TankSim.DefaultCapacity;
public List<FishSaveData> Fish { get; set; } = new();
}
public sealed class DecorSaveData
{
public string DefId { get; set; }
public float X { get; set; }
public float Y { get; set; }
}
public sealed class FishSaveData
{
public string SpeciesId { get; set; }
/// <summary>Optional player nickname (null/empty = species name).</summary>
public string Nickname { get; set; }
public float X { get; set; }
public float Y { get; set; }
public float Vx { get; set; }
public float Vy { get; set; }
public bool OnMeth { get; set; }
public float MethTimer { get; set; }
public float SickTimer { get; set; }
public float Addiction { get; set; }
public float WithdrawalTimer { get; set; }
public float Endurance { get; set; } = 3f;
public float SpeedStat { get; set; } = 3f;
public float Agility { get; set; } = 3f;
public bool Jacked { get; set; }
public float JackedTimer { get; set; }
public float Fat { get; set; }
public bool Stoned { get; set; }
public float StonedTimer { get; set; }
/// <summary>Seconds left of post-fight injury lockout (0 = can fight).</summary>
public float FightInjuryTimer { get; set; }
}