Defines FoodDef, a plain data holder for different food types in the game. It declares properties for display names, costs, boost values, visuals, and several predefined static FoodDef instances collected in a Catalog with helper find methods.
namespace NoChillquarium;
/// <summary>
/// Escalating food ladder. Nothing free — buy Fish Flakes first, then weirder food.
/// </summary>
public sealed class FoodDef
{
public string Id { get; init; }
public string Name { get; init; }
/// <summary>Optional short HUD label (inventory). Falls back to <see cref="Name"/>.</summary>
public string InvName { get; init; }
public string Note { get; init; }
/// <summary>Name for inventory / compact UI.</summary>
public string DisplayInv => string.IsNullOrWhiteSpace( InvName ) ? Name : InvName;
public double UnlockCost { get; init; }
public float BoostDuration { get; init; }
public float BoostMultiplier { get; init; }
public float ChaosOnFeed { get; init; }
public int PelletCount { get; init; }
public string PelletColor { get; init; }
public float BobMulWhileBoost { get; init; }
public float SpeedMulWhileBoost { get; init; }
/// <summary>Playtime seconds required before unlock is available (0 = start).</summary>
public float UnlockPlaytime { get; init; }
/// <summary>Optional inventory / shop icon sprite id (falls back to inv_food).</summary>
public string SpriteId { get; init; }
/// <summary>Optional tank pellet sprite id (falls back to colored circle).</summary>
public string PelletSpriteId { get; init; }
/// <summary>Inventory icon — custom art or generic food bag.</summary>
public string InvSpriteId =>
!string.IsNullOrWhiteSpace( SpriteId ) && SpriteCatalog.Has( SpriteId )
? SpriteId
: "inv_food";
public bool HasPelletSprite =>
!string.IsNullOrWhiteSpace( PelletSpriteId ) && SpriteCatalog.Has( PelletSpriteId );
public static readonly FoodDef Flakes = new()
{
Id = "flakes",
Name = "Fish Flakes",
InvName = "Fish Flakes",
Note = "grow + boost",
UnlockCost = 6,
BoostDuration = 12f,
BoostMultiplier = 1.65f,
ChaosOnFeed = 0f,
PelletCount = 6,
PelletColor = "#e8c060",
BobMulWhileBoost = 1f,
SpeedMulWhileBoost = 1f,
UnlockPlaytime = 0f
};
public static readonly FoodDef Pellets = new()
{
Id = "pellets",
Name = "Pellets",
Note = "crunch · grow",
UnlockCost = 20,
BoostDuration = 12f,
BoostMultiplier = 1.9f,
ChaosOnFeed = 0f,
PelletCount = 7,
PelletColor = "#d09040",
BobMulWhileBoost = 1.05f,
SpeedMulWhileBoost = 1.05f,
UnlockPlaytime = 90f // ~1.5 min
};
public static readonly FoodDef Bloodworms = new()
{
Id = "bloodworms",
Name = "Bloodworms",
Note = "grow fast",
UnlockCost = 35,
BoostDuration = 13f,
BoostMultiplier = 2.15f,
ChaosOnFeed = 0.2f,
PelletCount = 8,
PelletColor = "#a02030",
BobMulWhileBoost = 1.08f,
SpeedMulWhileBoost = 1.08f,
UnlockPlaytime = 4f * 60f, // ~4 min
SpriteId = "inv_bloodworms",
PelletSpriteId = "pellet_bloodworm"
};
public static readonly FoodDef FreezeDried = new()
{
Id = "freeze_dried",
Name = "Freeze-Dried",
Note = "fancy grow",
UnlockCost = 60,
BoostDuration = 10f,
BoostMultiplier = 2.0f,
ChaosOnFeed = 0.5f,
PelletCount = 7,
PelletColor = "#c07050",
BobMulWhileBoost = 1.1f,
SpeedMulWhileBoost = 1.1f,
UnlockPlaytime = 14f * 60f
};
public static readonly FoodDef BrineShrimp = new()
{
Id = "brine_shrimp",
Name = "Brine Shrimp",
Note = "salt snack",
UnlockCost = 85,
BoostDuration = 11f,
BoostMultiplier = 2.15f,
ChaosOnFeed = 0.8f,
PelletCount = 8,
PelletColor = "#e07050",
BobMulWhileBoost = 1.12f,
SpeedMulWhileBoost = 1.12f,
UnlockPlaytime = 20f * 60f
};
public static readonly FoodDef FriedChicken = new()
{
Id = "fried_chicken",
Name = "Fried Chicken",
Note = "greasy",
UnlockCost = 120,
BoostDuration = 11f,
BoostMultiplier = 2.3f,
ChaosOnFeed = 2f,
PelletCount = 5,
PelletColor = "#e8a040",
BobMulWhileBoost = 0.85f,
SpeedMulWhileBoost = 0.9f,
UnlockPlaytime = 30f * 60f
};
public static readonly FoodDef HotCheetos = new()
{
Id = "hot_cheetos",
Name = "Hot Cheetos",
Note = "flamin'",
UnlockCost = 150,
BoostDuration = 12f,
BoostMultiplier = 2.4f,
ChaosOnFeed = 3f,
PelletCount = 6,
PelletColor = "#e03020",
BobMulWhileBoost = 1.15f,
SpeedMulWhileBoost = 1.2f,
UnlockPlaytime = 40f * 60f
};
public static readonly FoodDef WeedGummies = new()
{
Id = "weed_gummies",
Name = "Weed Gummies",
InvName = "Gummies",
Note = "trippy",
UnlockCost = 180,
BoostDuration = 14f,
BoostMultiplier = 2.2f,
ChaosOnFeed = 4f,
PelletCount = 6,
PelletColor = "#50d060",
BobMulWhileBoost = 0.5f,
SpeedMulWhileBoost = 0.55f,
UnlockPlaytime = 80f * 60f // ~1h20
};
public static readonly FoodDef OtherFish = new()
{
Id = "other_fish",
Name = "Other Fish",
Note = "cannibal",
UnlockCost = 280,
BoostDuration = 12f,
BoostMultiplier = 2.7f,
ChaosOnFeed = 6f,
PelletCount = 4,
PelletColor = "#e06070",
BobMulWhileBoost = 1.2f,
SpeedMulWhileBoost = 1.15f,
UnlockPlaytime = 2f * 3600f // ~2h
};
public static readonly FoodDef Hand = new()
{
Id = "hand",
Name = "Dismembered Hand",
Note = "hand",
UnlockCost = 450,
BoostDuration = 13f,
BoostMultiplier = 3.1f,
ChaosOnFeed = 10f,
PelletCount = 3,
PelletColor = "#d08070",
BobMulWhileBoost = 1.3f,
SpeedMulWhileBoost = 1.2f,
UnlockPlaytime = 2.75f * 3600f // ~2h45
};
public static readonly FoodDef HomelessMan = new()
{
Id = "homeless_man",
Name = "Homeless Man",
Note = "unhinged",
UnlockCost = 700,
BoostDuration = 15f,
BoostMultiplier = 3.5f,
ChaosOnFeed = 15f,
PelletCount = 4,
PelletColor = "#a09080",
BobMulWhileBoost = 1.4f,
SpeedMulWhileBoost = 1.25f,
UnlockPlaytime = 3.5f * 3600f // ~3h30
};
public static IReadOnlyList<FoodDef> Catalog { get; } = new[]
{
Flakes,
Pellets,
Bloodworms,
FreezeDried,
BrineShrimp,
FriedChicken,
HotCheetos,
WeedGummies,
OtherFish,
Hand,
HomelessMan
};
public static FoodDef Find( string id ) =>
Catalog.FirstOrDefault( f => f.Id == id ) ?? Flakes;
/// <summary>Lookup without flakes fallback (null if unknown / empty).</summary>
public static FoodDef FindExact( string id ) =>
string.IsNullOrWhiteSpace( id ) ? null : Catalog.FirstOrDefault( f => f.Id == id );
}