FishSpecies.cs

Defines a FishSpecies class and WaterType enum used as a static catalog of fish species for the game. It holds species properties (id, name, water type, colors, size, speed, income, cost, sprite path), exposes several predefined species, and provides read-only catalogs and lookup helpers.

File Access
namespace NoChillquarium;

public enum WaterType
{
	Fresh,
	Salt,
	Any
}

/// <summary>Static species catalog. Sprites resolve via <see cref="SpriteCatalog"/>.</summary>
public sealed class FishSpecies
{
	public string Id { get; init; }
	public string Name { get; init; }
	public WaterType Water { get; init; }
	public string Color { get; init; }
	public string FinColor { get; init; }
	public float Width { get; init; }
	public float Height { get; init; }
	public float Speed { get; init; }
	public float IncomePerSecond { get; init; }
	public double BuyCost { get; init; }

	/// <summary>Sprite id / filename stem (resolved via <see cref="SpriteCatalog"/>).</summary>
	public string SpritePath { get; init; }

	/// <summary>True when a Texture was built for this species.</summary>
	public bool HasSprite => SpriteCatalog.Has( Id );

	/// <summary>Sprite id for &lt;spritebox sprite="..."&gt;.</summary>
	public string SpriteId => Id;

	public static readonly FishSpecies Goldfish = new()
	{
		Id = "goldfish",
		Name = "Goldfish",
		Water = WaterType.Fresh,
		Color = "#f0a020",
		FinColor = "#ff6030",
		Width = 52f,
		Height = 36f,
		Speed = 70f,
		IncomePerSecond = 0.4f,
		BuyCost = 15,
		SpritePath = "goldfish"
	};

	public static readonly FishSpecies NeonTetra = new()
	{
		Id = "neon_tetra",
		Name = "Neon Tetra",
		Water = WaterType.Fresh,
		Color = "#2ec4b6",
		FinColor = "#e01e5a",
		Width = 40f,
		Height = 22f,
		Speed = 100f,
		IncomePerSecond = 0.25f,
		BuyCost = 22,
		SpritePath = "neon_tetra"
	};

	public static readonly FishSpecies Betta = new()
	{
		Id = "betta",
		Name = "Betta",
		Water = WaterType.Fresh,
		Color = "#7b2cbf",
		FinColor = "#ff6b6b",
		Width = 50f,
		Height = 40f,
		Speed = 55f,
		IncomePerSecond = 0.55f,
		BuyCost = 40,
		SpritePath = "betta"
	};

	public static readonly FishSpecies Clownfish = new()
	{
		Id = "clownfish",
		Name = "Clownfish",
		Water = WaterType.Salt,
		Color = "#ff8c1a",
		FinColor = "#ffffff",
		Width = 46f,
		Height = 30f,
		Speed = 75f,
		IncomePerSecond = 0.5f,
		BuyCost = 35,
		SpritePath = "clownfish"
	};

	public static readonly FishSpecies BlueTang = new()
	{
		Id = "blue_tang",
		Name = "Blue Tang",
		Water = WaterType.Salt,
		Color = "#2b6cff",
		FinColor = "#ffd24a",
		Width = 50f,
		Height = 32f,
		Speed = 85f,
		IncomePerSecond = 0.7f,
		BuyCost = 55,
		SpritePath = "blue_tang"
	};

	public static IReadOnlyList<FishSpecies> FreshCatalog { get; } = new[]
	{
		Goldfish,
		NeonTetra,
		Betta
	};

	public static IReadOnlyList<FishSpecies> SaltCatalog { get; } = new[]
	{
		Clownfish,
		BlueTang
	};

	public static IReadOnlyList<FishSpecies> AllCatalog { get; } = new[]
	{
		Goldfish,
		NeonTetra,
		Betta,
		Clownfish,
		BlueTang
	};

	/// <summary>Shop shows everything so players can make salinity "mistakes".</summary>
	public static IReadOnlyList<FishSpecies> ShopCatalog => AllCatalog;

	public const string SharkSpriteId = "cocaine_shark";
	public static bool SharkHasSprite => SpriteCatalog.Has( SharkSpriteId );

	public static FishSpecies Find( string id ) =>
		AllCatalog.FirstOrDefault( s => s.Id == id ) ?? Goldfish;
}