Decompiled source of HearthstoneMod v1.0.5

HearthstoneMod.dll

Decompiled a month ago
using System;
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 Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("HearthstoneMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HearthstoneMod")]
[assembly: AssemblyTitle("HearthstoneMod")]
[assembly: AssemblyVersion("1.0.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 HearthstoneMod
{
	public class HearthstoneBurstEffect : MonoBehaviour
	{
		private Light _light;

		private float _elapsed;

		private float _duration;

		private float _peakIntensity;

		private const float RiseFraction = 0.12f;

		public static void Spawn(Vector3 position, Color color, float peakIntensity = 14f, float duration = 0.9f)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: 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_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("HearthstoneBurst");
			val.transform.position = position;
			Light val2 = val.AddComponent<Light>();
			val2.type = (LightType)2;
			val2.color = color;
			val2.range = 8f;
			val2.shadows = (LightShadows)0;
			val2.intensity = 0f;
			HearthstoneBurstEffect hearthstoneBurstEffect = val.AddComponent<HearthstoneBurstEffect>();
			hearthstoneBurstEffect._light = val2;
			hearthstoneBurstEffect._duration = duration;
			hearthstoneBurstEffect._peakIntensity = peakIntensity;
		}

		private void Update()
		{
			_elapsed += Time.deltaTime;
			float num = Mathf.Clamp01(_elapsed / _duration);
			_light.intensity = ((num < 0.12f) ? Mathf.Lerp(0f, _peakIntensity, num / 0.12f) : Mathf.Lerp(_peakIntensity, 0f, (num - 0.12f) / 0.88f));
			if (_elapsed >= _duration)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
	[BepInPlugin("com.ricky.hearthstonemod", "HearthstoneMod", "1.0.5")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class HearthstonePlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.ricky.hearthstonemod";

		public const string PluginName = "HearthstoneMod";

		public const string PluginVersion = "1.0.5";

		public const string ItemPrefabName = "Hearthstone";

		internal static ManualLogSource LogInstance;

		public static ConfigEntry<float> CooldownSeconds;

		public static ConfigEntry<int> CostFineWood;

		public static ConfigEntry<int> CostLeatherScraps;

		public static ConfigEntry<int> CostGreydwarfEye;

		public static ConfigEntry<bool> RequireBedSpawnPoint;

		private void Awake()
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			LogInstance = ((BaseUnityPlugin)this).Logger;
			CooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "CooldownSeconds", 600f, "Seconds between Hearthstone uses (default 600 = 10 minutes).");
			CostFineWood = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "FineWood", 5, "Fine Wood required to craft a Hearthstone.");
			CostLeatherScraps = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "LeatherScraps", 5, "Leather Scraps required to craft a Hearthstone. Swapped in for Silver in 1.0.4 - Silver is a Mountain-tier material, way too late-game for a convenience item meant to be craftable early.");
			CostGreydwarfEye = ((BaseUnityPlugin)this).Config.Bind<int>("Recipe", "GreydwarfEye", 5, "Greydwarf Eye required to craft a Hearthstone.");
			RequireBedSpawnPoint = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RequireBedSpawnPoint", true, "If true, the Hearthstone refuses to activate until you've slept in / set a bed spawn point. Turn off only if you want it to work with no bed set (it then has nowhere to send you, so leave this on).");
			PrefabManager.OnVanillaPrefabsAvailable += AddHearthstoneItem;
			new Harmony("com.ricky.hearthstonemod").PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"HearthstoneMod v1.0.5 loaded.");
		}

		private void AddHearthstoneItem()
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: Expected O, but got Unknown
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Expected O, but got Unknown
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Expected O, but got Unknown
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Expected O, but got Unknown
			PrefabManager.OnVanillaPrefabsAvailable -= AddHearthstoneItem;
			GameObject val = PrefabManager.Instance.CreateClonedPrefab("Hearthstone", "AmberPearl");
			if ((Object)(object)val == (Object)null)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Failed to clone base prefab for Hearthstone - is Jotunn/game version compatible?");
				return;
			}
			SharedData shared = val.GetComponent<ItemDrop>().m_itemData.m_shared;
			shared.m_name = "$item_hearthstone";
			shared.m_description = "$item_hearthstone_desc";
			shared.m_maxStackSize = 1;
			shared.m_weight = 1f;
			shared.m_value = 0;
			shared.m_questItem = false;
			shared.m_teleportable = true;
			shared.m_itemType = (ItemType)2;
			string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "Assets", "hearthstone_icon.png");
			if (File.Exists(text))
			{
				Sprite val2 = AssetUtils.LoadSpriteFromFile(text);
				if ((Object)(object)val2 != (Object)null)
				{
					shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 };
				}
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Icon not found at " + text + "; item will use the cloned prefab's original icon."));
			}
			LocalizationManager.Instance.AddLocalization("English", new Dictionary<string, string>
			{
				["item_hearthstone"] = "Hearthstone",
				["item_hearthstone_desc"] = "A rune-carved stone bound to your hearth-fire.\nActivate to return to your bed instantly, gear and all.\n" + $"Cooldown: {CooldownSeconds.Value / 60f:0.#} minutes."
			});
			ItemConfig val3 = new ItemConfig();
			val3.Name = "$item_hearthstone";
			val3.Description = "$item_hearthstone_desc";
			val3.CraftingStation = CraftingStations.Workbench.ToString();
			val3.Requirements = (RequirementConfig[])(object)new RequirementConfig[3]
			{
				new RequirementConfig
				{
					Item = "FineWood",
					Amount = CostFineWood.Value
				},
				new RequirementConfig
				{
					Item = "LeatherScraps",
					Amount = CostLeatherScraps.Value
				},
				new RequirementConfig
				{
					Item = "GreydwarfEye",
					Amount = CostGreydwarfEye.Value
				}
			};
			ItemConfig val4 = val3;
			CustomItem val5 = new CustomItem(val, false, val4);
			ItemManager.Instance.AddItem(val5);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Hearthstone item + recipe registered.");
		}
	}
	[HarmonyPatch]
	public static class Humanoid_UseItem_HearthstonePatch
	{
		private const string CooldownDataKey = "hearthstone_last_use_utc_ticks";

		private static readonly Color HearthstoneBurstColor = new Color(1f, 0.55f, 0.15f);

		private static FieldInfo _teleportEffectsField;

		private static bool _teleportEffectsFieldResolved;

		[HarmonyTargetMethods]
		private static IEnumerable<MethodBase> TargetMethods()
		{
			Type[] paramTypes = new Type[3]
			{
				typeof(Inventory),
				typeof(ItemData),
				typeof(bool)
			};
			HashSet<MethodBase> seen = new HashSet<MethodBase>();
			Type[] array = new Type[2]
			{
				typeof(Humanoid),
				typeof(Player)
			};
			for (int i = 0; i < array.Length; i++)
			{
				MethodInfo methodInfo = AccessTools.Method(array[i], "UseItem", paramTypes, (Type[])null);
				if (methodInfo != null && seen.Add(methodInfo))
				{
					yield return methodInfo;
				}
			}
		}

		[HarmonyPrefix]
		public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			ManualLogSource logInstance = HearthstonePlugin.LogInstance;
			if (logInstance != null)
			{
				string[] obj = new string[6]
				{
					"[HearthstoneMod] UseItem prefix fired - instance=",
					((object)__instance)?.GetType().Name,
					", item=",
					item?.m_shared?.m_name,
					", dropPrefab=",
					null
				};
				object obj2;
				if (item == null)
				{
					obj2 = null;
				}
				else
				{
					GameObject dropPrefab = item.m_dropPrefab;
					obj2 = ((dropPrefab != null) ? ((Object)dropPrefab).name : null);
				}
				obj[5] = (string)obj2;
				logInstance.LogInfo((object)string.Concat(obj));
			}
			if ((Object)(object)item?.m_dropPrefab == (Object)null || ((Object)item.m_dropPrefab).name != "Hearthstone")
			{
				return true;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if (val == null || (Object)(object)val != (Object)(object)Player.m_localPlayer)
			{
				return true;
			}
			TryActivateHearthstone(val, item);
			return false;
		}

		private static bool TryActivateHearthstone(Player player, ItemData item)
		{
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (item.m_customData == null)
			{
				item.m_customData = new Dictionary<string, string>();
			}
			float value = HearthstonePlugin.CooldownSeconds.Value;
			if (item.m_customData.TryGetValue("hearthstone_last_use_utc_ticks", out var value2) && long.TryParse(value2, out var result))
			{
				double totalSeconds = (DateTime.UtcNow - new DateTime(result, DateTimeKind.Utc)).TotalSeconds;
				if (totalSeconds < (double)value)
				{
					double seconds = (double)value - totalSeconds;
					ShowMessage(player, "Hearthstone is still warming up (" + FormatRemaining(seconds) + " left).");
					return false;
				}
			}
			PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null);
			if (val == null)
			{
				ShowMessage(player, "Can't reach your player profile right now.");
				return false;
			}
			if (!val.HaveCustomSpawnPoint() && HearthstonePlugin.RequireBedSpawnPoint.Value)
			{
				ShowMessage(player, "You have no bed spawn point set - sleep in or claim a bed first.");
				return false;
			}
			Vector3 customSpawnPoint = val.GetCustomSpawnPoint();
			item.m_customData["hearthstone_last_use_utc_ticks"] = DateTime.UtcNow.Ticks.ToString();
			PlayTeleportEffect(player, ((Component)player).transform.position, ((Component)player).transform.rotation);
			Quaternion rotation = ((Component)player).transform.rotation;
			bool num = ((Character)player).TeleportTo(customSpawnPoint, rotation, true);
			if (num)
			{
				PlayTeleportEffect(player, customSpawnPoint, rotation);
				ShowMessage(player, "The hearth-fire pulls you home.");
				return num;
			}
			item.m_customData.Remove("hearthstone_last_use_utc_ticks");
			ShowMessage(player, "Something interrupted the teleport - try again.");
			return num;
		}

		private static void PlayTeleportEffect(Player player, Vector3 pos, Quaternion rot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			HearthstoneBurstEffect.Spawn(pos, HearthstoneBurstColor);
			if (!_teleportEffectsFieldResolved)
			{
				_teleportEffectsFieldResolved = true;
				_teleportEffectsField = typeof(Player).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((FieldInfo f) => f.FieldType == typeof(EffectList) && f.Name.IndexOf("eleport", StringComparison.OrdinalIgnoreCase) >= 0);
				if (_teleportEffectsField == null)
				{
					ManualLogSource logInstance = HearthstonePlugin.LogInstance;
					if (logInstance != null)
					{
						logInstance.LogWarning((object)"Couldn't find a teleport EffectList field on Player - using only our own burst effect (teleport itself still works fine either way).");
					}
				}
			}
			object? obj = _teleportEffectsField?.GetValue(player);
			EffectList val = (EffectList)((obj is EffectList) ? obj : null);
			if (val != null)
			{
				val.Create(pos, rot, (Transform)null, 1f, -1, default(ZDOID));
			}
		}

		private static void ShowMessage(Player player, string text)
		{
			((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false);
		}

		private static string FormatRemaining(double seconds)
		{
			TimeSpan timeSpan = TimeSpan.FromSeconds(seconds);
			if (!(timeSpan.TotalMinutes >= 1.0))
			{
				return $"{Mathf.CeilToInt((float)timeSpan.TotalSeconds)}s";
			}
			return $"{Mathf.CeilToInt((float)timeSpan.TotalMinutes)}m";
		}
	}
}