UI/gameplay helper that models a fictional "dark web" shop for in-game purchases. It tracks the current listing, vendor, step/status, exposes read-only properties for UI, validates gating conditions, and handles purchase flow by calling Shop, TrainingSystem, EndingSystem, Economy and audio/UI helpers.
namespace NoChillquarium;
/// <summary>Shady marketplace listing the player is "browsing" on the dark web shop.</summary>
public enum DarkListing
{
None,
Meth,
M80,
Syringe,
Wmd,
Whale
}
/// <summary>
/// Shady checkout — one-click buy for everyday items.
/// WMD / whale keep a single pay confirm (high stakes).
/// </summary>
public static class DarkWeb
{
static readonly Random _rng = new();
static int _version;
static DarkListing _listing = DarkListing.None;
static int _step; // 0 unused · 1 unused · 2 pay (danger items only)
static string _status = "";
static string _vendor = "";
public static int Version => _version;
public static bool CheckoutOpen => _listing != DarkListing.None;
public static DarkListing Listing => _listing;
public static int Step => _step;
public static string Status => _status;
public static string Vendor => _vendor;
public static int Hops => 0;
public static int Stars => 0;
public static string SiteTitle => "Shop";
public static string SiteOnion => "";
public static string StepLabel => _step switch
{
2 => "PAY",
_ => "BUY"
};
public static string ItemName => _listing switch
{
DarkListing.Meth => "Meth bag",
DarkListing.M80 => "M80 stick",
DarkListing.Syringe => "Juice kit",
DarkListing.Wmd => "Suspicious crate",
DarkListing.Whale => "Blue whale",
_ => ""
};
public static string ItemNote => _listing switch
{
DarkListing.Meth => "Zoomies",
DarkListing.M80 => "Tape · boom",
DarkListing.Syringe => "Inject from tools",
DarkListing.Wmd => "No-chill key",
DarkListing.Whale => "No-chill key",
_ => ""
};
public static double ItemPrice => _listing switch
{
DarkListing.Meth => Shop.MethCost,
DarkListing.M80 => Shop.M80Cost,
DarkListing.Syringe => TrainingSystem.SyringeCost,
DarkListing.Wmd => EndingSystem.WmdCost,
DarkListing.Whale => EndingSystem.WhaleCost,
_ => 0
};
public static string PriceLabel =>
"Ð" + Economy.FormatDoge( ItemPrice );
public static string PayButtonLabel =>
"Pay " + PriceLabel;
public static bool CanAfford =>
Economy.Balance >= ItemPrice - 0.001;
public static string StarsText => "";
public static void Clear()
{
_listing = DarkListing.None;
_step = 0;
_status = "";
_vendor = "";
_version++;
}
public static void Tick( float dt )
{
// No multi-hop theater — buys are instant or one pay click.
_ = dt;
}
/// <summary>
/// Everyday shady goods buy on the spot (one click from the shop row).
/// WMD / whale open a single pay step.
/// </summary>
public static bool TryBegin( DarkListing listing )
{
if ( listing == DarkListing.None || !TankSim.IsActive )
return false;
// Soft gates before opening the theater
if ( listing == DarkListing.Syringe && !TrainingSystem.SteroidsUnlocked )
{
TankSim.ShowBanner( $"Juice {TrainingSystem.SteroidUnlockText.ToLower()}." );
GameAudio.PlayUi( GameAudio.Error );
return false;
}
if ( listing == DarkListing.Wmd && EndingSystem.HasWmd )
{
TankSim.ShowBanner( "You already bought the crate." );
GameAudio.PlayUi( GameAudio.Error );
return false;
}
if ( listing == DarkListing.Wmd && Economy.PlaytimeSeconds < EndingSystem.WmdUnlockPlaytime )
{
TankSim.ShowBanner( $"Not available yet. {EndingSystem.WmdUnlockText}." );
GameAudio.PlayUi( GameAudio.Error );
return false;
}
if ( listing == DarkListing.Whale && EndingSystem.HasWhale )
{
TankSim.ShowBanner( "Whale already on the books." );
GameAudio.PlayUi( GameAudio.Error );
return false;
}
if ( listing == DarkListing.Whale && Economy.PlaytimeSeconds < EndingSystem.WhaleUnlockPlaytime )
{
TankSim.ShowBanner( $"Whale listing sealed. {EndingSystem.WhaleUnlockText}." );
GameAudio.PlayUi( GameAudio.Error );
return false;
}
// Instant buy for routine shady stock.
if ( listing is DarkListing.Meth or DarkListing.M80 or DarkListing.Syringe )
{
_listing = listing;
_step = 2;
_vendor = PickVendor( listing );
var ok = ConfirmPay();
return ok;
}
// Danger items: one pay click only.
_listing = listing;
_step = 2;
_vendor = PickVendor( listing );
_status = "Ready to pay.";
GameAudio.PlayUi( GameAudio.Tape );
_version++;
return true;
}
public static void ContinueFromVendor()
{
// Legacy hook — jump to pay.
if ( _listing == DarkListing.None )
return;
_step = 2;
_status = "Ready to pay.";
GameAudio.PlayUi( GameAudio.Pop );
_version++;
}
public static void Cancel()
{
if ( _listing == DarkListing.None )
return;
Clear();
Shop.SetLastMessage( "Cancelled." );
GameAudio.PlayUi( GameAudio.Close );
_version++;
}
/// <summary>Final pay step — spends Ð and grants the listing.</summary>
public static bool ConfirmPay()
{
if ( _listing == DarkListing.None || _step != 2 )
return false;
var kind = _listing;
bool ok;
switch ( kind )
{
case DarkListing.Meth:
ok = Shop.TryBuyMeth();
break;
case DarkListing.M80:
ok = Shop.TryBuyM80();
break;
case DarkListing.Syringe:
ok = TrainingSystem.TryBuySyringe();
break;
case DarkListing.Wmd:
ok = EndingSystem.TryBuyWmd();
break;
case DarkListing.Whale:
ok = EndingSystem.TryBuyWhale();
break;
default:
ok = false;
break;
}
if ( !ok )
{
_status = "Not enough Ð.";
GameAudio.PlayUi( GameAudio.Error );
// Instant path already closed listing on success only — keep open for danger pay retry.
if ( kind is DarkListing.Meth or DarkListing.M80 or DarkListing.Syringe )
Clear();
_version++;
return false;
}
var drop = kind switch
{
DarkListing.Meth => "Meth bag bought.",
DarkListing.M80 => "M80 bought.",
DarkListing.Syringe => "Juice kit bought.",
DarkListing.Wmd => "Crate bought.",
DarkListing.Whale => "Blue whale bought. Grandma: \"Fancy. Don't put it in the bath.\"",
_ => "Bought."
};
Shop.SetLastMessage( drop );
TankSim.ShowBanner( drop );
GameAudio.PlayUi( GameAudio.Confirm );
Clear();
return true;
}
static string PickVendor( DarkListing listing ) => listing switch
{
DarkListing.Meth => "lot_chemist",
DarkListing.M80 => "unit_4b_garage",
DarkListing.Syringe => "bingo_nurse",
DarkListing.Wmd => "no_reply",
DarkListing.Whale => "aquarium_fence",
_ => "unknown"
};
}