AdvVignette.cs

Static utility that picks artwork and captions for the adventure vignette UI. It chooses left/right sprite ids and captions based on LotRunSystem phase, location, current room, and PipeCrawl state, and exposes properties like LeftId, RightId, LeftCaption, RightCaption, Visible and Version.

File Access
namespace NoChillquarium;

/// <summary>
/// Adventure gutter art — location plate on the left, event portrait on the
/// right. Swaps when you flush, meet someone, loot, or chomp a thing.
/// </summary>
public static class AdvVignette
{
	public static bool Visible => LotRunSystem.IsOpen;

	public static string LeftId
	{
		get
		{
			Resolve( out var left, out _, out _, out _ );
			return Pick( left );
		}
	}

	public static string RightId
	{
		get
		{
			Resolve( out _, out _, out var right, out _ );
			return Pick( right );
		}
	}

	public static string LeftCaption
	{
		get
		{
			Resolve( out _, out var cap, out _, out _ );
			return cap ?? "";
		}
	}

	public static string RightCaption
	{
		get
		{
			Resolve( out _, out _, out _, out var cap );
			return cap ?? "";
		}
	}

	public static bool HasLeft => SpriteCatalog.Has( LeftId );
	public static bool HasRight => SpriteCatalog.Has( RightId );

	public static int Version =>
		HashCode.Combine( LeftId, RightId, LeftCaption, RightCaption, LotRunSystem.Version, PipeCrawl.Version );

	static string Pick( string[] ids )
	{
		if ( ids is null )
			return "";
		foreach ( var id in ids )
		{
			if ( !string.IsNullOrEmpty( id ) && SpriteCatalog.Has( id ) )
				return id;
		}
		return "";
	}

	static void Resolve( out string[] left, out string leftCap, out string[] right, out string rightCap )
	{
		left = Array.Empty<string>();
		right = Array.Empty<string>();
		leftCap = "";
		rightCap = "";

		if ( !LotRunSystem.IsOpen )
			return;

		var phase = LotRunSystem.Phase;
		var loc = LotRunSystem.Location;
		var room = LotRunSystem.CurrentRoom;

		if ( phase == LotRunPhase.Flush )
		{
			left = new[] { "loc_bathroom", "adv_cg_flush" };
			leftCap = "Trailer bath";
			right = new[] { "adv_cg_flush" };
			rightCap = LotRunSystem.FlushFishName;
			return;
		}

		if ( phase == LotRunPhase.Faucet )
		{
			left = new[] { "loc_bathroom", "adv_cg_faucet" };
			leftCap = "Kitchen";
			right = new[] { "adv_cg_faucet" };
			rightCap = "Faucet home";
			return;
		}

		if ( phase == LotRunPhase.Map )
		{
			left = new[] { "loc_porch", "adv_cg_you" };
			leftCap = "The lot";
			right = new[] { "adv_cg_you", "ui_you" };
			rightCap = "Pick a hole";
			return;
		}

		if ( phase == LotRunPhase.Team )
		{
			left = LocIds( loc );
			leftCap = LocCaption( loc );
			right = new[] { "adv_cg_you", "ui_you" };
			rightCap = "Who goes";
			return;
		}

		if ( phase == LotRunPhase.Done )
		{
			left = LocIds( loc );
			leftCap = LocCaption( loc );
			if ( LotRunSystem.RunWon )
			{
				right = new[] { "adv_cg_loot", "adv_cg_you", "ui_you" };
				rightCap = "Cleared";
			}
			else
			{
				right = new[] { "adv_cg_faucet", "adv_cg_you" };
				rightCap = "Spit out";
			}
			return;
		}

		// Room / result / crawl
		left = LocIds( loc );
		leftCap = LocCaption( loc );

		if ( LotRunSystem.CrawlLive )
		{
			var focus = PipeCrawl.FocusThing;
			if ( focus is not null )
			{
				right = ThingIds( focus );
				rightCap = string.IsNullOrEmpty( focus.Name ) ? ThingCaption( focus ) : focus.Name;
				return;
			}
			if ( PipeCrawl.BossWave )
			{
				right = new[] { "adv_cg_boss" };
				rightCap = "In the way";
				return;
			}
		}

		if ( room is not null )
		{
			PersonArt( room, loc, out right, out rightCap );
			if ( right.Length > 0 )
				return;

			right = room.Kind switch
			{
				LotRoomKind.Loot => new[] { "adv_cg_loot", "adv_coin" },
				LotRoomKind.Hazard => new[] { "adv_cg_hazard", "adv_grate" },
				LotRoomKind.Boss => new[] { "adv_cg_boss", "adv_carp" },
				LotRoomKind.Fight => new[] { "adv_cg_mite", "adv_mite" },
				LotRoomKind.Choice => new[] { "adv_cg_you", "ui_you" },
				_ => FlavorRight( loc )
			};
			rightCap = room.Kind switch
			{
				LotRoomKind.Loot => "Take it",
				LotRoomKind.Hazard => "Watch it",
				LotRoomKind.Boss => room.Title,
				LotRoomKind.Fight => room.Title,
				LotRoomKind.Choice => "Split",
				_ => room.Title
			};
			return;
		}

		right = FlavorRight( loc );
		rightCap = LocCaption( loc );
	}

	static void PersonArt( LotRoomDef room, LotLocationDef loc, out string[] right, out string cap )
	{
		right = Array.Empty<string>();
		cap = "";
		var blob = ((room.Title ?? "") + " " + (room.Body ?? "") + " " + (loc?.Id ?? "")).ToLowerInvariant();

		if ( blob.Contains( "janitor" ) || blob.Contains( "not my dumpster" ) || blob.Contains( "pump row" ) )
		{
			right = new[] { "adv_cg_janitor", "ui_janitor" };
			cap = "Janitor";
			return;
		}
		if ( loc?.Id == "bingo_hall" && room.Kind is LotRoomKind.Look or LotRoomKind.Loot )
		{
			right = new[] { "adv_cg_grandma", "ui_grandma" };
			cap = "Bingo night";
			return;
		}
		if ( blob.Contains( "4b" ) || blob.Contains( "cousin" ) || blob.Contains( "brad" ) )
		{
			right = new[] { "adv_cg_brad", "ui_bully" };
			cap = "4B cousin";
			return;
		}
		if ( blob.Contains( "principal" ) || blob.Contains( "nameplate" ) || blob.Contains( "desk tank" ) )
		{
			right = new[] { "adv_cg_principal" };
			cap = "Principal";
		}
	}

	static string[] LocIds( LotLocationDef loc )
	{
		if ( loc is null )
			return new[] { "loc_porch" };
		return loc.Id switch
		{
			"toilet_pipes" => new[] { "loc_sewer", "loc_bathroom" },
			"jr_high_night" => new[] { "loc_school" },
			"dark_alley" => new[] { "loc_alley" },
			"neighbor_pool_night" => new[] { "loc_neighbor" },
			"gas_station" => new[] { "loc_gas" },
			"storm_drain" => new[] { "loc_sewer", "loc_alley" },
			"bingo_hall" => new[] { "loc_bingo" },
			_ => new[] { "loc_porch" }
		};
	}

	static string LocCaption( LotLocationDef loc )
	{
		if ( loc is null )
			return "Lot";
		return loc.Id switch
		{
			"toilet_pipes" => "Under the trailer",
			"jr_high_night" => "After hours",
			"dark_alley" => "Behind 4B",
			"neighbor_pool_night" => "Deed pool",
			"gas_station" => "Behind pumps",
			"storm_drain" => "Lot runoff",
			"bingo_hall" => "Downstairs",
			_ => loc.Name ?? "Lot"
		};
	}

	static string[] FlavorRight( LotLocationDef loc )
	{
		if ( loc is null )
			return new[] { "adv_cg_you", "ui_you" };
		return loc.Id switch
		{
			"toilet_pipes" => new[] { "adv_cg_mite", "adv_mite" },
			"jr_high_night" => new[] { "adv_cg_principal", "adv_cg_you" },
			"dark_alley" => new[] { "adv_cg_brad", "ui_bully" },
			"neighbor_pool_night" => new[] { "adv_cg_hazard" },
			"gas_station" => new[] { "adv_cg_janitor", "ui_janitor" },
			"storm_drain" => new[] { "adv_cg_you", "ui_you" },
			"bingo_hall" => new[] { "adv_cg_grandma", "ui_grandma" },
			_ => new[] { "adv_cg_you", "ui_you" }
		};
	}

	static string[] ThingIds( CrawlThing thing )
	{
		if ( thing is null )
			return new[] { "adv_mite" };
		if ( thing.Kind == CrawlKind.Boss )
			return new[] { "adv_cg_boss", thing.SpriteId, "adv_carp" };
		if ( thing.Kind == CrawlKind.Loot )
			return new[] { "adv_cg_loot", thing.SpriteId, "adv_coin" };
		if ( thing.Kind == CrawlKind.Hazard )
			return new[] { "adv_cg_hazard", thing.SpriteId, "adv_grate" };
		if ( string.Equals( thing.SpriteId, "adv_mite", StringComparison.OrdinalIgnoreCase ) )
			return new[] { "adv_cg_mite", "adv_mite" };
		if ( string.Equals( thing.SpriteId, "adv_carp", StringComparison.OrdinalIgnoreCase ) )
			return new[] { "adv_cg_boss", "adv_carp" };
		return new[] { thing.SpriteId, "adv_mite" };
	}

	static string ThingCaption( CrawlThing thing )
	{
		if ( thing is null )
			return "Incoming";
		return thing.Kind switch
		{
			CrawlKind.Boss => "Boss",
			CrawlKind.Loot => "Loot",
			CrawlKind.Hazard => "Hazard",
			_ => "Chomp"
		};
	}
}