Static progression gating helpers for the game UI. Exposes boolean properties that indicate whether systems (Train, Combine, Fight, DecorShop, Shady, Adventure) are unlocked, provides short hint strings for locked UI and a helper to compute the cheapest unlocked fight entry fee.
namespace NoChillquarium;
/// <summary>
/// Soft menu unlock ladder — learn one tool, earn the next.
/// Mirrors fusion's "food + feed" gate: hide advanced UI until the prior skill is practiced.
/// </summary>
public static class Progression
{
// ---- Soft unlocks (UI + systems) ----
/// <summary>Gym after the player has bought food and fed once.</summary>
public static bool TrainUnlocked => StorySystem.HasFedOnce;
/// <summary>Same care gate as fusion — aboms after feed.</summary>
public static bool CombineUnlocked =>
FeedSystem.HasAnyFood && StorySystem.HasFedOnce;
/// <summary>
/// Fight appears when you can pay entry <b>and</b> you've trained once
/// (teach gym before circuits).
/// </summary>
public static bool FightUnlocked =>
StorySystem.HasTrainedOnce && BattleSystem.CanAffordAnyFight();
/// <summary>Decor shop after early care + a couple fish (not day-one clutter).</summary>
public static bool DecorShopUnlocked =>
StorySystem.HasFedOnce && TankSim.TotalFishCount >= 2;
/// <summary>Shady / M80 after you've combined or fought — midgame chaos tools.</summary>
public static bool ShadyUnlocked =>
StorySystem.HasCombinedOnce
|| BattleSystem.Wins + BattleSystem.Losses > 0
|| StorySystem.HasBoomOnce;
/// <summary>Adventure Mode after fusion + fight intros (last ladder gift).</summary>
public static bool AdventureUnlocked => LotRunSystem.Unlocked;
// ---- Player-facing lock hints (short, funny) ----
public static string TrainHint =>
TrainUnlocked ? "" : "Feed once first";
public static string FightHint
{
get
{
if ( FightUnlocked )
return "";
if ( !StorySystem.HasTrainedOnce )
return "Train once first";
var fee = CheapestOpenEntryFee();
if ( fee > 0 && Economy.Balance + 0.001 < fee )
return $"Need Ð{Economy.FormatDoge( fee )} entry";
if ( !BattleSystem.CanAffordAnyFight() )
return "Earn entry Ð first";
return "Not yet";
}
}
/// <summary>Entry fee of the cheapest unlocked circuit, or 0 if none open yet.</summary>
public static double CheapestOpenEntryFee()
{
double best = 0;
foreach ( var t in BattleSystem.Catalog )
{
if ( t is null || !BattleSystem.IsUnlocked( t ) )
continue;
if ( best <= 0 || t.EntryFee < best )
best = t.EntryFee;
}
return best;
}
public static string DecorHint =>
DecorShopUnlocked
? ""
: !StorySystem.HasFedOnce
? "Feed once first"
: "Need 2+ fish";
public static string ShadyHint =>
ShadyUnlocked
? ""
: "Combine or fight first";
public static string AdventureHint =>
AdventureUnlocked ? "" : LotRunSystem.UnlockHint;
/// <summary>One-line ladder for banners / menus.</summary>
public static string LadderHint =>
"Care → Combine → Fight → Adventure";
}