relics/Relic.cs
using Microsoft.VisualBasic;
using Sandbox;
using System.Reflection.PortableExecutable;
using System.Runtime.Versioning;
using System.Threading.Tasks;

public enum RelicType { None, Wristwatch, PrayerBeads, MedicHelmet, MagnifyingGlass, Salad, Bandage, MedicalLicense, Magic8Ball, RoboAssistant, Battery, BatteryEmpty, GuideDog, LoveLetter, Pill, Taxi, TriangleRuler,
	Sign, Saw, Shield, Microscope, Satellite, Coupon, Flag, Crayon, Butter, WarMedal, SlotMachine, HotPot, Abacus, Briefcase, ShoppingCart, Trophy, Socks, Chopsticks, BloodDonation, RecycleBin, Clipboard, Juicebox,
	Chocolate, SacrificialBlade, Scale, Telescope, BowAndArrow, MantlepieceClock, Dartboard, PirateFlag, Revolver, MammothMeat, GrandfatherClock, PersonalChef, MouseTrap, KitchenKnife, LightBulb, RunningShoes,
	CreditCard, }

public class Relic : Component, IEventHandler
{
	public RelicType RelicType { get; set; }
	public int Level { get; set; }
	public int MaxLevel { get; set; }

	public virtual void Init()
	{
		MaxLevel = 3;
	}

	public virtual void LevelUp()
	{
		Level = Math.Min(Level + 1, MaxLevel);
	}

	public static string GetName( RelicType relicType )
	{
		switch ( relicType )
		{
			case RelicType.PrayerBeads: return "Prayer Beads";
			case RelicType.MedicHelmet: return "Medic Helmet";
			case RelicType.MagnifyingGlass: return "Magnifying Glass";
			case RelicType.MedicalLicense: return "Medical License";
			case RelicType.Magic8Ball: return "Magic 8 Ball";
			case RelicType.RoboAssistant: return "Robo-Assistant";
			case RelicType.BatteryEmpty: return "Battery (Empty)";
			case RelicType.GuideDog: return "Guide Dog";
			case RelicType.LoveLetter: return "Love Letter";
			case RelicType.TriangleRuler: return "Triangle Ruler";
			case RelicType.WarMedal: return "War Medal";
			case RelicType.SlotMachine: return "Slot Machine";
			case RelicType.HotPot: return "Hot Pot";
			case RelicType.ShoppingCart: return "Shopping Cart";
			case RelicType.BloodDonation: return "Blood Donation";
			case RelicType.RecycleBin: return "Recycle Bin";
			case RelicType.SacrificialBlade: return "Sacrificial Blade";
			case RelicType.BowAndArrow: return "Bow and Arrow";
			case RelicType.MantlepieceClock: return "Mantlepiece Clock";
			case RelicType.PirateFlag: return "Pirate Flag";
			case RelicType.MammothMeat: return "Mammoth Meat";
			case RelicType.GrandfatherClock: return "Grandfather Clock";
			case RelicType.PersonalChef: return "Personal Chef";
			case RelicType.MouseTrap: return "Mouse Trap";
			case RelicType.KitchenKnife: return "Kitchen Knife";
			case RelicType.LightBulb: return "Light Bulb";
			case RelicType.RunningShoes: return "Running Shoes";
			case RelicType.CreditCard: return "Credit Card";
		}

		return relicType.ToString();
	}

	public static string GetIconFilename( RelicType relicType )
	{
		switch ( relicType )
		{
			case RelicType.Wristwatch: return "textures/relics/wristwatch.png";
			//case RelicType.Ring: return "textures/relics/ring.png";
			case RelicType.PrayerBeads: return "textures/relics/prayer_beads.png";
			//case RelicType.Lipstick: return "textures/relics/lipstick.png";
			case RelicType.MedicHelmet: return "textures/relics/medic_helmet.png";
			case RelicType.MagnifyingGlass: return "textures/relics/magnifying_glass.png";
			case RelicType.Salad: return "textures/relics/salad.png";
			case RelicType.Bandage: return "textures/relics/bandage.png";
			case RelicType.MedicalLicense: return "textures/relics/medical_license.png";
			case RelicType.Magic8Ball: return "textures/relics/magic_8_ball.png";
			case RelicType.RoboAssistant: return "textures/relics/robot.png";
			case RelicType.Battery: return "textures/relics/battery.png";
			case RelicType.BatteryEmpty: return "textures/relics/battery_empty.png";
			case RelicType.GuideDog: return "textures/guide_dog.png";
			case RelicType.LoveLetter: return "textures/relics/love_letter.png";
			case RelicType.Pill: return "textures/relics/pill.png";
			case RelicType.Taxi: return "textures/relics/taxi.png";
			case RelicType.TriangleRuler: return "textures/relics/triangle_ruler.png";
			case RelicType.Sign: return "textures/relics/sign.png";
			case RelicType.Saw: return "textures/relics/saw.png";
			case RelicType.Shield: return "textures/relics/shield.png";
			case RelicType.Microscope: return "textures/relics/microscope.png";
			case RelicType.Satellite: return "textures/relics/satellite.png";
			case RelicType.Coupon: return "textures/relics/coupon.png";
			case RelicType.Flag: return "textures/relics/flag.png";
			case RelicType.Crayon: return "textures/relics/crayon.png";
			case RelicType.Butter: return "textures/relics/butter.png";
			case RelicType.WarMedal: return "textures/relics/war_medal.png";
			case RelicType.SlotMachine: return "textures/relics/slot_machine.png";
			case RelicType.HotPot: return "textures/relics/hot_pot.png";
			case RelicType.Abacus: return "textures/relics/abacus.png";
			case RelicType.Briefcase: return "textures/relics/briefcase.png";
			case RelicType.ShoppingCart: return "textures/relics/shopping_cart.png";
			case RelicType.Trophy: return "textures/relics/trophy.png";
			case RelicType.Socks: return "textures/relics/socks.png";
			case RelicType.Chopsticks: return "textures/relics/chopsticks.png";
			case RelicType.BloodDonation: return "textures/relics/blood_donation.png";
			case RelicType.RecycleBin: return "textures/relics/recycle_bin.png";
			case RelicType.Clipboard: return "textures/relics/clipboard.png";
			case RelicType.Juicebox: return "textures/relics/juicebox.png";
			case RelicType.Chocolate: return "textures/relics/chocolate.png";
			case RelicType.SacrificialBlade: return "textures/relics/sacrificial_blade.png";
			case RelicType.Scale: return "textures/relics/scale.png";
			case RelicType.Telescope: return "textures/relics/telescope.png";
			case RelicType.BowAndArrow: return "textures/relics/bow_and_arrow.png";
			case RelicType.MantlepieceClock: return "textures/relics/mantlepiece_clock.png";
			case RelicType.Dartboard: return "textures/relics/dartboard.png";
			case RelicType.PirateFlag: return "textures/relics/pirate_flag.png";
			case RelicType.Revolver: return "textures/relics/revolver.png";
			case RelicType.MammothMeat: return "textures/relics/mammoth_meat.png";
			case RelicType.GrandfatherClock: return "textures/relics/grandfather_clock.png";
			case RelicType.PersonalChef: return "textures/relics/personal_chef.png";
			case RelicType.MouseTrap: return "textures/relics/mouse_trap.png";
			case RelicType.KitchenKnife: return "textures/relics/kitchen_knife.png";
			case RelicType.LightBulb: return "textures/relics/light_bulb.png";
			case RelicType.RunningShoes: return "textures/relics/running_shoes.png";
			case RelicType.CreditCard: return "textures/relics/credit_card.png";
		}

		return "";
	}

	public static string GetRelicDescription( RelicType relicType, int level )
	{
		switch ( relicType )
		{
			case RelicType.Wristwatch: return $"+{2 * level}s turn duration";
			//case RelicType.Ring: return "This is a description";
			case RelicType.PrayerBeads: return $"{10 + 20 * level}% chance to heal +1 HP when you match a card that hadn't been previously revealed";
			//case RelicType.Lipstick: return "This is a description";
			case RelicType.MedicHelmet: return $"☀️Level start: heal +{level} HP";
			case RelicType.MagnifyingGlass: return $"☀️Level start: reveal {level} card{(level == 1 ? "" : "s")}";
			case RelicType.Salad: return $"+{level} Max HP";
			case RelicType.Bandage: return $"+{3 * level} HP";
			case RelicType.MedicalLicense: return $"When you overheal during a level, gain that much $";
			case RelicType.Magic8Ball: return $"When a card shakes, {level * 5}% chance to reveal it";
			case RelicType.RoboAssistant: return $"☀️Level start: shake {level} card{(level == 1 ? "" : "s")} and move it closer to {(level == 1 ? "its match" : "their matches")}";
			case RelicType.Battery: return $"Instead of dying, recover half your HP (only works once)";
			case RelicType.BatteryEmpty: return $"Instead of dying, recover half your HP (only works once)";
			case RelicType.GuideDog: return $"☀️Level start: replace a card pair with guide dog";
			case RelicType.LoveLetter: return $"When you heal, {level * 20}% chance to reveal a card";
			case RelicType.Pill: return $"Recover full HP, but -{3 * level}s turn duration";
			case RelicType.Taxi: return $"❌Mismatch: move {(level == 1 ? "one of the cards toward its match" : "both of the cards toward their matches")}";
			case RelicType.TriangleRuler: return $"Every {5 - level} matches, reveal a corner card";
			case RelicType.Sign: return $"❌Mismatch: {level * 25}% chance to reveal a card you've already seen";
			case RelicType.Saw: return $"❌Mismatch: {level * 10}% chance to\nget +$1";
			case RelicType.Shield: return $"The first {level} {(level == 1 ? "mismatch" : "mismatches")} each level {(level == 1 ? "doesn't" : "don't")} hurt you";
			case RelicType.Microscope: return $"✅Match: reveal a nearby card";
			case RelicType.Satellite: return $"Next level start: reveal {level * 3} cards";
			case RelicType.Coupon: return $"After next level, the first item you buy will be free";
			case RelicType.Flag: return $"Place up to {level} flag{(level == 1 ? "" : "s")} on cards (removed when chosen)\n(right-click to add/remove)                    ";
			case RelicType.Crayon: return $"Cards show the # of times they've been chosen (up to {level} time{(level == 1 ? "" : "s")})";
			case RelicType.Butter: return $"Food/beverage cards heal an additional {level} HP";
			case RelicType.WarMedal: return $"+${level} at the end of every level";
			case RelicType.SlotMachine: return $"+${level} when matching 2 adjacent cards";
			case RelicType.HotPot: return $"+{level} HP when you make 3 consecutive matches";
			case RelicType.Abacus: return $"+${level} when you make 3 consecutive matches";
			case RelicType.Briefcase: return $"When you gain money, get ${level} extra";
			case RelicType.ShoppingCart: return $"The shop offers {level} extra item";
			case RelicType.Trophy: return $"+${2 * level} when you finish a level at full HP";
			case RelicType.Socks: return $"☀️Level start: shake {level} card{(level == 1 ? "" : "s")} {(level == 1 ? "that's" : "that are")} adjacent to {(level == 1 ? "its match" : "their matches")}";
			case RelicType.Chopsticks: return $"{20 * level}% chance to heal +1 HP when you make 2 consecutive matches";
			case RelicType.BloodDonation: return $"+${3 * level}";
			case RelicType.RecycleBin: return $"Reroll shop items";
			case RelicType.Clipboard: return $"+{100 * level}% chance for the shop to offer items you already have";
			case RelicType.Juicebox: return $"{15 * level}% chance to heal +1 HP when you buy an item";
			case RelicType.Chocolate: return $"+3 HP, but -{level} Max HP";
			case RelicType.SacrificialBlade: return $"When you hurt a boss, heal +{level} HP";
			case RelicType.Scale: return $"Choose first card each turn: shake {level * 2} cards that don't match";
			case RelicType.Telescope: return $"Choose first card each turn: shake it if its match is >2 spaces away";
			case RelicType.BowAndArrow: return $"Each level has {level} additional {(level == 1 ? "bounty" : "bounties")}";
			case RelicType.MantlepieceClock: return $"Bounties last {1 + level} additional turns";
			case RelicType.Dartboard: return $"Bounties are worth ${level} more";
			case RelicType.PirateFlag: return $"When buying an item, {10 * level}% chance to get it for free";
			case RelicType.Revolver: return $"☀️Level start: shake {level} card{(level == 1 ? "" : "s")} that {(level == 1 ? "has" : "have")} a bounty";
			case RelicType.MammothMeat: return $"+{8 * level} Max HP";
			case RelicType.GrandfatherClock: return $"+{10 * level}s turn duration";
			case RelicType.PersonalChef: return $"When you overheal during a level, gain that much Max HP";
			case RelicType.MouseTrap: return $"When you claim a bounty, get +{level} Max HP";
			case RelicType.KitchenKnife: return $"When you claim a bounty, heal +{level} HP";
			case RelicType.LightBulb: return $"When you claim a bounty, reveal all nearby cards";
			case RelicType.RunningShoes: return $"Bounties can be claimed before they're ready";
			case RelicType.CreditCard: return $"All items cost HP instead of money";
		}

		return "";
	}

	public static string GetRelicUpgradeDescription( RelicType relicType, int fromLevel, int toLevel )
	{
		switch ( relicType )
		{
			case RelicType.Wristwatch: return $"+2s time per turn"; // return $"+{2 * fromLevel}→{2 * toLevel}s time per turn";
			case RelicType.PrayerBeads: return $"{10 + 20 * fromLevel}→{10 + 20 * toLevel}% chance to heal +1 HP when you match a card that hadn't been previously revealed";
			case RelicType.MedicHelmet: return $"☀️Level start: heal +{fromLevel}→{toLevel} HP";
			case RelicType.MagnifyingGlass: return $"☀️Level start: reveal {fromLevel}→{toLevel} cards";
			case RelicType.Salad: return $"+1 Max HP"; // return $"+{2 * fromLevel}→{2 * toLevel} Max HP";
			case RelicType.Bandage: return $"+3 HP";
			case RelicType.Magic8Ball: return $"When a card shakes, {fromLevel * 5}→{toLevel * 5}% chance to reveal it";
			case RelicType.RoboAssistant: return $"☀️Level start: shake {fromLevel}→{toLevel} cards and move them closer to their matches";
			case RelicType.LoveLetter: return $"When you heal, {fromLevel * 20}→{toLevel * 20}% chance to reveal a card";
			case RelicType.Pill: return $"Recover full HP, but -3s turn duration";
			case RelicType.Taxi: return $"❌Mismatch: move one→both of the cards toward their matches";
			case RelicType.TriangleRuler: return $"Every {5 - fromLevel}→{5 - toLevel} matches, reveal a corner card";
			case RelicType.Sign: return $"❌Mismatch: {fromLevel * 25}→{toLevel * 25}% chance to reveal a card you've already seen";
			case RelicType.Saw: return $"❌Mismatch: {fromLevel * 10}→{toLevel * 10}% chance to get +$1";
			case RelicType.Shield: return $"The first {fromLevel}→{toLevel} mismatches each level don't hurt you";
			case RelicType.Satellite: return $"Next level start: reveal {fromLevel * 3}→{toLevel * 3} cards";
			case RelicType.Flag: return $"Place up to {fromLevel}→{toLevel} flags on cards (removed when chosen)\n(right-click to add/remove)";
			case RelicType.Crayon: return $"Cards show the # of times they've been chosen (up to {fromLevel}→{toLevel} times)";
			case RelicType.Butter: return $"Food/beverage cards heal an additional {fromLevel}→{toLevel} HP";
			case RelicType.WarMedal: return $"+${fromLevel}→{toLevel} at the end of every level";
			case RelicType.SlotMachine: return $"+${fromLevel}→{toLevel} when matching 2 adjacent cards";
			case RelicType.HotPot: return $"+{fromLevel}→{toLevel} HP when you make 3 consecutive matches";
			case RelicType.Abacus: return $"+${fromLevel}→{toLevel} when you make 3 consecutive matches";
			case RelicType.Briefcase: return $"Whenever you gain money, get ${fromLevel}→{toLevel} extra";
			case RelicType.ShoppingCart: return $"The shop offers {fromLevel}→{toLevel} extra items";
			case RelicType.Trophy: return $"+${2 * fromLevel}→{2 * toLevel} when you finish a level at full HP";
			case RelicType.Socks: return $"☀️Level start: shake {fromLevel}→{toLevel} cards that are adjacent to their matches";
			case RelicType.Chopsticks: return $"{20 * fromLevel}→{20 * toLevel}% chance to heal +1 HP when you make 2 consecutive matches";
			case RelicType.BloodDonation: return $"+$3";
			case RelicType.RecycleBin: return $"Reroll shop items";
			case RelicType.Clipboard: return $"+{100 * fromLevel}→{100 * toLevel}% chance for the shop to offer items you already have";
			case RelicType.Juicebox: return $"{15 * fromLevel}→{15 * toLevel}% chance to heal +1 HP when you buy an item";
			case RelicType.Chocolate: return $"+3 HP, but -1 Max HP";
			case RelicType.SacrificialBlade: return $"When you hurt a boss, heal +{fromLevel}→{toLevel} HP";
			case RelicType.Scale: return $"Choose first card each turn: shake {fromLevel * 2}→{toLevel * 2} cards that don't match";
			case RelicType.BowAndArrow: return $"Each level has {fromLevel}→{toLevel} additional bounties";
			case RelicType.MantlepieceClock: return $"Bounties last {1 + fromLevel}→{1 + toLevel} additional turns";
			case RelicType.Dartboard: return $"Bounties are worth ${fromLevel}→{toLevel} more";
			case RelicType.PirateFlag: return $"When buying an item, {10 * fromLevel}→{10 * toLevel}% chance to get it for free";
			case RelicType.Revolver: return $"☀️Level start: shake {fromLevel}→{toLevel} cards that have a bounty";
			case RelicType.MammothMeat: return $"+8 Max HP";
			case RelicType.GrandfatherClock: return $"+10s turn duration";
			case RelicType.MouseTrap: return $"When you claim a bounty, get +{fromLevel}→{toLevel} Max HP";
			case RelicType.KitchenKnife: return $"When you claim a bounty, heal +{fromLevel}→{toLevel} HP";
		}

		return "";
	}

	public static int GetRelicPrice( RelicType relicType, int level )
	{
		switch ( relicType )
		{
			case RelicType.Wristwatch: return 1;
			//case RelicType.Ring: return 4;
			case RelicType.PrayerBeads: return 7;
			//case RelicType.Lipstick: return 1;
			case RelicType.MedicHelmet: return 1 + level;
			case RelicType.MagnifyingGlass: return level;
			case RelicType.Salad: return level;
			case RelicType.Bandage: return 1;
			case RelicType.MedicalLicense: return 9;
			case RelicType.Magic8Ball: return 2;
			case RelicType.RoboAssistant: return 1;
			case RelicType.Battery: return 8;
			case RelicType.GuideDog: return 8;
			case RelicType.LoveLetter: return 2 + level;
			case RelicType.Pill: return 1 + level * 2;
			case RelicType.Taxi: return 8;
			case RelicType.TriangleRuler: return 2;
			case RelicType.Sign: return 2;
			case RelicType.Saw: return 3 + level;
			case RelicType.Shield: return 1 + level;
			case RelicType.Microscope: return 12;
			case RelicType.Satellite: return 1 + level;
			case RelicType.Coupon: return 5;
			case RelicType.Flag: return 2 + level;
			case RelicType.Crayon: return 3 + level * 2;
			case RelicType.Butter: return 3 + level * 2;
			case RelicType.WarMedal: return 2 + level;
			case RelicType.SlotMachine: return 1 + level * 2;
			case RelicType.HotPot: return 2 + level * 2;
			case RelicType.Abacus: return 2 + level * 2;
			case RelicType.Briefcase: return 3 + level * 2;
			case RelicType.ShoppingCart: return level;
			case RelicType.Trophy: return level;
			case RelicType.Socks: return level;
			case RelicType.Chopsticks: return 2 + level;
			case RelicType.BloodDonation: return 1 + level;
			case RelicType.RecycleBin: return level - 1;
			case RelicType.Clipboard: return level;
			case RelicType.Juicebox: return 2 + level;
			case RelicType.Chocolate: return level - 1;
			case RelicType.SacrificialBlade: return 1 + level * 2;
			case RelicType.Scale: return 2;
			case RelicType.Telescope: return 3;
			case RelicType.BowAndArrow: return 1 + level;
			case RelicType.MantlepieceClock: return level;
			case RelicType.Dartboard: return level;
			case RelicType.PirateFlag: return 2 + level;
			case RelicType.Revolver: return 1 + 2 * level;
			case RelicType.MammothMeat: return 20;
			case RelicType.GrandfatherClock: return 18;
			case RelicType.PersonalChef: return 20;
			case RelicType.MouseTrap: return level * 2 - 1;
			case RelicType.KitchenKnife: return level;
			case RelicType.LightBulb: return 4;
			case RelicType.RunningShoes: return 9;
			case RelicType.CreditCard: return 12;
		}

		return 0;
	}

	public static bool DoesRelicCostHP( RelicType relicType )
	{
		switch ( relicType )
		{
			case RelicType.WarMedal: return true;
			case RelicType.Abacus: return true;
			case RelicType.Briefcase: return true;
			case RelicType.BloodDonation: return true;
		}

		return false;
	}

	public virtual bool ShouldHandleEvent( EventType eventType )
	{
		return false;
	}

	public virtual async Task HandleEventAsync(EventType eventType)
	{
		await Task.Frame();
	}

	public virtual string GetEventText( EventType eventType )
	{
		return GetRelicDescription( RelicType, Level );
	}

	public void SetRelicType( RelicType newType) 
	{
		RelicType = newType;
		Manager.Instance.RelicHash++;
	}
}