Decompiled source of PotatoShopTweaks v1.0.1

plugins/PotatoShopTweaks.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: AssemblyTitle("Potato Shop Tweaks")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.1.0")]
namespace PotatoShopTweaks;

internal static class AutoPrice
{
	private sealed class Tally
	{
		public int Checked;

		public int Changed;

		public int AlreadyRight;

		public int NoMarket;

		public int Failed;
	}

	[HarmonyPatch(typeof(PriceChangeManager), "OnDayStarted")]
	internal static class Morning
	{
		[HarmonyPriority(0)]
		private static void Postfix()
		{
			if (Plugin.AutoPriceEveryMorning.Value)
			{
				Run("morning");
			}
		}
	}

	private const int PerFrame = 20;

	private static bool running;

	internal static void Run(string why)
	{
		if (running)
		{
			return;
		}
		if (Coop.IsGuest)
		{
			if (why == "hotkey")
			{
				Plugin.Toast("Auto-pricing: only the host can do this in co-op.");
			}
			return;
		}
		ShelfManager val = FindShelfManager();
		if ((Object)(object)val == (Object)null)
		{
			if (why == "hotkey")
			{
				Plugin.Toast("Auto-pricing: load your shop first.");
			}
		}
		else
		{
			((MonoBehaviour)Runner.Ensure()).StartCoroutine(Price(val, why));
		}
	}

	private static ShelfManager FindShelfManager()
	{
		ShelfManager result = null;
		int num = -1;
		ShelfManager[] array = Object.FindObjectsOfType<ShelfManager>();
		foreach (ShelfManager val in array)
		{
			if (!((Object)(object)val == (Object)null))
			{
				int num2 = Count(val.m_ShelfList) + Count(val.m_CardShelfList) + Count(val.m_CardItemCombiShelfList);
				if (num2 > num)
				{
					result = val;
					num = num2;
				}
			}
		}
		return result;
	}

	private static int Count<T>(List<T> list)
	{
		return list?.Count ?? 0;
	}

	private static IEnumerator Price(ShelfManager shelves, string why)
	{
		running = true;
		int step = 0;
		float factor = 1f + Plugin.AutoPriceMarkup.Value / 100f;
		Tally items = new Tally();
		Tally cards = new Tally();
		List<EItemType> itemTypes = new List<EItemType>();
		List<CardData> cardList = new List<CardData>();
		try
		{
			Collect(shelves, itemTypes, cardList);
		}
		catch (Exception ex)
		{
			running = false;
			Plugin.Log.LogError((object)("Auto-pricing couldn't read the shelves: " + ex));
			Plugin.Toast("Auto-pricing failed; see the BepInEx log.");
			yield break;
		}
		Plugin.Log.LogInfo((object)($"Auto-pricing: {Count(shelves.m_ShelfList)} shelves, {Count(shelves.m_CardShelfList)} card shelves, " + $"{Count(shelves.m_CardItemCombiShelfList)} combo shelves; {itemTypes.Count} kinds of items and {cardList.Count} kinds of cards on them."));
		foreach (EItemType type in itemTypes)
		{
			items.Checked++;
			try
			{
				float itemMarketPrice = CPlayerData.GetItemMarketPrice(type);
				if (itemMarketPrice <= 0f)
				{
					items.NoMarket++;
				}
				else
				{
					float num = Round(itemMarketPrice * factor);
					if (Mathf.Abs(CPlayerData.GetItemPrice(type, true) - num) > 0.001f)
					{
						CPlayerData.SetItemPrice(type, num);
						items.Changed++;
					}
					else
					{
						items.AlreadyRight++;
					}
				}
			}
			catch (Exception ex2)
			{
				items.Failed++;
				Plugin.Log.LogWarning((object)$"Auto-pricing skipped item {type}: {ex2.Message}");
			}
			int num2;
			step = (num2 = step + 1);
			if (num2 % 20 == 0)
			{
				yield return null;
			}
		}
		foreach (CardData card in cardList)
		{
			cards.Checked++;
			try
			{
				float cardMarketPrice = CPlayerData.GetCardMarketPrice(card);
				if (cardMarketPrice <= 0f)
				{
					cards.NoMarket++;
				}
				else
				{
					float num3 = Round(cardMarketPrice * factor);
					if (Mathf.Abs(CPlayerData.GetCardPrice(card) - num3) > 0.001f)
					{
						CPlayerData.SetCardPrice(card, num3);
						cards.Changed++;
					}
					else
					{
						cards.AlreadyRight++;
					}
				}
			}
			catch (Exception ex3)
			{
				cards.Failed++;
				Plugin.Log.LogWarning((object)$"Auto-pricing skipped a card: {ex3.Message}");
			}
			int num2;
			step = (num2 = step + 1);
			if (num2 % 20 == 0)
			{
				yield return null;
			}
		}
		running = false;
		Plugin.Log.LogInfo((object)($"Auto-pricing items: {items.Checked} checked, {items.Changed} changed, {items.AlreadyRight} already right, " + $"{items.NoMarket} without a market price, {items.Failed} failed. Cards: {cards.Checked} checked, {cards.Changed} changed, " + $"{cards.AlreadyRight} already right, {cards.NoMarket} without a market price, {cards.Failed} failed."));
		if (!(why != "hotkey") || items.Changed + cards.Changed != 0)
		{
			if (items.Checked + cards.Checked == 0)
			{
				Plugin.Toast("Auto-pricing: found nothing on your shelves to price.");
				yield break;
			}
			string markup = ((!(Plugin.AutoPriceMarkup.Value >= 0f)) ? $"{Plugin.AutoPriceMarkup.Value:0.#}%" : $"+{Plugin.AutoPriceMarkup.Value:0.#}%");
			string what = ((!Plugin.AutoPriceCards.Value) ? $"{items.Changed} of {items.Checked} items" : $"{items.Changed} of {items.Checked} items and {cards.Changed} of {cards.Checked} cards");
			int right = items.AlreadyRight + cards.AlreadyRight;
			Plugin.Toast($"Auto-pricing: repriced {what} to market {markup}" + ((right <= 0) ? "." : $" ({right} already were)."));
		}
	}

	private static void Collect(ShelfManager shelves, List<EItemType> itemTypes, List<CardData> cardList)
	{
		HashSet<EItemType> seen = new HashSet<EItemType>();
		if (shelves.m_ShelfList != null)
		{
			foreach (Shelf shelf in shelves.m_ShelfList)
			{
				if ((Object)(object)shelf != (Object)null)
				{
					AddItems(shelf.GetItemCompartmentList(), seen, itemTypes);
				}
			}
		}
		if (shelves.m_CardItemCombiShelfList != null)
		{
			foreach (CardItemCombiShelf cardItemCombiShelf in shelves.m_CardItemCombiShelfList)
			{
				if ((Object)(object)cardItemCombiShelf != (Object)null)
				{
					AddItems(cardItemCombiShelf.GetItemCompartmentList(), seen, itemTypes);
				}
			}
		}
		if (!Plugin.AutoPriceCards.Value)
		{
			return;
		}
		HashSet<string> seen2 = new HashSet<string>();
		if (shelves.m_CardShelfList != null)
		{
			foreach (CardShelf cardShelf in shelves.m_CardShelfList)
			{
				AddCards(cardShelf, seen2, cardList);
			}
		}
		if (shelves.m_CardItemCombiShelfList == null)
		{
			return;
		}
		foreach (CardItemCombiShelf cardItemCombiShelf2 in shelves.m_CardItemCombiShelfList)
		{
			AddCards((CardShelf)(object)cardItemCombiShelf2, seen2, cardList);
		}
	}

	private static void AddItems(List<ShelfCompartment> compartments, HashSet<EItemType> seen, List<EItemType> itemTypes)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Invalid comparison between Unknown and I4
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		if (compartments == null)
		{
			return;
		}
		foreach (ShelfCompartment compartment in compartments)
		{
			if (!((Object)(object)compartment == (Object)null))
			{
				EItemType itemType = compartment.GetItemType();
				if ((int)itemType >= 0 && seen.Add(itemType))
				{
					itemTypes.Add(itemType);
				}
			}
		}
	}

	private static void AddCards(CardShelf shelf, HashSet<string> seen, List<CardData> cardList)
	{
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)shelf == (Object)null)
		{
			return;
		}
		List<InteractableCardCompartment> cardCompartmentList = shelf.GetCardCompartmentList();
		if (cardCompartmentList == null)
		{
			return;
		}
		foreach (InteractableCardCompartment item2 in cardCompartmentList)
		{
			if ((Object)(object)item2 == (Object)null || item2.m_StoredCardList == null)
			{
				continue;
			}
			foreach (InteractableCard3d storedCard in item2.m_StoredCardList)
			{
				CardData val = ((!((Object)(object)storedCard != (Object)null) || !((Object)(object)storedCard.m_Card3dUI != (Object)null) || !((Object)(object)storedCard.m_Card3dUI.m_CardUI != (Object)null)) ? null : storedCard.m_Card3dUI.m_CardUI.GetCardData());
				if (val != null)
				{
					string item = $"{val.expansionType}|{val.monsterType}|{val.borderType}|{val.isFoil}|{val.isDestiny}|{val.cardGrade}|{val.gradedCardIndex}";
					if (seen.Add(item))
					{
						cardList.Add(val);
					}
				}
			}
		}
	}

	private static float Round(float price)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Invalid comparison between Unknown and I4
		if (Plugin.AutoPriceRound.Value)
		{
			float currencyConversionRate = GameInstance.GetCurrencyConversionRate();
			CGameManager instance = CSingleton<CGameManager>.Instance;
			price = ((!((Object)(object)instance != (Object)null) || (int)instance.m_CurrencyType != 2) ? ((float)Mathf.RoundToInt(price * currencyConversionRate)) : ((float)Mathf.RoundToInt(price * currencyConversionRate / 100f) * 100f));
			price /= currencyConversionRate;
		}
		float currencyRoundDivideAmount = GameInstance.GetCurrencyRoundDivideAmount();
		if (currencyRoundDivideAmount > 0f)
		{
			price = (float)Mathf.RoundToInt(price * currencyRoundDivideAmount) / currencyRoundDivideAmount;
		}
		return (!(price > 0f)) ? 0.5f : price;
	}
}
internal static class Coop
{
	internal const string OriginalId = "com.zwhit.cardshopcoop";

	internal const string CommunityId = "dev.meepen.cardshopcoop";

	private static bool looked;

	private static PropertyInfo roleProperty;

	private static PropertyInfo RoleProperty
	{
		get
		{
			if (!looked)
			{
				looked = true;
				if (Chainloader.PluginInfos.ContainsKey("com.zwhit.cardshopcoop") || Chainloader.PluginInfos.ContainsKey("dev.meepen.cardshopcoop"))
				{
					roleProperty = AccessTools.TypeByName("CardShopCoop.CoopCore")?.GetProperty("Role", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
					if (roleProperty == null)
					{
						Plugin.Log.LogWarning((object)"A co-op mod is installed but its session role couldn't be read; this mod acts as if every game is the host's.");
					}
				}
			}
			return roleProperty;
		}
	}

	internal static bool IsGuest
	{
		[CompilerGenerated]
		get
		{
			return Role() == "Client";
		}
	}

	private static string Role()
	{
		PropertyInfo propertyInfo = RoleProperty;
		if (propertyInfo == null)
		{
			return "None";
		}
		try
		{
			return propertyInfo.GetValue(null, null)?.ToString() ?? "None";
		}
		catch
		{
			return "None";
		}
	}

	internal static string Describe()
	{
		if (Chainloader.PluginInfos.ContainsKey("dev.meepen.cardshopcoop"))
		{
			return "CardShopCoopCommunity";
		}
		if (Chainloader.PluginInfos.ContainsKey("com.zwhit.cardshopcoop"))
		{
			return "CardShopCoop";
		}
		return "none (solo)";
	}
}
internal static class Customers
{
	[HarmonyPatch(typeof(CustomerManager), "EvaluateMaxCustomerCount")]
	internal static class Count
	{
		private static void Postfix(CustomerManager __instance)
		{
			if (!Coop.IsGuest)
			{
				float value = Plugin.CustomerCount.Value;
				if (!(value <= 0f) && value != 1f)
				{
					__instance.m_CustomerCountMax = Mathf.Max(1, Mathf.RoundToInt((float)__instance.m_CustomerCountMax * value));
					__instance.m_TimePerCustomer = Mathf.Max(0.5f, __instance.m_TimePerCustomer / value);
				}
			}
		}
	}

	[HarmonyPatch(typeof(CustomerManager), "GetCustomerMaxMoney")]
	internal static class Cash
	{
		private static void Postfix(ref float __result)
		{
			if (!Coop.IsGuest)
			{
				__result *= Plugin.CustomerCash.Value;
			}
		}
	}
}
internal static class Smelly
{
	[HarmonyPatch(typeof(Customer), "ActivateCustomer")]
	internal static class SpawnRoll
	{
		private static void Prefix()
		{
			Spawning = true;
		}

		private static void Finalizer()
		{
			Spawning = false;
		}
	}

	[HarmonyPatch(typeof(Customer), "SetSmelly")]
	internal static class Roll
	{
		private static bool Prefix()
		{
			if (!Spawning || Coop.IsGuest)
			{
				return true;
			}
			float value = Plugin.SmellyChance.Value;
			if (value >= 100f)
			{
				return true;
			}
			return Random.value * 100f < value;
		}
	}

	[HarmonyPatch(typeof(Customer), "StenchLeaveCheck")]
	internal static class Stench
	{
		private static bool Prefix(ref bool __result)
		{
			if (Plugin.StenchDrivesAway.Value || Coop.IsGuest)
			{
				return true;
			}
			__result = false;
			return false;
		}
	}

	internal static bool Spawning;
}
[HarmonyPatch(typeof(LightManager), "Update")]
internal static class DayLengthPatch
{
	[HarmonyPriority(0)]
	private static void Prefix(LightManager __instance, out float __state)
	{
		__state = -1f;
		float value = Plugin.DayLength.Value;
		if (!(value <= 0f) && value != 1f && !Coop.IsGuest)
		{
			__state = __instance.m_TimerLerpSpeed;
			__instance.m_TimerLerpSpeed = __state / value;
		}
	}

	private static void Finalizer(LightManager __instance, float __state)
	{
		if (__state >= 0f)
		{
			__instance.m_TimerLerpSpeed = __state;
		}
	}
}
internal static class Expansions
{
	[HarmonyPatch(typeof(CPlayerData), "GetUnlockShopRoomCost")]
	internal static class ShopRoom
	{
		private static void Postfix(ref float __result)
		{
			__result *= Plugin.ExpansionCost.Value;
		}
	}

	[HarmonyPatch(typeof(CPlayerData), "GetUnlockWarehouseRoomCost")]
	internal static class WarehouseRoom
	{
		private static void Postfix(ref float __result)
		{
			__result *= Plugin.ExpansionCost.Value;
		}
	}

	[HarmonyPatch(typeof(ExpansionShopUIScreen), "Init")]
	internal static class ShopScreen
	{
		private static void Prefix()
		{
			Apply(force: true);
		}
	}

	private static UnlockRoomManager manager;

	private static int managerId;

	private static float gamePrice;

	private static float appliedFactor = 1f;

	private static float nextLook;

	internal static void Apply(bool force)
	{
		if ((Object)(object)manager == (Object)null)
		{
			if (!force && Time.realtimeSinceStartup < nextLook)
			{
				return;
			}
			nextLook = Time.realtimeSinceStartup + 2f;
			manager = Object.FindObjectOfType<UnlockRoomManager>();
			if ((Object)(object)manager == (Object)null)
			{
				return;
			}
		}
		if (((Object)manager).GetInstanceID() != managerId)
		{
			managerId = ((Object)manager).GetInstanceID();
			gamePrice = manager.m_ShopB_UnlockPrice;
			appliedFactor = 1f;
		}
		float value = Plugin.ExpansionCost.Value;
		if (value != appliedFactor || force)
		{
			manager.m_ShopB_UnlockPrice = gamePrice * value;
			appliedFactor = value;
		}
	}
}
internal static class Market
{
	[HarmonyPatch(typeof(PriceChangeManager), "OnDayStarted")]
	internal static class DailyChange
	{
		private static void Prefix()
		{
			Rolling = !Coop.IsGuest;
		}

		private static void Finalizer()
		{
			Rolling = false;
		}
	}

	[HarmonyPatch(typeof(CPlayerData), "AddItemPricePercentChange")]
	internal static class ItemSwing
	{
		[HarmonyPriority(800)]
		private static void Prefix(ref float percentChange)
		{
			if (Rolling)
			{
				percentChange *= Plugin.PriceSwing.Value;
			}
		}
	}

	[HarmonyPatch(typeof(CPlayerData), "AddCardPricePercentChange")]
	internal static class CardSwing
	{
		[HarmonyPriority(800)]
		private static void Prefix(ref float percentChange)
		{
			if (Rolling)
			{
				percentChange *= Plugin.PriceSwing.Value;
			}
		}
	}

	[HarmonyPatch(typeof(PriceChangeManager), "EvaluatePriceCrash")]
	internal static class Crashes
	{
		private static bool Prefix()
		{
			return Plugin.PriceCrashes.Value || Coop.IsGuest;
		}
	}

	internal static bool Rolling;
}
[BepInPlugin("potato.shoptweaks", "Potato Shop Tweaks", "1.0.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInProcess("Card Shop Simulator.exe")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Id = "potato.shoptweaks";

	public const string Version = "1.0.1";

	internal static ManualLogSource Log;

	internal static Plugin Instance;

	internal static ConfigEntry<float> WorkerWorkSpeed;

	internal static ConfigEntry<float> WorkerWalkSpeed;

	internal static ConfigEntry<float> WorkerSalary;

	internal static ConfigEntry<float> CustomerCount;

	internal static ConfigEntry<float> CustomerCash;

	internal static ConfigEntry<float> SmellyChance;

	internal static ConfigEntry<bool> StenchDrivesAway;

	internal static ConfigEntry<float> PriceSwing;

	internal static ConfigEntry<bool> PriceCrashes;

	internal static ConfigEntry<KeyboardShortcut> AutoPriceKey;

	internal static ConfigEntry<float> AutoPriceMarkup;

	internal static ConfigEntry<bool> AutoPriceRound;

	internal static ConfigEntry<bool> AutoPriceCards;

	internal static ConfigEntry<bool> AutoPriceEveryMorning;

	internal static ConfigEntry<float> DayLength;

	internal static ConfigEntry<float> ExpansionCost;

	private Harmony harmony;

	private static ConfigFile configFile;

	private static FileSystemWatcher watcher;

	private static volatile bool configChanged;

	private static float reloadAt;

	private void Awake()
	{
		//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Expected O, but got Unknown
		//IL_034d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Instance = this;
		WorkerWorkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Workers", "Work speed", 1f, Host("How fast hired workers restock, scan items and give change: 2 = twice as fast. 1 = the game's normal. Applies when a worker starts their shift or changes task.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f)));
		WorkerWalkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Workers", "Walk speed", 1f, Host("How fast hired workers walk: 1.5 = half again as fast. 1 = the game's normal. Applies when a worker starts their shift or changes task.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f)));
		WorkerSalary = ((BaseUnityPlugin)this).Config.Bind<float>("1 - Workers", "Salary", 1f, Shared("Multiplies what workers cost per day, in the hiring screen and on the daily bill: 0.5 = half pay, 0 = they work for free. 1 = the game's normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)));
		CustomerCount = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Customers", "Customer count", 1f, Host("Multiplies how many customers can be in the shop at once and how often new ones arrive: 2 = twice as many, arriving twice as often. 1 = the game's normal. Applies on the next day, level-up or room unlock. A lot of customers can slow the game down.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f)));
		CustomerCash = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Customers", "Customer cash", 1f, Host("Multiplies how much money each new customer can spend: 2 = twice as much. 1 = the game's normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f)));
		SmellyChance = ((BaseUnityPlugin)this).Config.Bind<float>("3 - Smelly customers", "Smelly chance", 100f, Host("Percent of the game's chance that a new customer is smelly: 50 = half as many smelly customers, 0 = none. 100 = the game's normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f)));
		StenchDrivesAway = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Smelly customers", "Stench drives customers away", true, Host("On: the game's normal, other customers near a smelly one may leave and leave a bad review. Off: they don't mind the smell."));
		PriceSwing = ((BaseUnityPlugin)this).Config.Bind<float>("4 - Market prices", "Daily price swing", 1f, Host("Multiplies how far market prices of items and cards move each morning: 0.5 = half as much, 0 = prices never move, 2 = twice as wild. 1 = the game's normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f)));
		PriceCrashes = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Market prices", "Price crashes", true, Host("On: the game's normal, prices can sometimes crash or spike. Off: no crashes or spikes."));
		AutoPriceKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("5 - Auto-pricing", "Hotkey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Press to set the price of everything on your shelves to its market price plus the markup below. In co-op only the host can use it (the new prices reach everyone). Personal.");
		AutoPriceMarkup = ((BaseUnityPlugin)this).Config.Bind<float>("5 - Auto-pricing", "Markup percent", 10f, new ConfigDescription("Percent above market price: 10 = market price + 10%, 0 = exactly market price, -10 = 10% below. Personal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-50f, 200f), Array.Empty<object>()));
		AutoPriceRound = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Auto-pricing", "Round prices", false, "Round each price to a whole amount, the way the workers' \"round up\" option does. Rounding can push cheap items far above market. Personal.");
		AutoPriceCards = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Auto-pricing", "Include cards", true, "Also price the cards on your card shelves. Personal.");
		AutoPriceEveryMorning = ((BaseUnityPlugin)this).Config.Bind<bool>("5 - Auto-pricing", "Every morning", false, "Also auto-price every morning, right after the market moves. Host or solo only. Personal.");
		DayLength = ((BaseUnityPlugin)this).Config.Bind<float>("6 - Day length", "Day length", 1f, Host("Multiplies how long a shop day lasts in real time: 2 = days last twice as long (the clock runs at half speed). Customers keep arriving at their usual pace, so a longer day brings more of them. 1 = the game's normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f)));
		ExpansionCost = ((BaseUnityPlugin)this).Config.Bind<float>("7 - Expansions", "Expansion cost", 1f, Shared("Multiplies the cost of shop rooms, warehouse rooms and shop lot B: 0.5 = half price. 1 = the game's normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)));
		ExpansionCost.SettingChanged += delegate
		{
			Expansions.Apply(force: true);
		};
		harmony = new Harmony("potato.shoptweaks");
		Type[] array = new Type[18]
		{
			typeof(Workers.Speed),
			typeof(Workers.SalaryTotal),
			typeof(Workers.SalaryText),
			typeof(Workers.SalaryScreen),
			typeof(Customers.Count),
			typeof(Customers.Cash),
			typeof(Smelly.SpawnRoll),
			typeof(Smelly.Roll),
			typeof(Smelly.Stench),
			typeof(Market.DailyChange),
			typeof(Market.ItemSwing),
			typeof(Market.CardSwing),
			typeof(Market.Crashes),
			typeof(AutoPrice.Morning),
			typeof(DayLengthPatch),
			typeof(Expansions.ShopRoom),
			typeof(Expansions.WarehouseRoom),
			typeof(Expansions.ShopScreen)
		};
		foreach (Type type in array)
		{
			Patch(type);
		}
		WatchConfigFile();
		Runner.Ensure();
		Log.LogInfo((object)string.Format("Potato Shop Tweaks {0} loaded. Co-op mod: {1}.", "1.0.1", Coop.Describe()));
	}

	private void WatchConfigFile()
	{
		configFile = ((BaseUnityPlugin)this).Config;
		try
		{
			FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath));
			fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite;
			watcher = fileSystemWatcher;
			watcher.Changed += delegate
			{
				configChanged = true;
			};
			watcher.Created += delegate
			{
				configChanged = true;
			};
			watcher.Renamed += delegate
			{
				configChanged = true;
			};
			watcher.EnableRaisingEvents = true;
		}
		catch (Exception ex)
		{
			Log.LogWarning((object)("Settings won't reload while the game runs: " + ex.Message));
		}
	}

	internal static void CheckConfigReload()
	{
		if (!configChanged)
		{
			return;
		}
		if (reloadAt == 0f)
		{
			reloadAt = Time.realtimeSinceStartup + 1f;
		}
		else if (!(Time.realtimeSinceStartup < reloadAt))
		{
			configChanged = false;
			reloadAt = 0f;
			try
			{
				configFile.Reload();
				Toast("Potato Shop Tweaks: settings reloaded.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Couldn't reload settings: " + ex.Message));
			}
		}
	}

	private static ConfigDescription Host(string text, AcceptableValueBase range = null)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		return new ConfigDescription(text + " In co-op the host's setting counts.", range, Array.Empty<object>());
	}

	private static ConfigDescription Shared(string text, AcceptableValueBase range = null)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		return new ConfigDescription(text + " In co-op the host's setting is what's charged; keep it the same on every player's game so menus show the same prices.", range, Array.Empty<object>());
	}

	private void Patch(Type type)
	{
		try
		{
			harmony.CreateClassProcessor(type).Patch();
		}
		catch (Exception ex)
		{
			Log.LogError((object)$"{type.Name} is disabled: {ex.GetBaseException().Message}");
		}
	}

	private void Start()
	{
		Runner.Ensure();
	}

	internal static void Toast(string text)
	{
		Runner.Toast(text);
	}
}
internal sealed class Runner : MonoBehaviour
{
	private static Runner instance;

	private static string toast;

	private static float toastUntil;

	private static GUIStyle toastStyle;

	internal static Runner Ensure()
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		if ((Object)(object)instance != (Object)null)
		{
			return instance;
		}
		GameObject val = new GameObject("PotatoShopTweaks");
		Object.DontDestroyOnLoad((Object)(object)val);
		((Object)val).hideFlags = (HideFlags)61;
		instance = val.AddComponent<Runner>();
		return instance;
	}

	internal static void Toast(string text)
	{
		toast = text;
		toastUntil = Time.realtimeSinceStartup + 4f;
		Plugin.Log.LogInfo((object)text);
	}

	private void Update()
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			Plugin.CheckConfigReload();
			KeyboardShortcut value = Plugin.AutoPriceKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				AutoPrice.Run("hotkey");
			}
			Expansions.Apply(force: false);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Update: " + ex));
		}
	}

	private void OnGUI()
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0034: Expected O, but got Unknown
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if (toast != null && !(Time.realtimeSinceStartup > toastUntil))
		{
			if (toastStyle == null)
			{
				GUIStyle val = new GUIStyle(GUI.skin.box);
				val.fontSize = 20;
				val.alignment = (TextAnchor)4;
				val.wordWrap = true;
				toastStyle = val;
				toastStyle.normal.textColor = Color.white;
			}
			float num = Mathf.Min(700f, (float)Screen.width - 40f);
			GUI.Box(new Rect(((float)Screen.width - num) / 2f, 60f, num, 48f), toast, toastStyle);
		}
	}
}
internal static class Workers
{
	internal struct Stats
	{
		public float Restock;

		public float Scan;

		public float Change;

		public float Walk;
	}

	[HarmonyPatch]
	internal static class Speed
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			yield return AccessTools.Method(typeof(Worker), "EvaluateWorkerAttribute", (Type[])null, (Type[])null);
			yield return AccessTools.Method(typeof(Worker), "EvaluateTaskLevelStat", (Type[])null, (Type[])null);
		}

		private static void Prefix(Worker __instance, out Stats __state)
		{
			__state = Read(__instance);
		}

		private static void Postfix(Worker __instance, Stats __state)
		{
			if (Coop.IsGuest)
			{
				return;
			}
			Stats stats = Read(__instance);
			float value = Plugin.WorkerWorkSpeed.Value;
			float value2 = Plugin.WorkerWalkSpeed.Value;
			if (value > 0f && value != 1f)
			{
				if (stats.Restock != __state.Restock)
				{
					__instance.m_RestockTime = stats.Restock / value;
				}
				if (stats.Scan != __state.Scan)
				{
					__instance.m_ScanItemTime = stats.Scan / value;
				}
				if (stats.Change != __state.Change)
				{
					__instance.m_GiveChangeTime = stats.Change / value;
				}
			}
			if (value2 > 0f && value2 != 1f && stats.Walk != __state.Walk)
			{
				SetWalk(__instance, stats.Walk * value2);
			}
		}

		private static Stats Read(Worker w)
		{
			return new Stats
			{
				Restock = w.m_RestockTime,
				Scan = w.m_ScanItemTime,
				Change = w.m_GiveChangeTime,
				Walk = GetWalk(w)
			};
		}
	}

	[HarmonyPatch(typeof(WorkerManager), "EvaluateSalaryCost")]
	internal static class SalaryTotal
	{
		private static void Postfix(WorkerManager __instance)
		{
			float value = Plugin.WorkerSalary.Value;
			if (value != 1f)
			{
				__instance.m_TotalSalaryCost *= value;
			}
		}
	}

	[HarmonyPatch(typeof(WorkerData), "GetSalaryCostText")]
	internal static class SalaryText
	{
		private static void Prefix(WorkerData __instance, out float __state)
		{
			if (Scaled.IsScaled(__instance))
			{
				__state = float.NaN;
				return;
			}
			__state = __instance.costPerDay;
			__instance.costPerDay *= Plugin.WorkerSalary.Value;
		}

		private static void Finalizer(WorkerData __instance, float __state)
		{
			if (!float.IsNaN(__state))
			{
				__instance.costPerDay = __state;
			}
		}
	}

	[HarmonyPatch(typeof(WorkerInteractUIScreen), "OpenScreen")]
	internal static class SalaryScreen
	{
		private static void Prefix(Worker worker, out WorkerData __state)
		{
			__state = ((!((Object)(object)worker != (Object)null)) ? null : worker.GetWorkerData());
			if (__state != null)
			{
				Scaled.Push(__state);
			}
		}

		private static void Finalizer(WorkerData __state)
		{
			if (__state != null)
			{
				Scaled.Pop(__state);
			}
		}
	}

	private static class Scaled
	{
		private static readonly Dictionary<WorkerData, float> originals = new Dictionary<WorkerData, float>();

		internal static bool IsScaled(WorkerData data)
		{
			return originals.ContainsKey(data);
		}

		internal static void Push(WorkerData data)
		{
			if (!originals.ContainsKey(data))
			{
				originals[data] = data.costPerDay;
				data.costPerDay *= Plugin.WorkerSalary.Value;
			}
		}

		internal static void Pop(WorkerData data)
		{
			if (originals.TryGetValue(data, out var value))
			{
				data.costPerDay = value;
				originals.Remove(data);
			}
		}
	}

	private static readonly FieldInfo ExtraSpeedField = AccessTools.Field(typeof(Worker), "m_ExtraSpeedMultiplier");

	private static float GetWalk(Worker w)
	{
		return (float)ExtraSpeedField.GetValue(w);
	}

	private static void SetWalk(Worker w, float value)
	{
		ExtraSpeedField.SetValue(w, value);
	}
}