Decompiled source of GeneratorMod v0.3.0

GeneratorMod.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using REPOLib.Modules;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("GeneratorMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0")]
[assembly: AssemblyProduct("GeneratorMod")]
[assembly: AssemblyTitle("GeneratorMod")]
[assembly: AssemblyVersion("0.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GeneratorMod
{
	internal static class ChargingStationAccess
	{
		private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		private static readonly FieldInfo ChargeTotal = typeof(ChargingStation).GetField("chargeTotal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo ChargeFloat = typeof(ChargingStation).GetField("chargeFloat", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo SegmentCurrent = typeof(ChargingStation).GetField("chargeSegmentCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo Segments = typeof(ChargingStation).GetField("chargeSegments", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static ChargingStation cached;

		private static float nextSearchTime;

		private static bool loggedLayout;

		private static bool warnedMissing;

		public static bool Usable
		{
			get
			{
				if (ChargeTotal != null)
				{
					return ChargeTotal.FieldType == typeof(int);
				}
				return false;
			}
		}

		public static ChargingStation Get()
		{
			if ((Object)(object)cached != (Object)null)
			{
				return cached;
			}
			if (Time.unscaledTime < nextSearchTime)
			{
				return null;
			}
			nextSearchTime = Time.unscaledTime + 1f;
			cached = Object.FindObjectOfType<ChargingStation>();
			if ((Object)(object)cached != (Object)null)
			{
				LogLayoutOnce(cached);
			}
			return cached;
		}

		public static int GetCharge(ChargingStation station)
		{
			if (!Usable)
			{
				return 0;
			}
			return (int)ChargeTotal.GetValue(station);
		}

		public static bool AddCharge(ChargingStation station, int percent)
		{
			if (!Usable)
			{
				if (!warnedMissing)
				{
					warnedMissing = true;
					Plugin.Log.LogError((object)"ChargingStation.chargeTotal (int) not found - the game may have renamed it. Recharge disabled.");
				}
				return false;
			}
			int num = Mathf.Max(1, Plugin.MaxCharge.Value);
			int num2 = (int)ChargeTotal.GetValue(station);
			int num3 = Mathf.Clamp(num2 + percent, 0, num);
			if (num3 == num2)
			{
				return false;
			}
			Plugin.Log.LogInfo((object)$"AddCharge called: percent={percent}, before={num2}, max={num}");
			if (num3 == num2)
			{
				Plugin.Log.LogInfo((object)"AddCharge: no change (clamped or percent is 0)");
				return false;
			}
			ChargeTotal.SetValue(station, num3);
			Plugin.Log.LogInfo((object)$"AddCharge set: total={(int)ChargeTotal.GetValue(station)}");
			float num4 = (float)num3 / (float)num;
			if (ChargeFloat != null && ChargeFloat.FieldType == typeof(float))
			{
				ChargeFloat.SetValue(station, num4);
			}
			if (SegmentCurrent != null && SegmentCurrent.FieldType == typeof(int) && Segments != null && Segments.FieldType == typeof(int))
			{
				int num5 = (int)Segments.GetValue(station);
				SegmentCurrent.SetValue(station, Mathf.RoundToInt(num4 * (float)num5));
			}
			return true;
		}

		private static void LogLayoutOnce(ChargingStation station)
		{
			if (!loggedLayout)
			{
				loggedLayout = true;
				IEnumerable<string> values = from f in typeof(ChargingStation).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
					where f.Name.StartsWith("charge", StringComparison.OrdinalIgnoreCase)
					select $"{f.FieldType.Name} {f.Name}={f.GetValue(station)}";
				Plugin.Log.LogInfo((object)("ChargingStation found. Charge-related fields: " + string.Join(", ", values)));
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "Update")]
	internal static class ChargingStationUpdatePatch
	{
		private static void Postfix(ref float ___chargeFloat)
		{
			float percentPerSecond = GeneratorTicker.PercentPerSecond;
			if (!(percentPerSecond <= 0f) && SemiFunc.IsMasterClientOrSingleplayer())
			{
				float num = (float)Mathf.Max(1, Plugin.MaxCharge.Value) / 100f;
				if (!(___chargeFloat >= num))
				{
					___chargeFloat = Mathf.Min(num, ___chargeFloat + percentPerSecond * Time.deltaTime / 100f);
				}
			}
		}
	}
	internal static class GeneratorItemFactory
	{
		internal const string AssetName = "Item Upgrade Player Generator";

		internal const string DisplayName = "Generator Upgrade";

		private static GameObject prefabRoot;

		internal static Item CreateItemData()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			Item obj = ScriptableObject.CreateInstance<Item>();
			((Object)obj).name = "Item Upgrade Player Generator";
			obj.itemName = "Generator Upgrade";
			obj.description = "Slowly recharges the truck's energy crystals during levels.";
			obj.itemType = (itemType)3;
			obj.emojiIcon = (emojiIcon)11;
			obj.itemVolume = (itemVolume)6;
			obj.value = ScriptableObject.CreateInstance<Value>();
			obj.minPlayerCount = 1;
			obj.physicalItem = true;
			ApplyConfiguredValues(obj);
			return obj;
		}

		internal static void ApplyConfiguredValues(Item item)
		{
			if (!((Object)(object)item == (Object)null))
			{
				if ((Object)(object)item.value == (Object)null)
				{
					item.value = ScriptableObject.CreateInstance<Value>();
				}
				float num = (float)Plugin.BasePrice.Value / 4f;
				item.value.valueMin = num;
				item.value.valueMax = num;
				int value = Plugin.MaxPurchases.Value;
				item.maxPurchase = true;
				item.maxPurchaseAmount = value;
				item.maxAmount = value;
			}
		}

		internal static IEnumerator RegisterPrefabWhenReady()
		{
			Item template = null;
			int waits = 0;
			while ((Object)(object)template == (Object)null)
			{
				template = FindTemplate();
				if ((Object)(object)template != (Object)null)
				{
					break;
				}
				waits++;
				if (waits == 120)
				{
					Plugin.Log.LogWarning((object)("Still waiting for vanilla upgrade '" + Plugin.TemplateItemName.Value + "'. Upgrade items seen so far: " + ListUpgradeItemNames()));
				}
				yield return (object)new WaitForSeconds(0.25f);
			}
			Plugin.Log.LogInfo((object)("Using '" + ((Object)template).name + "' as the prefab template."));
			CopyTemplateMetadata(template, Plugin.GeneratorItem);
			prefabRoot = new GameObject("GeneratorMod - Registered Prefabs");
			prefabRoot.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)prefabRoot);
			GameObject val = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)template.prefab).Prefab, prefabRoot.transform, false);
			((Object)val).name = "Item Upgrade Player Generator";
			ItemAttributes component = val.GetComponent<ItemAttributes>();
			ItemUpgrade component2 = val.GetComponent<ItemUpgrade>();
			ItemToggle component3 = val.GetComponent<ItemToggle>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || (Object)(object)component3 == (Object)null)
			{
				Plugin.Log.LogError((object)("Template prefab '" + ((Object)template).name + "' is missing ItemAttributes / ItemUpgrade / ItemToggle. The game may have changed. Aborting."));
				Object.Destroy((Object)(object)prefabRoot);
				prefabRoot = null;
				yield break;
			}
			component.item = Plugin.GeneratorItem;
			component2.isPlayerUpgrade = true;
			component2.upgradeEvent = new UnityEvent();
			StripVanillaUpgradeComponents(val);
			GeneratorVisuals.Apply(val);
			REPOLibItemUpgrade val2 = val.GetComponent<REPOLibItemUpgrade>();
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val.AddComponent<REPOLibItemUpgrade>();
			}
			AccessTools.Field(typeof(REPOLibItemUpgrade), "_upgradeId").SetValue(val2, "Generator");
			if ((Object)(object)val.GetComponent<GeneratorUpgradeBridge>() == (Object)null)
			{
				val.AddComponent<GeneratorUpgradeBridge>();
			}
			if (Items.RegisterItem(component) == null)
			{
				Plugin.Log.LogError((object)"REPOLib rejected the Generator item prefab.");
			}
			else
			{
				Plugin.Log.LogInfo((object)($"Registered '{Plugin.GeneratorItem.itemName}' at ${Plugin.BasePrice.Value:N0}, " + $"{Plugin.ShopChancePercent.Value}% shop chance."));
			}
		}

		private static Item FindTemplate()
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			string value = Plugin.TemplateItemName.Value;
			Item val = null;
			foreach (Item allItem in Items.AllItems)
			{
				if (!((Object)(object)allItem == (Object)null) && !((Object)(object)allItem == (Object)(object)Plugin.GeneratorItem) && allItem.prefab != null && !((Object)(object)((PrefabRef<GameObject>)(object)allItem.prefab).Prefab == (Object)null))
				{
					if (((Object)allItem).name == value)
					{
						return allItem;
					}
					if ((Object)(object)val == (Object)null && (int)allItem.itemType == 3 && ((Object)allItem).name.StartsWith("Item Upgrade Player", StringComparison.Ordinal) && (((Object)allItem).name.IndexOf("Energy", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)allItem).name.IndexOf("Stamina", StringComparison.OrdinalIgnoreCase) >= 0))
					{
						val = allItem;
					}
				}
			}
			return val;
		}

		private static string ListUpgradeItemNames()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			List<string> list = new List<string>();
			foreach (Item allItem in Items.AllItems)
			{
				if ((Object)(object)allItem != (Object)null && (int)allItem.itemType == 3)
				{
					list.Add(((Object)allItem).name);
				}
			}
			if (list.Count != 0)
			{
				return string.Join(", ", list);
			}
			return "(none yet)";
		}

		private static void StripVanillaUpgradeComponents(GameObject prefab)
		{
			MonoBehaviour[] components = prefab.GetComponents<MonoBehaviour>();
			foreach (MonoBehaviour val in components)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((object)val).GetType().Name;
					if (name.StartsWith("ItemUpgradePlayer", StringComparison.Ordinal))
					{
						Plugin.Log.LogInfo((object)("Removing vanilla component " + name + " from the copied prefab."));
						Object.DestroyImmediate((Object)(object)val);
					}
				}
			}
		}

		private static void CopyTemplateMetadata(Item source, Item destination)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			destination.disabled = false;
			destination.itemType = (itemType)3;
			destination.emojiIcon = source.emojiIcon;
			destination.itemVolume = source.itemVolume;
			destination.itemSecretShopType = source.itemSecretShopType;
			destination.colorPreset = source.colorPreset;
			destination.spawnRotationOffset = source.spawnRotationOffset;
			destination.physicalItem = source.physicalItem;
		}
	}
	internal static class GeneratorLevels
	{
		public static int TotalOwned()
		{
			PlayerUpgrade generatorUpgrade = Plugin.GeneratorUpgrade;
			if (generatorUpgrade == null)
			{
				return 0;
			}
			int num = 0;
			foreach (int value in generatorUpgrade.PlayerDictionary.Values)
			{
				num += Mathf.Max(0, value);
			}
			return num;
		}

		public static int TotalForPresentPlayers()
		{
			PlayerUpgrade generatorUpgrade = Plugin.GeneratorUpgrade;
			if (generatorUpgrade == null)
			{
				return 0;
			}
			int num = 0;
			HashSet<string> hashSet = new HashSet<string>();
			foreach (PlayerAvatar item in SemiFunc.PlayerGetAll())
			{
				if (!((Object)(object)item == (Object)null))
				{
					string text = SemiFunc.PlayerGetSteamID(item);
					if (!string.IsNullOrEmpty(text) && hashSet.Add(text))
					{
						num += Mathf.Max(0, generatorUpgrade.GetLevel(text));
					}
				}
			}
			return num;
		}
	}
	internal class GeneratorTicker : MonoBehaviour
	{
		internal static float PercentPerSecond;

		private float levelTimer;

		private int cachedLevels;

		private void Update()
		{
			if (!SemiFunc.RunIsLevel() || (Plugin.HostOnly.Value && !SemiFunc.IsMasterClientOrSingleplayer()))
			{
				PercentPerSecond = 0f;
				return;
			}
			levelTimer -= Time.unscaledDeltaTime;
			if (levelTimer <= 0f)
			{
				levelTimer = 1f;
				cachedLevels = GeneratorLevels.TotalForPresentPlayers();
			}
			PercentPerSecond = ((cachedLevels <= 0) ? 0f : (Plugin.RatePercentPerMinute.Value * (float)cachedLevels / 60f));
		}
	}
	internal sealed class GeneratorUpgradeBridge : MonoBehaviour
	{
		private static readonly FieldInfo UpgradeIdField = AccessTools.Field(typeof(REPOLibItemUpgrade), "_upgradeId");

		private void Awake()
		{
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			ItemUpgrade component = ((Component)this).GetComponent<ItemUpgrade>();
			REPOLibItemUpgrade component2 = ((Component)this).GetComponent<REPOLibItemUpgrade>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || UpgradeIdField == null)
			{
				Plugin.Log.LogError((object)"A spawned Generator box is missing its upgrade components.");
				return;
			}
			UpgradeIdField.SetValue(component2, "Generator");
			if (component.upgradeEvent == null)
			{
				component.upgradeEvent = new UnityEvent();
			}
			((UnityEventBase)component.upgradeEvent).RemoveAllListeners();
			component.upgradeEvent.AddListener(new UnityAction(component2.Upgrade));
		}
	}
	internal static class GeneratorVisuals
	{
		private const string BoxFile = "generator_box.png";

		private const string TargetTextureName = "Upgrade_Energy_Albedo";

		private const int TexSize = 512;

		private static Texture2D boxTexture;

		internal static void Apply(GameObject prefab)
		{
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Expected O, but got Unknown
			int num = 0;
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				bool flag = false;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val2 = sharedMaterials[j];
					if ((Object)(object)val2 == (Object)null || !val2.HasProperty("_MainTex"))
					{
						continue;
					}
					Texture texture = val2.GetTexture("_MainTex");
					if ((Object)(object)texture == (Object)null || ((Object)texture).name != "Upgrade_Energy_Albedo")
					{
						continue;
					}
					if (texture.width != 512 || texture.height != 512)
					{
						Plugin.Log.LogWarning((object)$"{((Object)texture).name} is {texture.width}x{texture.height}, expected {512}x{512}. The game may have changed it; keeping the vanilla look.");
						continue;
					}
					if ((Object)(object)boxTexture == (Object)null)
					{
						boxTexture = LoadBoxTexture(texture);
					}
					if (!((Object)(object)boxTexture == (Object)null))
					{
						Material val3 = new Material(val2)
						{
							name = ((Object)val2).name + " (Generator)"
						};
						val3.SetTexture("_MainTex", (Texture)(object)boxTexture);
						sharedMaterials[j] = val3;
						flag = true;
						num++;
					}
				}
				if (flag)
				{
					val.sharedMaterials = sharedMaterials;
				}
			}
			Plugin.Log.LogInfo((object)((num > 0) ? string.Format("Retextured {0} material(s) with {1}.", num, "generator_box.png") : "No material using 'Upgrade_Energy_Albedo' was found; keeping the vanilla look."));
		}

		private static Texture2D LoadBoxTexture(Texture like)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "generator_box.png");
			if (!File.Exists(text))
			{
				Plugin.Log.LogWarning((object)("generator_box.png not found next to the DLL (" + text + "). Keeping the vanilla look."));
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(text)))
			{
				Plugin.Log.LogWarning((object)"Could not decode generator_box.png.");
				return null;
			}
			if (((Texture)val).width != 512 || ((Texture)val).height != 512)
			{
				Plugin.Log.LogWarning((object)string.Format("{0} must be {1}x{2}, but is {3}x{4}.", "generator_box.png", 512, 512, ((Texture)val).width, ((Texture)val).height));
				return null;
			}
			((Object)val).name = "GeneratorBoxAlbedo";
			((Texture)val).wrapMode = like.wrapMode;
			((Texture)val).filterMode = like.filterMode;
			((Texture)val).anisoLevel = like.anisoLevel;
			((Object)val).hideFlags = (HideFlags)32;
			return val;
		}
	}
	[BepInPlugin("KimJongPoon.GeneratorMod", "GeneratorMod", "0.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "KimJongPoon.GeneratorMod";

		public const string Name = "GeneratorMod";

		public const string Version = "0.3.0";

		public const string UpgradeId = "Generator";

		public const float ShopValueMultiplier = 4f;

		internal static ManualLogSource Log;

		internal static PlayerUpgrade GeneratorUpgrade;

		internal static Item GeneratorItem;

		internal static ConfigEntry<int> BasePrice;

		internal static ConfigEntry<float> ShopChancePercent;

		internal static ConfigEntry<int> MaxPurchases;

		internal static ConfigEntry<bool> UseVanillaPriceScaling;

		internal static ConfigEntry<string> TemplateItemName;

		internal static ConfigEntry<float> RatePercentPerMinute;

		internal static ConfigEntry<bool> HostOnly;

		internal static ConfigEntry<int> MaxCharge;

		internal static ConfigEntry<bool> DebugLogging;

		private Harmony harmony;

		private void Awake()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Expected O, but got Unknown
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BasePrice = ((BaseUnityPlugin)this).Config.Bind<int>("Shop", "BasePrice", 25000, new ConfigDescription("Price of the Generator upgrade box in the shop (25000 = $25k).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1000, 5000000), Array.Empty<object>()));
			ShopChancePercent = ((BaseUnityPlugin)this).Config.Bind<float>("Shop", "ShopChancePercent", 10f, new ConfigDescription("Chance (in percent) that the Generator is added to the pool of upgrades for any one shop visit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			MaxPurchases = ((BaseUnityPlugin)this).Config.Bind<int>("Shop", "MaxPurchases", 1, new ConfigDescription("How many Generator levels the whole team can buy in total. Each level adds another RatePercentPerMinute.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			UseVanillaPriceScaling = ((BaseUnityPlugin)this).Config.Bind<bool>("Shop", "UseVanillaPriceScaling", false, "If false, the price is always exactly BasePrice. If true, the game's normal upgrade price scaling applies on top.");
			TemplateItemName = ((BaseUnityPlugin)this).Config.Bind<string>("Shop", "TemplateItemName", "Item Upgrade Player Energy", "Name of the vanilla upgrade item whose prefab (the box) is copied. The stamina upgrade is 'Energy' in the game's code.");
			RatePercentPerMinute = ((BaseUnityPlugin)this).Config.Bind<float>("Recharge", "RatePercentPerMinute", 3f, new ConfigDescription("Percent of a full truck energy bar restored per minute, per Generator level. Only ticks during active levels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			HostOnly = ((BaseUnityPlugin)this).Config.Bind<bool>("Recharge", "HostOnly", false, "If true, only the host (or singleplayer) applies the recharge. Leave false unless clients double-count in multiplayer.");
			MaxCharge = ((BaseUnityPlugin)this).Config.Bind<int>("Recharge", "MaxCharge", 100, "Value of ChargingStation.chargeTotal that means a full bar. Vanilla is 100.");
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "DebugLogging", false, "Log every shop roll and every recharge tick.");
			GeneratorItem = GeneratorItemFactory.CreateItemData();
			BasePrice.SettingChanged += delegate
			{
				GeneratorItemFactory.ApplyConfiguredValues(GeneratorItem);
			};
			MaxPurchases.SettingChanged += delegate
			{
				GeneratorItemFactory.ApplyConfiguredValues(GeneratorItem);
			};
			GeneratorUpgrade = Upgrades.RegisterUpgrade("Generator", GeneratorItem, (Action<PlayerAvatar, int>)null, (Action<PlayerAvatar, int>)null);
			if (GeneratorUpgrade == null)
			{
				Log.LogError((object)"Could not register REPOLib upgrade 'Generator'. GeneratorMod will not continue.");
				return;
			}
			harmony = new Harmony("KimJongPoon.GeneratorMod");
			harmony.PatchAll();
			GameObject val = new GameObject("GeneratorMod.Ticker")
			{
				hideFlags = (HideFlags)61
			};
			Object.DontDestroyOnLoad((Object)val);
			((MonoBehaviour)val.AddComponent<GeneratorTicker>()).StartCoroutine(GeneratorItemFactory.RegisterPrefabWhenReady());
			Log.LogInfo((object)"GeneratorMod 0.3.0 loaded. Waiting for the vanilla upgrade prefab to copy.");
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "GetAllItemsFromStatsManager")]
	internal static class ShopRollPatch
	{
		[HarmonyPrefix]
		private static void Prefix()
		{
			Item generatorItem = Plugin.GeneratorItem;
			if (!((Object)(object)generatorItem == (Object)null))
			{
				GeneratorItemFactory.ApplyConfiguredValues(generatorItem);
				int num = GeneratorLevels.TotalOwned();
				bool num2 = num < Plugin.MaxPurchases.Value;
				float num3 = Random.Range(0f, 100f);
				bool flag = num2 && num3 < Plugin.ShopChancePercent.Value;
				generatorItem.minPlayerCount = (flag ? 1 : 99);
				generatorItem.maxAmountInShop = (flag ? 1 : 0);
				if (Plugin.DebugLogging.Value)
				{
					Plugin.Log.LogInfo((object)$"Shop roll: {num3:0.0} vs {Plugin.ShopChancePercent.Value}% | owned {num}/{Plugin.MaxPurchases.Value} | offered = {flag}");
				}
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "UpgradeValueGet")]
	internal static class UpgradePricePatch
	{
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Prefix(Item item, ref float __result)
		{
			if ((Object)(object)item == (Object)null || ((Object)item).name != "Item Upgrade Player Generator")
			{
				return true;
			}
			if (Plugin.UseVanillaPriceScaling.Value)
			{
				return true;
			}
			__result = Plugin.BasePrice.Value;
			return false;
		}
	}
}