Decompiled source of GusterCrystalUpgrader v1.0.1

GusterCrystalUpgrader.dll

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

[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("GusterCrystalUpgrader")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("GusterCrystalUpgrader")]
[assembly: AssemblyTitle("GusterCrystalUpgrader")]
[assembly: AssemblyVersion("1.0.1.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 GusterCrystalUpgrader
{
	internal static class CrystalTierFactory
	{
		internal const string SmallId = "GusterSmallPowerCrystal";

		internal const string MediumId = "GusterMediumPowerCrystal";

		internal const string LargeId = "GusterLargePowerCrystal";

		internal const string SmallName = "Guster Small Crystal";

		internal const string MediumName = "Guster Medium Crystal";

		internal const string LargeName = "Guster Large Crystal";

		private static GameObject prefabRoot;

		internal static Item Small { get; private set; }

		internal static Item Medium { get; private set; }

		internal static Item Large { get; private set; }

		internal static IEnumerator RegisterWhenReady()
		{
			Item template = null;
			while ((Object)(object)template == (Object)null)
			{
				template = ((IEnumerable<Item>)Items.AllItems).FirstOrDefault((Func<Item, bool>)((Item item) => (Object)(object)item != (Object)null && ((Object)item).name == "Item Power Crystal" && item.prefab != null && (Object)(object)((PrefabRef<GameObject>)(object)item.prefab).Prefab != (Object)null));
				if ((Object)(object)template == (Object)null)
				{
					yield return (object)new WaitForSeconds(0.25f);
				}
			}
			prefabRoot = new GameObject("Guster Crystal Upgrader - Registered Crystal Prefabs");
			prefabRoot.SetActive(false);
			Object.DontDestroyOnLoad((Object)(object)prefabRoot);
			Small = Register(template, "GusterSmallPowerCrystal", "Guster Small Crystal", "A small vanilla crystal. Restores 100% energy.", 1750f, 2500f, 1f, Color.white);
			Medium = Register(template, "GusterMediumPowerCrystal", "Guster Medium Crystal", "A medium orange crystal. Restores 175% energy.", 3000f, 3750f, 1.14f, new Color(1f, 0.36f, 0.03f));
			Large = Register(template, "GusterLargePowerCrystal", "Guster Large Crystal", "A large red crystal. Restores 250% energy.", 5000f, 6250f, 1.3f, new Color(1f, 0.04f, 0.08f));
			Plugin.Log.LogInfo((object)"Registered small, medium, and large Guster power crystals.");
		}

		private static Item Register(Item template, string id, string displayName, string description, float rawMin, float rawMax, float size, Color tint)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			Item val = ScriptableObject.CreateInstance<Item>();
			((Object)val).name = id;
			val.itemName = displayName;
			val.description = description;
			val.status = (Status)1;
			val.disabled = false;
			val.itemType = (itemType)5;
			val.itemVolume = template.itemVolume;
			val.itemSecretShopType = template.itemSecretShopType;
			val.emojiIcon = template.emojiIcon;
			val.colorPreset = template.colorPreset;
			val.spawnRotationOffset = template.spawnRotationOffset;
			val.physicalItem = template.physicalItem;
			val.maxAmount = template.maxAmount;
			val.maxAmountInShop = 99;
			val.minPlayerCount = 1;
			val.value = ScriptableObject.CreateInstance<Value>();
			val.value.valueMin = rawMin;
			val.value.valueMax = rawMax;
			GameObject val2 = Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)template.prefab).Prefab, prefabRoot.transform, false);
			((Object)val2).name = id;
			ItemAttributes component = val2.GetComponent<ItemAttributes>();
			if ((Object)(object)component == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				Plugin.Log.LogError((object)("Vanilla Power Crystal prefab is missing ItemAttributes; could not register " + id + "."));
				return null;
			}
			component.item = val;
			val2.transform.localScale = val2.transform.localScale * size;
			if (size != 1f || tint != Color.white)
			{
				TintCrystal(val2, tint);
			}
			val.prefab = Items.RegisterItem(component);
			return val;
		}

		private static void TintCrystal(GameObject prefab, Color tint)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Material[] materials = componentsInChildren[i].materials;
				foreach (Material val in materials)
				{
					if (val.HasProperty("_BaseColor"))
					{
						val.SetColor("_BaseColor", tint);
					}
					if (val.HasProperty("_Color"))
					{
						val.SetColor("_Color", tint);
					}
					if (val.HasProperty("_EmissionColor"))
					{
						val.SetColor("_EmissionColor", tint * 1.3f);
					}
				}
			}
		}
	}
	[BepInPlugin("GusterStudios.GusterCrystalUpgrader", "Guster Crystal Upgrader", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Log;

		private Harmony harmony;

		private bool showShop;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("GusterStudios.GusterCrystalUpgrader");
			harmony.PatchAll(typeof(Plugin).Assembly);
			((MonoBehaviour)this).StartCoroutine(CrystalTierFactory.RegisterWhenReady());
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Guster Crystal Upgrader loaded. Press F7 in the truck shop to open the storage upgrade panel.");
		}

		private void Update()
		{
			if (Input.GetKeyDown((KeyCode)288) && SemiFunc.RunIsShop())
			{
				showShop = !showShop;
			}
		}

		private void OnGUI()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			if (!showShop || !SemiFunc.RunIsShop())
			{
				return;
			}
			StatsManager instance = StatsManager.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				int upgradeLevel = GetUpgradeLevel(instance.runStats);
				int num = PriceForNext(upgradeLevel);
				int runStatCurrency = instance.GetRunStatCurrency();
				GUI.Box(new Rect((float)(Screen.width - 390), (float)(Screen.height - 240), 360f, 205f), "GUSTER CRYSTAL UPGRADER");
				GUI.Label(new Rect((float)(Screen.width - 370), (float)(Screen.height - 205), 320f, 24f), "Crystal storage upgrade");
				GUI.Label(new Rect((float)(Screen.width - 370), (float)(Screen.height - 180), 320f, 24f), "Upgrade: " + upgradeLevel + " / 20");
				GUI.Label(new Rect((float)(Screen.width - 370), (float)(Screen.height - 155), 320f, 24f), "Capacity: " + (500 + upgradeLevel * 100) + "% (no free energy)");
				GUI.Label(new Rect((float)(Screen.width - 370), (float)(Screen.height - 130), 320f, 24f), "Team cash: $" + runStatCurrency + " | Next: $" + num);
				GUI.enabled = upgradeLevel < 20 && runStatCurrency >= num && SemiFunc.IsMasterClientOrSingleplayer();
				if (GUI.Button(new Rect((float)(Screen.width - 370), (float)(Screen.height - 95), 320f, 38f), (upgradeLevel >= 20) ? "MAXIMUM LEVEL" : "BUY +100% STORAGE"))
				{
					Purchase(instance, upgradeLevel, num);
				}
				GUI.enabled = true;
				if (GUI.Button(new Rect((float)(Screen.width - 370), (float)(Screen.height - 51), 320f, 25f), "Close (F7)"))
				{
					showShop = false;
				}
			}
		}

		private static int GetUpgradeLevel(Dictionary<string, int> stats)
		{
			if (stats == null || !stats.TryGetValue("gusterCrystalStorageUpgrades", out var value))
			{
				return 0;
			}
			return Mathf.Clamp(value, 0, 20);
		}

		private static int PriceForNext(int level)
		{
			return 10000 + level * 5000;
		}

		private static void Purchase(StatsManager stats, int level, int price)
		{
			if (!((Object)(object)stats == (Object)null) && level < 20 && stats.GetRunStatCurrency() >= price && SemiFunc.IsMasterClientOrSingleplayer())
			{
				SemiFunc.StatSetRunCurrency(stats.GetRunStatCurrency() - price);
				PunManager.instance.SetRunStatSet("gusterCrystalStorageUpgrades", level + 1);
				if ((Object)(object)ChargingStation.instance != (Object)null)
				{
					AccessTools.Field(typeof(ChargingStation), "maxCrystals")?.SetValue(ChargingStation.instance, 5 + level + 1);
				}
				Log.LogInfo((object)("Purchased crystal storage upgrade " + (level + 1) + " for $" + price + "."));
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "Start")]
	internal static class ChargingStationStartPatch
	{
		private static int savedCharge;

		private static void Prefix()
		{
			savedCharge = (((Object)(object)StatsManager.instance != (Object)null && StatsManager.instance.runStats != null && StatsManager.instance.runStats.TryGetValue("chargingStationChargeTotal", out var value)) ? value : 100);
		}

		private static void Postfix(ChargingStation __instance)
		{
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)StatsManager.instance == (Object)null))
			{
				int value;
				int num = ((StatsManager.instance.runStats != null && StatsManager.instance.runStats.TryGetValue("gusterCrystalStorageUpgrades", out value)) ? Mathf.Clamp(value, 0, 20) : 0);
				int num2 = 5 + num;
				AccessTools.Field(typeof(ChargingStation), "maxCrystals")?.SetValue(__instance, num2);
				int num3 = Mathf.Max(2, SemiFunc.StatGetItemsPurchased("Item Power Crystal"));
				int num4 = SemiFunc.StatGetItemsPurchased("GusterMediumPowerCrystal");
				int num5 = SemiFunc.StatGetItemsPurchased("GusterLargePowerCrystal");
				float num6 = (float)num3 + (float)num4 * 1.75f + (float)num5 * 2.5f;
				int num7 = (int)AccessTools.Field(typeof(ChargingStation), "energyPerCrystal").GetValue(__instance);
				int num8 = num2 * num7;
				int num9 = Mathf.RoundToInt(num6 * (float)num7);
				int num10 = Mathf.Clamp(savedCharge, 0, Mathf.Min(num8, num9));
				AccessTools.Field(typeof(ChargingStation), "chargeTotal")?.SetValue(__instance, num10);
				AccessTools.Field(typeof(ChargingStation), "chargeFloat")?.SetValue(__instance, (float)num10 / 100f);
				AccessTools.Field(typeof(ChargingStation), "chargeInt")?.SetValue(__instance, Mathf.CeilToInt(num6));
				AccessTools.Field(typeof(ChargingStation), "chargeScale")?.SetValue(__instance, (float)num10 / 100f);
				AccessTools.Field(typeof(ChargingStation), "chargeScaleTarget")?.SetValue(__instance, (float)num10 / 100f);
				AccessTools.Field(typeof(ChargingStation), "chargeSegmentCurrent")?.SetValue(__instance, Mathf.RoundToInt((float)num10 / 100f * (float)__instance.chargeSegments));
				Transform val = ((Component)__instance).transform.Find("Charge");
				if ((Object)(object)val != (Object)null)
				{
					Vector3 localScale = val.localScale;
					localScale.x = (float)num10 / 100f;
					val.localScale = localScale;
				}
				if (StatsManager.instance.runStats != null)
				{
					PunManager.instance.SetRunStatSet("chargingStationChargeTotal", num10);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ChargingStation), "ChargeItems")]
	internal static class ChargingStationCapacityPatch
	{
		private static void Postfix(ChargingStation __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				int num = (int)AccessTools.Field(typeof(ChargingStation), "maxCrystals").GetValue(__instance);
				int num2 = (int)AccessTools.Field(typeof(ChargingStation), "energyPerCrystal").GetValue(__instance);
				float num3 = (float)AccessTools.Field(typeof(ChargingStation), "chargeFloat").GetValue(__instance);
				AccessTools.Field(typeof(ChargingStation), "chargeTotal")?.SetValue(__instance, Mathf.Clamp(Mathf.RoundToInt(num3 * 100f), 0, num * num2));
			}
		}
	}
	[HarmonyPatch(typeof(ShopManager), "GetAllItemsFromStatsManager")]
	internal static class CrystalShopStockPatch
	{
		private static void Postfix(ShopManager __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !SemiFunc.IsNotMasterClient() && !((Object)(object)CrystalTierFactory.Small == (Object)null) && !((Object)(object)CrystalTierFactory.Medium == (Object)null) && !((Object)(object)CrystalTierFactory.Large == (Object)null))
			{
				__instance.potentialItemConsumables.RemoveAll((Item item) => (Object)(object)item != (Object)null && (((Object)item).name == "Item Power Crystal" || ((Object)item).name == "GusterSmallPowerCrystal" || ((Object)item).name == "GusterMediumPowerCrystal" || ((Object)item).name == "GusterLargePowerCrystal"));
				int num = Random.Range(2, 4);
				int num2 = Random.Range(1, 3);
				int num3 = Random.Range(1, 3);
				for (int num4 = 0; num4 < num; num4++)
				{
					__instance.potentialItemConsumables.Add(CrystalTierFactory.Small);
				}
				for (int num5 = 0; num5 < num2; num5++)
				{
					__instance.potentialItemConsumables.Add(CrystalTierFactory.Medium);
				}
				for (int num6 = 0; num6 < num3; num6++)
				{
					__instance.potentialItemConsumables.Add(CrystalTierFactory.Large);
				}
				__instance.itemConsumablesAmount = num + num2 + num3;
				for (int num7 = __instance.potentialItemConsumables.Count - 1; num7 > 0; num7--)
				{
					int index = Random.Range(0, num7 + 1);
					Item value = __instance.potentialItemConsumables[num7];
					__instance.potentialItemConsumables[num7] = __instance.potentialItemConsumables[index];
					__instance.potentialItemConsumables[index] = value;
				}
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "RunStartStats")]
	internal static class DefaultCrystalCountPatch
	{
		private static void Postfix(StatsManager __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				__instance.itemsPurchased["Item Power Crystal"] = Mathf.Max(2, __instance.itemsPurchased.TryGetValue("Item Power Crystal", out var value) ? value : 0);
				__instance.itemsPurchasedTotal["Item Power Crystal"] = Mathf.Max(2, __instance.itemsPurchasedTotal.TryGetValue("Item Power Crystal", out var value2) ? value2 : 0);
			}
		}
	}
	[HarmonyPatch(typeof(StatsManager), "ItemPurchase", new Type[] { typeof(string) })]
	internal static class CrystalPurchaseEnergyPatch
	{
		private static void Postfix(string itemName)
		{
			if (!((Object)(object)StatsManager.instance == (Object)null) && SemiFunc.IsMasterClientOrSingleplayer())
			{
				int num = itemName switch
				{
					"GusterLargePowerCrystal" => 25, 
					"GusterMediumPowerCrystal" => 18, 
					"GusterSmallPowerCrystal" => 10, 
					_ => 0, 
				};
				if (num > 0)
				{
					int value;
					int num2 = (StatsManager.instance.runStats.TryGetValue("gusterCrystalStorageUpgrades", out value) ? Mathf.Clamp(value, 0, 20) : 0);
					int num3 = (5 + num2) * 10;
					int value2;
					int num4 = (StatsManager.instance.runStats.TryGetValue("chargingStationChargeTotal", out value2) ? value2 : 0);
					PunManager.instance.SetRunStatSet("chargingStationChargeTotal", Mathf.Clamp(num4 + num, 0, num3));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemAttributes), "GetValue")]
	internal static class CrystalPricePatch
	{
		private static void Postfix(ItemAttributes __instance)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.item == (Object)null || (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient))
			{
				return;
			}
			int num;
			int num2;
			if (((Object)__instance.item).name == "GusterSmallPowerCrystal")
			{
				num = 7;
				num2 = 10;
			}
			else if (((Object)__instance.item).name == "GusterMediumPowerCrystal")
			{
				num = 12;
				num2 = 15;
			}
			else
			{
				if (!(((Object)__instance.item).name == "GusterLargePowerCrystal"))
				{
					return;
				}
				num = 20;
				num2 = 25;
			}
			int num3 = Random.Range(num, num2 + 1);
			AccessTools.Field(typeof(ItemAttributes), "value")?.SetValue(__instance, num3);
			object? obj = AccessTools.Field(typeof(ItemAttributes), "photonView")?.GetValue(__instance);
			PhotonView val = (PhotonView)((obj is PhotonView) ? obj : null);
			if (GameManager.Multiplayer() && (Object)(object)val != (Object)null && val.ViewID != 0)
			{
				val.RPC("GetValueRPC", (RpcTarget)1, new object[1] { num3 });
			}
		}
	}
}