Decompiled source of EtchedRunes v1.0.6

Orgetorix.EtchedRunes.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyTitle("Orgetorix.EtchedRunes")]
[assembly: AssemblyDescription("Etched Runestones for Epic Loot – Haldor shop")]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Orgetorix")]
[assembly: AssemblyProduct("Orgetorix.EtchedRunes")]
[assembly: AssemblyCopyright("Copyright © Orgetorix 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a1b2c3d4-e5f6-7890-abcd-ef1234567890")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyVersion("1.0.6.0")]
namespace Orgetorix.EtchedRunes
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("Orgetorix.EtchedRunes", "Orgetorix Etched Runes", "1.0.6")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class EtchedRunesPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "Orgetorix.EtchedRunes";

		public const string PluginName = "Orgetorix Etched Runes";

		public const string PluginVersion = "1.0.6";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("Orgetorix.EtchedRunes");
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			Log.LogInfo((object)"Orgetorix Etched Runes v1.0.6 loaded (waiting for prefabs).");
		}

		private void OnVanillaPrefabsAvailable()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			if (!ModConfig.Enabled.Value)
			{
				Log.LogInfo((object)"Mod disabled in config – skipping registration.");
				return;
			}
			RichesRuneManager.RegisterAll();
			LegendaryRuneManager.RegisterAll();
			Log.LogInfo((object)"Etched Runes registration finished.");
		}

		private void OnDestroy()
		{
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	public class RichesItemConfig
	{
		public string Label;

		public ConfigEntry<bool> Enabled;

		public ConfigEntry<string> Prefab;

		public ConfigEntry<string> Enchantment;

		public ConfigEntry<float> EnchantmentValue;

		public ConfigEntry<string> Rarity;

		public ConfigEntry<int> CoinsCost;

		public ConfigEntry<int> Stack;

		public ConfigEntry<bool> ApplyOnUse;

		public ConfigEntry<string> AllowedItemTypes;
	}
	public class LegendaryRuneDef
	{
		public string Key;

		public string SetName;

		public string Label;

		public ConfigEntry<bool> Enabled;

		public ConfigEntry<string> DisplayName;

		public ConfigEntry<string> LegendaryID;

		public ConfigEntry<string> AllowedItemTypes;

		public ConfigEntry<string> AllowedSkillTypes;

		public ConfigEntry<bool> RequireNoParryPower;

		public ConfigEntry<int> Price;

		public ConfigEntry<int> StackSize;

		public ConfigEntry<string> BasePrefab;

		public string PrefabName => "Orgetorix_LegRune_" + Key;
	}
	public static class ModConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<string> LogLevel;

		public static ConfigEntry<bool> RichesRunesEnabled;

		public static ConfigEntry<bool> LegendarySetRunesEnabled;

		public static ConfigEntry<bool> SetHeimdallEnabled;

		public static ConfigEntry<bool> SetRagnarEnabled;

		public static ConfigEntry<bool> SetGullveigEnabled;

		public static ConfigEntry<bool> SetHelEnabled;

		public static ConfigEntry<bool> SetUllrEnabled;

		public static ConfigEntry<bool> SetEirEnabled;

		public static ConfigEntry<bool> SetMimirEnabled;

		public static readonly List<RichesItemConfig> RichesItems = new List<RichesItemConfig>();

		public static readonly List<LegendaryRuneDef> LegendaryRunes = new List<LegendaryRuneDef>();

		public static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable or disable the entire mod");
			LogLevel = config.Bind<string>("General", "LogLevel", "Info", "Debug, Info, Warning, Error");
			RichesRunesEnabled = config.Bind<bool>("General", "Riches Runes", true, "Enable all Riches etched runestones in Haldor's shop");
			LegendarySetRunesEnabled = config.Bind<bool>("General", "Legendary Set Runes", true, "Enable all Legendary Set etched runes in Haldor's shop");
			SetHeimdallEnabled = config.Bind<bool>("General", "Set Heimdall", true, "Enable Heimdall set runes");
			SetRagnarEnabled = config.Bind<bool>("General", "Set Ragnar", true, "Enable Ragnar set runes");
			SetGullveigEnabled = config.Bind<bool>("General", "Set Gullveig", true, "Enable Gullveig set runes (More Set Items)");
			SetHelEnabled = config.Bind<bool>("General", "Set Hel", true, "Enable Hel set runes (More Set Items)");
			SetUllrEnabled = config.Bind<bool>("General", "Set Ullr", true, "Enable Ullr set runes (More Set Items)");
			SetEirEnabled = config.Bind<bool>("General", "Set Eir", true, "Enable Eir 2-piece runes (More Set Items)");
			SetMimirEnabled = config.Bind<bool>("General", "Set Mimir", true, "Enable Mimir 2-piece runes (More Set Items)");
			AddRiches(config, "01 Magic Runestone 10", "EtchedRunestoneMagic", "Riches", 10f, "Magic", 350, 1);
			AddRiches(config, "02 Magic Runestone 15", "EtchedRunestoneMagic", "Riches", 15f, "Magic", 500, 1);
			AddRiches(config, "03 Rare Runestone 20", "EtchedRunestoneRare", "Riches", 20f, "Rare", 800, 1);
			AddRiches(config, "04 Rare Runestone 25", "EtchedRunestoneRare", "Riches", 25f, "Rare", 1100, 1);
			AddRiches(config, "05 Epic Runestone 30", "EtchedRunestoneEpic", "Riches", 30f, "Epic", 1800, 1);
			AddRiches(config, "06 Epic Runestone 35", "EtchedRunestoneEpic", "Riches", 35f, "Epic", 2400, 1);
			AddRiches(config, "07 Legendary Runestone 40", "EtchedRunestoneLegendary", "Riches", 40f, "Legendary", 4000, 1);
			AddRiches(config, "08 Mythic Runestone 50", "EtchedRunestoneMythic", "Riches", 50f, "Mythic", 7500, 1);
			AddRiches(config, "09 Feather Fall Runestone", "EtchedRunestoneEpic", "FeatherFall", 1f, "Epic", 3500, 1);
			AddRiches(config, "10 Air Jump Runestone", "EtchedRunestoneEpic", "DoubleJump", 1f, "Epic", 3500, 1);
			AddLegendary(config, "01 Heimdall - Son of Nine Mothers", "Heimdall_SonOfNineMothers", "Heimdall", "Etched Rune: Son of Nine Mothers", "HeimdallHelmet", "Helmet", "", requireNoParry: false, 5000);
			AddLegendary(config, "02 Heimdall - Heart of the Bifrost", "Heimdall_HeartOfTheBifrost", "Heimdall", "Etched Rune: Heart of the Bifrost", "HeimdallChest", "Chest", "", requireNoParry: false, 5000);
			AddLegendary(config, "03 Heimdall - Stride of the Aesir", "Heimdall_StrideOfTheAesir", "Heimdall", "Etched Rune: Stride of the Aesir", "HeimdallLegs", "Legs", "", requireNoParry: false, 5000);
			AddLegendary(config, "04 Heimdall - Guardian of the Gods", "Heimdall_GuardianOfTheGods", "Heimdall", "Etched Rune: Guardian of the Gods", "HeimdallTowerShield", "Shield", "", requireNoParry: true, 5000);
			AddLegendary(config, "05 Ragnar - Serpentsbane", "Ragnar_Serpentsbane", "Ragnar", "Etched Rune: Serpentsbane", "RagnarBattleAxe", "TwoHandedWeapon", "Axes", requireNoParry: false, 5000);
			AddLegendary(config, "06 Ragnar - Ragnars White Shirt", "Ragnar_WhiteShirt", "Ragnar", "Etched Rune: Ragnar's White Shirt", "RagnarChest", "Chest", "", requireNoParry: false, 5000);
			AddLegendary(config, "07 Ragnar - Ragnars Ironsides", "Ragnar_Ironsides", "Ragnar", "Etched Rune: Ragnar's Ironsides", "RagnarLegs", "Legs", "", requireNoParry: false, 5000);
			AddLegendary(config, "08 Ragnar - Ragnars Boneless Wrap", "Ragnar_BonelessWrap", "Ragnar", "Etched Rune: Ragnar's Boneless Wrap", "RagnarCape", "Shoulder", "", requireNoParry: false, 5000);
			AddLegendary(config, "09 Gullveig - Staff of Three Winters", "Gullveig_Staff", "Gullveig", "Etched Rune: Staff of Three Winters", "GullveigStaff", "TwoHandedWeapon,TwoHandedWeaponLeft", "ElementalMagic", requireNoParry: false, 5000);
			AddLegendary(config, "10 Gullveig - Circlet of Cinders", "Gullveig_Helmet", "Gullveig", "Etched Rune: Circlet of Cinders", "GullveigHelmet", "Helmet", "", requireNoParry: false, 5000);
			AddLegendary(config, "11 Gullveig - Robe of the Wildfire", "Gullveig_Chest", "Gullveig", "Etched Rune: Robe of the Wildfire", "GullveigChest", "Chest", "", requireNoParry: false, 5000);
			AddLegendary(config, "12 Gullveig - Sash of the Storm", "Gullveig_Cape", "Gullveig", "Etched Rune: Sash of the Storm", "GullveigCape", "Shoulder", "", requireNoParry: false, 5000);
			AddLegendary(config, "13 Hel - Crook of the Dead", "Hel_Staff", "Hel", "Etched Rune: Crook of the Dead", "HelStaff", "TwoHandedWeapon,TwoHandedWeaponLeft", "BloodMagic", requireNoParry: false, 5000);
			AddLegendary(config, "14 Hel - Mask of the Barrow", "Hel_Helmet", "Hel", "Etched Rune: Mask of the Barrow", "HelHelmet", "Helmet", "", requireNoParry: false, 5000);
			AddLegendary(config, "15 Hel - Shroud of Helheim", "Hel_Chest", "Hel", "Etched Rune: Shroud of Helheim", "HelChest", "Chest", "", requireNoParry: false, 5000);
			AddLegendary(config, "16 Hel - Bindings of the Grave", "Hel_Legs", "Hel", "Etched Rune: Bindings of the Grave", "HelLegs", "Legs", "", requireNoParry: false, 5000);
			AddLegendary(config, "17 Ullr - Yew of Ullr", "Ullr_Bow", "Ullr", "Etched Rune: Yew of Ullr", "UllrBow", "Bow,Crossbow", "Bows,Crossbows", requireNoParry: false, 5000);
			AddLegendary(config, "18 Ullr - Hunters Hood", "Ullr_Helmet", "Ullr", "Etched Rune: Hunter's Hood", "UllrHelmet", "Helmet", "", requireNoParry: false, 5000);
			AddLegendary(config, "19 Ullr - Quiet Mail", "Ullr_Chest", "Ullr", "Etched Rune: Quiet Mail", "UllrChest", "Chest", "", requireNoParry: false, 5000);
			AddLegendary(config, "20 Ullr - Cloak of the Hunt", "Ullr_Cape", "Ullr", "Etched Rune: Cloak of the Hunt", "UllrCape", "Shoulder", "", requireNoParry: false, 5000);
			AddLegendary(config, "21 Eir - Eirs Mercy", "Eir_Mercy", "Eir", "Etched Rune: Eir's Mercy", "EirCharm", "Utility", "", requireNoParry: false, 2500);
			AddLegendary(config, "22 Eir - Eirs Reminder", "Eir_Reminder", "Eir", "Etched Rune: Eir's Reminder", "EirTrinket", "Utility", "", requireNoParry: false, 2500);
			AddLegendary(config, "23 Mimir - Mimirs Wellspring", "Mimir_Wellspring", "Mimir", "Etched Rune: Mimir's Wellspring", "MimirCharm", "Utility", "", requireNoParry: false, 2500);
			AddLegendary(config, "24 Mimir - Mimirs Debt", "Mimir_Debt", "Mimir", "Etched Rune: Mimir's Debt", "MimirTrinket", "Utility", "", requireNoParry: false, 2500);
		}

		private static void AddRiches(ConfigFile config, string label, string prefab, string enchant, float value, string rarity, int cost, int stack)
		{
			AddRiches(config, label, prefab, enchant, value, rarity, cost, stack, applyOnUse: false, "");
		}

		private static void AddRiches(ConfigFile config, string label, string prefab, string enchant, float value, string rarity, int cost, int stack, bool applyOnUse, string allowedTypes)
		{
			string text = label + " - ";
			RichesItemConfig richesItemConfig = new RichesItemConfig();
			richesItemConfig.Label = label;
			richesItemConfig.Enabled = config.Bind<bool>("Riches Runes", text + "Enabled", true, "Enable this runestone in Haldor's shop");
			richesItemConfig.Prefab = config.Bind<string>("Riches Runes", text + "Prefab", prefab, "Prefab to clone");
			richesItemConfig.Enchantment = config.Bind<string>("Riches Runes", text + "Enchantment", enchant, "Magic effect type");
			richesItemConfig.EnchantmentValue = config.Bind<float>("Riches Runes", text + "Enchantment Value", value, "Effect strength");
			richesItemConfig.Rarity = config.Bind<string>("Riches Runes", text + "Rarity", rarity, "Magic, Rare, Epic, Legendary, Mythic");
			richesItemConfig.CoinsCost = config.Bind<int>("Riches Runes", text + "Coins Cost", cost, "Coin price");
			richesItemConfig.Stack = config.Bind<int>("Riches Runes", text + "Stack", stack, "Stack per purchase");
			richesItemConfig.ApplyOnUse = config.Bind<bool>("Riches Runes", text + "ApplyOnUse", applyOnUse, "If true, use on inventory slot 1 instead of being a pre-etched item");
			richesItemConfig.AllowedItemTypes = config.Bind<string>("Riches Runes", text + "AllowedItemTypes", allowedTypes, "Allowed item types when ApplyOnUse is true");
			RichesItems.Add(richesItemConfig);
		}

		private static void AddLegendary(ConfigFile config, string label, string key, string setName, string displayName, string legendaryId, string allowedTypes, string allowedSkills, bool requireNoParry, int price)
		{
			string text = label + " - ";
			LegendaryRuneDef legendaryRuneDef = new LegendaryRuneDef();
			legendaryRuneDef.Key = key;
			legendaryRuneDef.SetName = setName;
			legendaryRuneDef.Label = label;
			legendaryRuneDef.Enabled = config.Bind<bool>("Legendary Sets", text + "Enabled", true, "Enable this rune in Haldor's shop");
			legendaryRuneDef.DisplayName = config.Bind<string>("Legendary Sets", text + "DisplayName", displayName, "In-game display name");
			legendaryRuneDef.LegendaryID = config.Bind<string>("Legendary Sets", text + "LegendaryID", legendaryId, "Epic Loot Legendary ID");
			legendaryRuneDef.AllowedItemTypes = config.Bind<string>("Legendary Sets", text + "AllowedItemTypes", allowedTypes, "Allowed item types");
			legendaryRuneDef.AllowedSkillTypes = config.Bind<string>("Legendary Sets", text + "AllowedSkillTypes", allowedSkills, "Allowed skill types");
			legendaryRuneDef.RequireNoParryPower = config.Bind<bool>("Legendary Sets", text + "RequireNoParryPower", requireNoParry, "Tower shield only (no parry)");
			legendaryRuneDef.Price = config.Bind<int>("Legendary Sets", text + "Price", price, "Coin price at Haldor");
			legendaryRuneDef.StackSize = config.Bind<int>("Legendary Sets", text + "StackSize", 1, "Stack size");
			legendaryRuneDef.BasePrefab = config.Bind<string>("Legendary Sets", text + "BasePrefab", "EtchedRunestoneLegendary", "Prefab to clone");
			LegendaryRunes.Add(legendaryRuneDef);
		}

		public static bool IsRichesEnabled(RichesItemConfig c)
		{
			if (Enabled.Value && RichesRunesEnabled.Value)
			{
				return c.Enabled.Value;
			}
			return false;
		}

		public static bool IsLegendaryEnabled(LegendaryRuneDef def)
		{
			if (!Enabled.Value || !LegendarySetRunesEnabled.Value || !def.Enabled.Value)
			{
				return false;
			}
			if (def.SetName == "Heimdall" && !SetHeimdallEnabled.Value)
			{
				return false;
			}
			if (def.SetName == "Ragnar" && !SetRagnarEnabled.Value)
			{
				return false;
			}
			if (def.SetName == "Gullveig" && !SetGullveigEnabled.Value)
			{
				return false;
			}
			if (def.SetName == "Hel" && !SetHelEnabled.Value)
			{
				return false;
			}
			if (def.SetName == "Ullr" && !SetUllrEnabled.Value)
			{
				return false;
			}
			if (def.SetName == "Eir" && !SetEirEnabled.Value)
			{
				return false;
			}
			if (def.SetName == "Mimir" && !SetMimirEnabled.Value)
			{
				return false;
			}
			return true;
		}
	}
	public static class RichesRuneManager
	{
		public static readonly Dictionary<string, RichesItemConfig> Registered = new Dictionary<string, RichesItemConfig>();

		private static ManualLogSource Logger => EtchedRunesPlugin.Log;

		public static void RegisterAll()
		{
			int num = 0;
			foreach (RichesItemConfig richesItem in ModConfig.RichesItems)
			{
				if (ModConfig.IsRichesEnabled(richesItem))
				{
					num++;
					try
					{
						RegisterOne(richesItem, num);
					}
					catch (Exception ex)
					{
						Logger.LogError((object)("Riches rune register failed (" + richesItem.Label + "): " + ex));
					}
				}
			}
		}

		private static void RegisterOne(RichesItemConfig cfg, int index)
		{
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Expected O, but got Unknown
			string text = cfg.Prefab.Value;
			GameObject prefab = PrefabManager.Instance.GetPrefab(text);
			if ((Object)(object)prefab == (Object)null)
			{
				string[] array = new string[5] { "EtchedRunestoneMagic", "EtchedRunestoneRare", "EtchedRunestoneEpic", "EtchedRunestoneLegendary", "EtchedRunestoneMythic" };
				for (int i = 0; i < array.Length; i++)
				{
					prefab = PrefabManager.Instance.GetPrefab(array[i]);
					if ((Object)(object)prefab != (Object)null)
					{
						Logger.LogWarning((object)("Riches base prefab '" + text + "' missing, fallback: " + array[i]));
						text = array[i];
						break;
					}
				}
			}
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogError((object)("No base prefab for Riches item " + cfg.Label + " – skipped."));
				return;
			}
			string text2 = text + "_Orge_" + index;
			string text3 = DisplayEffectName(cfg.Enchantment.Value);
			ItemConfig val = new ItemConfig();
			val.Description = "Pre-etched: " + text3 + (IsNumericEffect(cfg.Enchantment.Value) ? (" " + cfg.EnchantmentValue.Value) : "") + " [" + cfg.Rarity.Value + "]. Use at the Enchanting Table.";
			CustomItem val2 = new CustomItem(text2, text, val);
			ItemManager.Instance.AddItem(val2);
			Registered[text2] = cfg;
			Logger.LogInfo((object)("Registered etched runestone: " + text2 + " -> " + text3 + " " + cfg.EnchantmentValue.Value));
			GameObject prefab2 = PrefabManager.Instance.GetPrefab(text2);
			if ((Object)(object)prefab2 != (Object)null)
			{
				ItemDrop component = prefab2.GetComponent<ItemDrop>();
				if ((Object)(object)component != (Object)null && component.m_itemData != null)
				{
					component.m_itemData.m_dropPrefab = prefab2;
					ApplyEtchedMagic(component.m_itemData, cfg);
				}
			}
		}

		public static void TryApplyMagicData(ItemData item)
		{
			if (item == null)
			{
				return;
			}
			if (ShouldStripIllegalMagic(item))
			{
				StripMagic(item);
			}
			else if (IsOurShopRune(item))
			{
				RichesItemConfig richesItemConfig = FindConfig(item);
				if (richesItemConfig != null && !AlreadyHasEtchedEffect(item, richesItemConfig))
				{
					ApplyEtchedMagic(item, richesItemConfig);
				}
			}
		}

		public static bool IsOurShopRune(ItemData item)
		{
			string prefabName = GetPrefabName(item);
			if (string.IsNullOrEmpty(prefabName))
			{
				return false;
			}
			if (prefabName.IndexOf("_Orge_", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return false;
			}
			return Registered.ContainsKey(prefabName);
		}

		private static string GetPrefabName(ItemData item)
		{
			if (item == null)
			{
				return null;
			}
			string text = null;
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				text = ((Object)item.m_dropPrefab).name;
			}
			if (string.IsNullOrEmpty(text) && item.m_shared != null)
			{
				text = item.m_shared.m_name;
			}
			if (string.IsNullOrEmpty(text))
			{
				return null;
			}
			return text.Replace("(Clone)", "").Trim();
		}

		private static bool ShouldStripIllegalMagic(ItemData item)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Invalid comparison between Unknown and I4
			string prefabName = GetPrefabName(item);
			if (string.IsNullOrEmpty(prefabName))
			{
				return false;
			}
			if (prefabName.IndexOf("_Orge_", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			if (prefabName.IndexOf("Orgetorix_LegRune", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			if (prefabName.IndexOf("Runestone", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			if (prefabName.IndexOf("EtchedRune", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return false;
			}
			bool flag = prefabName.Equals("Stone", StringComparison.OrdinalIgnoreCase) || prefabName.Equals("$item_stone", StringComparison.OrdinalIgnoreCase);
			bool flag2 = item.m_shared != null && (int)item.m_shared.m_itemType == 1;
			if (!flag && !flag2)
			{
				return false;
			}
			return ItemLooksMagic(item);
		}

		private static bool ItemLooksMagic(ItemData item)
		{
			try
			{
				Type type = FindType("EpicLoot.API");
				if (type == null)
				{
					return false;
				}
				MethodInfo methodInfo = type.GetMethod("IsMagicItem", BindingFlags.Static | BindingFlags.Public) ?? type.GetMethod("IsEpicLootItem", BindingFlags.Static | BindingFlags.Public);
				if (methodInfo != null)
				{
					object obj = methodInfo.Invoke(null, new object[1] { item });
					if (obj is bool && (bool)obj)
					{
						return true;
					}
				}
				MethodInfo method = type.GetMethod("GetMagicItemJson", BindingFlags.Static | BindingFlags.Public);
				if (method != null)
				{
					string text = method.Invoke(null, new object[1] { item }) as string;
					if (!string.IsNullOrEmpty(text) && text.IndexOf("EffectType", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static void StripMagic(ItemData item)
		{
			try
			{
				Type type = FindType("EpicLoot.ItemDataExtensions");
				if (type != null)
				{
					string[] array = new string[4] { "RemoveMagicItem", "ClearMagicItem", "DeleteMagicItem", "MakeNonMagic" };
					for (int i = 0; i < array.Length; i++)
					{
						MethodInfo method = type.GetMethod(array[i], BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
						if (!(method == null))
						{
							try
							{
								method.Invoke(null, new object[1] { item });
								Logger.LogInfo((object)("Stripped illegal magic via " + array[i] + " from " + GetPrefabName(item)));
								return;
							}
							catch
							{
							}
						}
					}
					MethodInfo method2 = type.GetMethod("SaveMagicItem", BindingFlags.Static | BindingFlags.Public);
					if (method2 != null)
					{
						try
						{
							method2.Invoke(null, new object[2] { item, null });
							Logger.LogInfo((object)("Stripped illegal magic via SaveMagicItem(null) from " + GetPrefabName(item)));
							return;
						}
						catch
						{
						}
					}
				}
				Type type2 = FindType("EpicLoot.API");
				if (type2 != null)
				{
					MethodInfo method3 = type2.GetMethod("ApplyMagicItemJson", BindingFlags.Static | BindingFlags.Public);
					if (method3 != null)
					{
						method3.Invoke(null, new object[2] { item, "" });
						Logger.LogInfo((object)("Stripped illegal magic via empty JSON from " + GetPrefabName(item)));
					}
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("StripMagic failed: " + ex.Message));
			}
		}

		private static bool AlreadyHasEtchedEffect(ItemData item, RichesItemConfig cfg)
		{
			string text = ResolveEffectType(cfg.Enchantment.Value);
			try
			{
				Type type = FindType("EpicLoot.API");
				if (type == null)
				{
					return false;
				}
				MethodInfo method = type.GetMethod("ItemHasMagicEffect", BindingFlags.Static | BindingFlags.Public);
				if (method != null)
				{
					object obj = method.Invoke(null, new object[3] { item, text, true });
					if (obj is bool && (bool)obj)
					{
						return true;
					}
				}
				MethodInfo method2 = type.GetMethod("GetMagicItemJson", BindingFlags.Static | BindingFlags.Public);
				if (method2 != null)
				{
					string text2 = method2.Invoke(null, new object[1] { item }) as string;
					if (!string.IsNullOrEmpty(text2) && text2.IndexOf("\"EffectType\":\"" + text + "\"") >= 0)
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static RichesItemConfig FindConfig(ItemData item)
		{
			string[] array = new string[2];
			if ((Object)(object)item.m_dropPrefab != (Object)null)
			{
				array[0] = ((Object)item.m_dropPrefab).name;
			}
			if (item.m_shared != null)
			{
				array[1] = item.m_shared.m_name;
			}
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i];
				if (!string.IsNullOrEmpty(text))
				{
					text = text.Replace("(Clone)", "").Trim();
					if (Registered.TryGetValue(text, out var value))
					{
						return value;
					}
				}
			}
			return null;
		}

		private static void ApplyEtchedMagic(ItemData item, RichesItemConfig cfg)
		{
			try
			{
				string text = ResolveEffectType(cfg.Enchantment.Value);
				float value = cfg.EnchantmentValue.Value;
				string value2 = cfg.Rarity.Value;
				if (!TryApplyViaApiJson(item, text, value, value2) && !TryApplyMagicToItemData(item, text, value, value2) && !TrySaveMagicItem(item, text, value, value2))
				{
					Logger.LogWarning((object)("Could not apply etched magic for " + text + " / " + cfg.Label));
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("ApplyEtchedMagic failed: " + ex.Message));
			}
		}

		private static bool TryApplyViaApiJson(ItemData item, string effectType, float value, string rarityName)
		{
			Type type = FindType("EpicLoot.API");
			if (type == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("ApplyMagicItemJson", BindingFlags.Static | BindingFlags.Public);
			if (method == null)
			{
				return false;
			}
			int num = RarityToInt(rarityName);
			string text = "{\"Version\":3,\"Rarity\":" + num + ",\"Effects\":[{\"Version\":1,\"EffectValue\":" + value.ToString(CultureInfo.InvariantCulture) + ",\"EffectType\":\"" + effectType + "\"}],\"TypeNameOverride\":null,\"LegendaryID\":null,\"SetID\":null,\"IsUnidentified\":false,\"SocketCount\":0,\"Sockets\":[]}";
			object obj = method.Invoke(null, new object[2] { item, text });
			bool flag = !(obj is bool) || (bool)obj;
			if (!flag)
			{
				Logger.LogWarning((object)("ApplyMagicItemJson returned false for " + effectType));
			}
			return flag;
		}

		private static int RarityToInt(string rarity)
		{
			if (string.IsNullOrEmpty(rarity))
			{
				return 0;
			}
			return rarity.Trim().ToLowerInvariant() switch
			{
				"rare" => 1, 
				"epic" => 2, 
				"legendary" => 3, 
				"mythic" => 4, 
				_ => 0, 
			};
		}

		private static bool TryApplyMagicToItemData(ItemData item, string effectType, float value, string rarityName)
		{
			Type type = FindType("EpicLoot.ItemDataExtensions");
			if (type == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("ApplyMagicToItemData", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				return false;
			}
			ParameterInfo[] parameters = method.GetParameters();
			object[] array = new object[parameters.Length];
			for (int i = 0; i < parameters.Length; i++)
			{
				Type parameterType = parameters[i].ParameterType;
				string text = ((parameters[i].Name != null) ? parameters[i].Name.ToLowerInvariant() : "");
				if (parameterType.Name.IndexOf("ItemData") >= 0)
				{
					array[i] = item;
				}
				else if (parameterType == typeof(string) && (text.IndexOf("effect") >= 0 || text.IndexOf("type") >= 0))
				{
					array[i] = effectType;
				}
				else if (parameterType == typeof(string) && text.IndexOf("rarity") >= 0)
				{
					array[i] = rarityName;
				}
				else if (parameterType == typeof(float) || parameterType == typeof(double) || parameterType == typeof(int))
				{
					if (parameterType == typeof(int))
					{
						array[i] = Mathf.RoundToInt(value);
					}
					else if (parameterType == typeof(double))
					{
						array[i] = (double)value;
					}
					else
					{
						array[i] = value;
					}
				}
				else if (parameterType.IsEnum && parameterType.Name.IndexOf("Rarity") >= 0)
				{
					array[i] = ParseEnum(parameterType, rarityName);
				}
				else if (parameterType.IsEnum)
				{
					array[i] = ParseEnum(parameterType, effectType);
				}
				else
				{
					array[i] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null);
				}
			}
			method.Invoke(null, array);
			Logger.LogInfo((object)("ApplyMagicToItemData OK: " + effectType));
			return true;
		}

		private static bool TrySaveMagicItem(ItemData item, string effectType, float value, string rarityName)
		{
			Type type = FindType("EpicLoot.ItemDataExtensions");
			Type type2 = FindType("EpicLoot.MagicItem");
			Type effectClrType = FindType("EpicLoot.MagicItemEffect");
			if (type == null || type2 == null)
			{
				return false;
			}
			MethodInfo method = type.GetMethod("GetMagicItem", BindingFlags.Static | BindingFlags.Public);
			MethodInfo method2 = type.GetMethod("SaveMagicItem", BindingFlags.Static | BindingFlags.Public);
			MethodInfo method3 = type.GetMethod("SetNumericEffectValue", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			object obj = null;
			if (method != null)
			{
				try
				{
					obj = method.Invoke(null, new object[1] { item });
				}
				catch
				{
				}
			}
			if (obj == null)
			{
				obj = Activator.CreateInstance(type2);
			}
			PropertyInfo property = type2.GetProperty("Rarity");
			if (property != null)
			{
				object obj3 = ParseEnum(property.PropertyType, rarityName);
				if (obj3 != null)
				{
					property.SetValue(obj, obj3, null);
				}
			}
			EnsureEffectOnMagicItem(obj, effectClrType, effectType, value);
			if (method3 != null && IsNumericEffect(effectType))
			{
				try
				{
					method3.Invoke(null, new object[3] { item, effectType, value });
				}
				catch
				{
					try
					{
						method3.Invoke(null, new object[3] { obj, effectType, value });
					}
					catch
					{
					}
				}
			}
			if (method2 != null)
			{
				method2.Invoke(null, new object[2] { item, obj });
				Logger.LogInfo((object)("SaveMagicItem OK: " + effectType));
				return true;
			}
			return false;
		}

		private static void EnsureEffectOnMagicItem(object magicItem, Type effectClrType, string effectType, float value)
		{
			if (magicItem == null)
			{
				return;
			}
			PropertyInfo property = magicItem.GetType().GetProperty("Effects");
			if (property == null)
			{
				return;
			}
			object value2 = property.GetValue(magicItem, null);
			if (value2 == null)
			{
				return;
			}
			PropertyInfo property2 = value2.GetType().GetProperty("Count");
			int num = 0;
			if (property2 != null)
			{
				num = (int)property2.GetValue(value2, null);
			}
			MethodInfo method = value2.GetType().GetMethod("get_Item", new Type[1] { typeof(int) });
			if (method != null)
			{
				for (int i = 0; i < num; i++)
				{
					object obj = method.Invoke(value2, new object[1] { i });
					if (obj != null)
					{
						string effectTypeName = GetEffectTypeName(obj);
						if (effectTypeName == effectType)
						{
							SetEffectValue(obj, value);
							return;
						}
					}
				}
			}
			object obj2 = CreateMagicItemEffect(effectClrType, effectType, value);
			if (obj2 != null)
			{
				MethodInfo method2 = value2.GetType().GetMethod("Add");
				if (method2 != null)
				{
					method2.Invoke(value2, new object[1] { obj2 });
				}
			}
		}

		private static object CreateMagicItemEffect(Type effectClrType, string effectType, float value)
		{
			if (effectClrType == null)
			{
				effectClrType = FindType("EpicLoot.MagicItemEffect");
			}
			if (effectClrType == null)
			{
				return null;
			}
			object obj = null;
			try
			{
				obj = Activator.CreateInstance(effectClrType);
			}
			catch
			{
				return null;
			}
			PropertyInfo property = effectClrType.GetProperty("EffectType");
			if (property != null)
			{
				if (property.PropertyType == typeof(string))
				{
					property.SetValue(obj, effectType, null);
				}
				else if (property.PropertyType.IsEnum)
				{
					object obj3 = ParseEnum(property.PropertyType, effectType);
					if (obj3 != null)
					{
						property.SetValue(obj, obj3, null);
					}
				}
			}
			FieldInfo field = effectClrType.GetField("EffectType");
			if (field != null && field.FieldType == typeof(string))
			{
				field.SetValue(obj, effectType);
			}
			SetEffectValue(obj, value);
			return obj;
		}

		private static void SetEffectValue(object effect, float value)
		{
			if (effect == null)
			{
				return;
			}
			PropertyInfo property = effect.GetType().GetProperty("EffectValue");
			if (property != null && property.CanWrite)
			{
				if (property.PropertyType == typeof(float))
				{
					property.SetValue(effect, value, null);
				}
				else if (property.PropertyType == typeof(double))
				{
					property.SetValue(effect, (double)value, null);
				}
				else if (property.PropertyType == typeof(int))
				{
					property.SetValue(effect, Mathf.RoundToInt(value), null);
				}
			}
			FieldInfo field = effect.GetType().GetField("EffectValue");
			if (field != null)
			{
				if (field.FieldType == typeof(float))
				{
					field.SetValue(effect, value);
				}
				else if (field.FieldType == typeof(double))
				{
					field.SetValue(effect, (double)value);
				}
			}
		}

		private static string GetEffectTypeName(object effect)
		{
			if (effect == null)
			{
				return null;
			}
			PropertyInfo property = effect.GetType().GetProperty("EffectType");
			if (property != null)
			{
				object value = property.GetValue(effect, null);
				if (value != null)
				{
					return value.ToString();
				}
			}
			FieldInfo field = effect.GetType().GetField("EffectType");
			if (field != null)
			{
				object value2 = field.GetValue(effect);
				if (value2 != null)
				{
					return value2.ToString();
				}
			}
			return null;
		}

		private static string ResolveEffectType(string configured)
		{
			if (string.IsNullOrEmpty(configured))
			{
				return "Riches";
			}
			string text = configured.Trim();
			if (text.Equals("Air Jump", StringComparison.OrdinalIgnoreCase) || text.Equals("AirJump", StringComparison.OrdinalIgnoreCase))
			{
				return "DoubleJump";
			}
			if (text.Equals("Feather Fall", StringComparison.OrdinalIgnoreCase))
			{
				return "FeatherFall";
			}
			return text;
		}

		private static string DisplayEffectName(string effectType)
		{
			string text = ResolveEffectType(effectType);
			if (text == "DoubleJump")
			{
				return "Air Jump";
			}
			if (text == "FeatherFall")
			{
				return "Feather Fall";
			}
			return text;
		}

		private static bool IsNumericEffect(string effectType)
		{
			string text = ResolveEffectType(effectType);
			return text == "Riches";
		}

		private static Type FindType(string fullName)
		{
			Type type = Type.GetType(fullName + ", EpicLoot");
			if (type != null)
			{
				return type;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				try
				{
					if (!(assemblies[i].GetName().Name != "EpicLoot"))
					{
						type = assemblies[i].GetType(fullName);
						if (type != null)
						{
							return type;
						}
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private static object ParseEnum(Type enumType, string name)
		{
			if (enumType == null || !enumType.IsEnum || string.IsNullOrEmpty(name))
			{
				return null;
			}
			try
			{
				return Enum.Parse(enumType, name, ignoreCase: true);
			}
			catch
			{
				return null;
			}
		}
	}
	public static class LegendaryRuneManager
	{
		private static readonly Dictionary<string, LegendaryRuneDef> PrefabToRune = new Dictionary<string, LegendaryRuneDef>();

		private static ManualLogSource Logger => EtchedRunesPlugin.Log;

		public static void RegisterAll()
		{
			if (!ModConfig.Enabled.Value)
			{
				return;
			}
			foreach (LegendaryRuneDef legendaryRune in ModConfig.LegendaryRunes)
			{
				if (ModConfig.IsLegendaryEnabled(legendaryRune))
				{
					try
					{
						RegisterSingleRune(legendaryRune);
					}
					catch (Exception ex)
					{
						Logger.LogError((object)("Failed to register rune " + legendaryRune.Key + ": " + ex));
					}
				}
			}
		}

		private static void RegisterSingleRune(LegendaryRuneDef def)
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Expected O, but got Unknown
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			string text = def.BasePrefab.Value;
			if (string.IsNullOrEmpty(text))
			{
				text = "EtchedRunestoneLegendary";
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab(text);
			if ((Object)(object)prefab == (Object)null)
			{
				string[] array = new string[5] { "EtchedRunestoneLegendary", "EtchedRunestoneEpic", "EtchedRunestoneRare", "EtchedRunestoneMagic", "SwordBronze" };
				for (int i = 0; i < array.Length; i++)
				{
					prefab = PrefabManager.Instance.GetPrefab(array[i]);
					if ((Object)(object)prefab != (Object)null)
					{
						text = array[i];
						Logger.LogWarning((object)("Base prefab missing, using fallback: " + text + " for " + def.Key));
						break;
					}
				}
			}
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogError((object)("No base prefab found for legendary rune " + def.Key + " – skipped."));
				return;
			}
			ItemConfig val = new ItemConfig();
			val.Name = def.DisplayName.Value;
			val.Description = "Apply this rune to a matching item to turn it into the Legendary Set piece.\nLegendary ID: " + def.LegendaryID.Value;
			CustomItem val2 = new CustomItem(def.PrefabName, text, val);
			ItemManager.Instance.AddItem(val2);
			PrefabToRune[def.PrefabName] = def;
			Logger.LogInfo((object)("Registered etched rune: " + def.DisplayName.Value + " (" + def.PrefabName + ") -> " + def.LegendaryID.Value));
		}

		public static LegendaryRuneDef GetRuneByPrefab(string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return null;
			}
			if (PrefabToRune.TryGetValue(prefabName, out var value))
			{
				return value;
			}
			return null;
		}

		public static LegendaryRuneDef GetRuneByItemData(ItemData item)
		{
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				return null;
			}
			return GetRuneByPrefab(((Object)item.m_dropPrefab).name);
		}

		public static bool IsEtchedRune(ItemData item)
		{
			return GetRuneByItemData(item) != null;
		}

		public static bool CanApplyTo(LegendaryRuneDef rune, ItemData target)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			if (rune == null || target == null || target.m_shared == null)
			{
				return false;
			}
			SharedData shared = target.m_shared;
			string text = rune.AllowedItemTypes.Value;
			if (text == null)
			{
				text = "";
			}
			if (!string.IsNullOrEmpty(text))
			{
				string[] array = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				bool flag = false;
				for (int i = 0; i < array.Length; i++)
				{
					string value = array[i].Trim();
					if (Enum.TryParse<ItemType>(value, ignoreCase: true, out ItemType result) && shared.m_itemType == result)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					return false;
				}
			}
			string text2 = rune.AllowedSkillTypes.Value;
			if (text2 == null)
			{
				text2 = "";
			}
			if (!string.IsNullOrEmpty(text2))
			{
				string[] array2 = text2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				bool flag2 = false;
				for (int j = 0; j < array2.Length; j++)
				{
					string value2 = array2[j].Trim();
					if (Enum.TryParse<SkillType>(value2, ignoreCase: true, out SkillType result2) && shared.m_skillType == result2)
					{
						flag2 = true;
						break;
					}
				}
				if (!flag2)
				{
					return false;
				}
			}
			if (rune.RequireNoParryPower.Value && shared.m_timedBlockBonus > 1.01f)
			{
				return false;
			}
			return true;
		}

		public static bool TryApplyRune(LegendaryRuneDef rune, ItemData target, out string message)
		{
			message = "";
			if (!CanApplyTo(rune, target))
			{
				message = "This rune cannot be applied to that item.";
				return false;
			}
			string value = rune.LegendaryID.Value;
			if (string.IsNullOrEmpty(value))
			{
				message = "Rune has no LegendaryID configured.";
				return false;
			}
			try
			{
				if (ApplyLegendaryViaReflection(target, value))
				{
					message = "Successfully etched: " + rune.DisplayName.Value;
					Logger.LogInfo((object)("Applied " + value + " to " + target.m_shared.m_name));
					return true;
				}
				message = "Epic Loot refused to create the legendary item (requirements not met or API not found).";
				Logger.LogWarning((object)("ApplyLegendary failed for " + value));
				return false;
			}
			catch (Exception ex)
			{
				message = "Error while applying rune: " + ex.Message;
				Logger.LogError((object)ex.ToString());
				return false;
			}
		}

		private static bool ApplyLegendaryViaReflection(ItemData item, string legendaryId)
		{
			Assembly assembly = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				try
				{
					if (assemblies[i].GetName().Name == "EpicLoot")
					{
						assembly = assemblies[i];
						break;
					}
				}
				catch
				{
				}
			}
			if (assembly == null)
			{
				Logger.LogError((object)"EpicLoot assembly not found.");
				return false;
			}
			Type type = assembly.GetType("EpicLoot.API");
			if (type == null)
			{
				Logger.LogError((object)"EpicLoot.API type not found.");
				return false;
			}
			MethodInfo method = type.GetMethod("GetMagicItemJson", BindingFlags.Static | BindingFlags.Public);
			MethodInfo method2 = type.GetMethod("ApplyMagicItemJson", BindingFlags.Static | BindingFlags.Public);
			MethodInfo method3 = type.GetMethod("GetLegendaryInfoJson", BindingFlags.Static | BindingFlags.Public);
			if (method != null && method2 != null)
			{
				string text = null;
				try
				{
					text = method.Invoke(null, new object[1] { item }) as string;
				}
				catch (Exception ex)
				{
					Logger.LogWarning((object)("GetMagicItemJson failed: " + ex.Message));
				}
				string text2 = null;
				string setId = null;
				if (method3 != null)
				{
					try
					{
						string text3 = method3.Invoke(null, new object[1] { legendaryId }) as string;
						if (!string.IsNullOrEmpty(text3))
						{
							Logger.LogInfo((object)("LegendaryInfoJson: " + text3));
							text2 = ExtractJsonString(text3, "Name");
							if (string.IsNullOrEmpty(text2))
							{
								text2 = ExtractJsonString(text3, "name");
							}
							if (IndexOfIgnoreCase(text3, "\"IsSetItem\":true") >= 0 || IndexOfIgnoreCase(text3, "\"IsSetItem\": true") >= 0)
							{
								setId = (legendaryId.StartsWith("Heimdall") ? "Heimdall" : ((!legendaryId.StartsWith("Ragnar")) ? legendaryId : "Ragnar"));
							}
						}
					}
					catch (Exception ex2)
					{
						Logger.LogWarning((object)("GetLegendaryInfoJson failed: " + ex2.Message));
					}
				}
				text = ((!string.IsNullOrEmpty(text) && !(text == "null") && !(text == "{}")) ? InjectLegendaryIntoJson(text, legendaryId, text2, setId) : BuildMinimalMagicJson(legendaryId, text2, setId));
				Logger.LogInfo((object)("Applying magic JSON (preserve effects): " + text));
				try
				{
					if (!(method2.Invoke(null, new object[2] { item, text }) is bool result))
					{
						return true;
					}
					return result;
				}
				catch (Exception ex3)
				{
					Logger.LogError((object)("ApplyMagicItemJson failed: " + ex3));
					if (ex3.InnerException != null)
					{
						Logger.LogError((object)("Inner: " + ex3.InnerException));
					}
				}
			}
			return ApplyLegendaryOnMagicItemObject(assembly, item, legendaryId);
		}

		private static bool ApplyLegendaryOnMagicItemObject(Assembly epicAsm, ItemData item, string legendaryId)
		{
			Type type = epicAsm.GetType("EpicLoot.ItemDataExtensions");
			if (type == null)
			{
				Logger.LogError((object)"ItemDataExtensions not found.");
				return false;
			}
			MethodInfo method = type.GetMethod("GetMagicItem", BindingFlags.Static | BindingFlags.Public);
			MethodInfo method2 = type.GetMethod("SaveMagicItem", BindingFlags.Static | BindingFlags.Public);
			if (method == null || method2 == null)
			{
				Logger.LogError((object)"GetMagicItem/SaveMagicItem not found.");
				return false;
			}
			object obj = null;
			try
			{
				obj = method.Invoke(null, new object[1] { item });
			}
			catch
			{
			}
			Type type2 = epicAsm.GetType("EpicLoot.MagicItem");
			if (type2 == null)
			{
				type2 = epicAsm.GetType("EpicLoot.Magic.MagicItem");
			}
			if (obj == null)
			{
				if (type2 == null)
				{
					Logger.LogError((object)"MagicItem type not found and item has no magic data.");
					return false;
				}
				obj = Activator.CreateInstance(type2);
				PropertyInfo property = type2.GetProperty("Rarity");
				if (property != null)
				{
					Type propertyType = property.PropertyType;
					try
					{
						object value = Enum.Parse(propertyType, "Legendary", ignoreCase: true);
						property.SetValue(obj, value, null);
					}
					catch
					{
					}
				}
			}
			Type type3 = obj.GetType();
			PropertyInfo[] properties = type3.GetProperties(BindingFlags.Instance | BindingFlags.Public);
			for (int i = 0; i < properties.Length; i++)
			{
				Logger.LogInfo((object)("MagicItem prop: " + properties[i].Name + " : " + properties[i].PropertyType.Name));
			}
			SetStringProp(obj, "TypeNameOverride", "$mod_epicloot_l_" + legendaryId.ToLowerInvariant());
			SetStringProp(obj, "LegendaryID", legendaryId);
			SetStringProp(obj, "LegendaryId", legendaryId);
			SetStringProp(obj, "LegendarySetItemID", legendaryId);
			SetStringProp(obj, "LegendarySetItemId", legendaryId);
			try
			{
				method2.Invoke(null, new object[2] { item, obj });
				Logger.LogInfo((object)("SaveMagicItem OK for " + legendaryId));
				return true;
			}
			catch (Exception ex)
			{
				Logger.LogError((object)("SaveMagicItem failed: " + ex));
				return false;
			}
		}

		private static void SetStringProp(object obj, string name, string value)
		{
			if (obj != null && value != null)
			{
				PropertyInfo property = obj.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
				if (property != null && property.CanWrite && property.PropertyType == typeof(string))
				{
					property.SetValue(obj, value, null);
					Logger.LogInfo((object)("Set " + name + " = " + value));
				}
				FieldInfo field = obj.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public);
				if (field != null && field.FieldType == typeof(string))
				{
					field.SetValue(obj, value);
					Logger.LogInfo((object)("Set field " + name + " = " + value));
				}
			}
		}

		private static string ExtractJsonString(string json, string key)
		{
			if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(key))
			{
				return null;
			}
			string text = "\"" + key + "\"";
			int num = json.IndexOf(text, StringComparison.OrdinalIgnoreCase);
			if (num < 0)
			{
				return null;
			}
			int num2 = json.IndexOf(':', num + text.Length);
			if (num2 < 0)
			{
				return null;
			}
			int num3 = json.IndexOf('"', num2 + 1);
			if (num3 < 0)
			{
				return null;
			}
			int num4 = json.IndexOf('"', num3 + 1);
			if (num4 < 0)
			{
				return null;
			}
			return json.Substring(num3 + 1, num4 - num3 - 1);
		}

		private static string BuildMinimalMagicJson(string legendaryId, string typeNameOverride, string setId)
		{
			if (string.IsNullOrEmpty(typeNameOverride))
			{
				typeNameOverride = "$mod_epicloot_l_" + legendaryId.ToLowerInvariant();
			}
			string text = "";
			if (!string.IsNullOrEmpty(setId))
			{
				text = ",\"SetID\":\"" + setId + "\"";
			}
			return "{\"Version\":3,\"Rarity\":3,\"Effects\":[],\"TypeNameOverride\":\"" + typeNameOverride + "\",\"LegendaryID\":\"" + legendaryId + "\"" + text + ",\"IsUnidentified\":false}";
		}

		private static string InjectLegendaryIntoJson(string json, string legendaryId, string typeNameOverride, string setId)
		{
			if (string.IsNullOrEmpty(typeNameOverride))
			{
				typeNameOverride = "$mod_epicloot_l_" + legendaryId.ToLowerInvariant();
			}
			json = SetOrReplaceJsonString(json, "TypeNameOverride", typeNameOverride);
			json = SetOrReplaceJsonString(json, "LegendaryID", legendaryId);
			if (!string.IsNullOrEmpty(setId))
			{
				json = SetOrReplaceJsonString(json, "SetID", setId);
			}
			return json;
		}

		private static string SetOrReplaceJsonString(string json, string key, string value)
		{
			if (string.IsNullOrEmpty(json))
			{
				json = "{}";
			}
			string text = value.Replace("\\", "\\\\").Replace("\"", "\\\"");
			string text2 = "\"" + key + "\":\"" + text + "\"";
			string text3 = "\"" + key + "\"";
			int num = IndexOfIgnoreCase(json, text3);
			if (num >= 0)
			{
				int num2 = json.IndexOf(':', num + text3.Length);
				if (num2 < 0)
				{
					return json;
				}
				int i;
				for (i = num2 + 1; i < json.Length && (json[i] == ' ' || json[i] == '\t'); i++)
				{
				}
				int j = i;
				if (i < json.Length && json[i] == '"')
				{
					for (j = i + 1; j < json.Length; j++)
					{
						if (json[j] == '"' && json[j - 1] != '\\')
						{
							j++;
							break;
						}
					}
				}
				else if (i + 4 <= json.Length && json.Substring(i, 4) == "null")
				{
					j = i + 4;
				}
				else
				{
					for (; j < json.Length && json[j] != ',' && json[j] != '}'; j++)
					{
					}
				}
				return json.Substring(0, num) + text2 + json.Substring(j);
			}
			string text4 = json.Trim();
			if (text4.EndsWith("}"))
			{
				text4 = text4.Substring(0, text4.Length - 1).TrimEnd(new char[0]);
			}
			if (!text4.EndsWith("{") && !text4.EndsWith(","))
			{
				text4 += ",";
			}
			return text4 + text2 + "}";
		}

		private static int IndexOfIgnoreCase(string haystack, string needle)
		{
			return haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
		}
	}
}
namespace Orgetorix.EtchedRunes.Patches
{
	[HarmonyPatch(typeof(Trader), "GetAvailableItems")]
	public static class Trader_GetAvailableItems_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(Trader __instance, ref List<TradeItem> __result)
		{
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Expected O, but got Unknown
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Expected O, but got Unknown
			if (!ModConfig.Enabled.Value || (Object)(object)__instance == (Object)null || ((Object)__instance).name == null || (((Object)__instance).name.IndexOf("Haldor", StringComparison.OrdinalIgnoreCase) < 0 && (__instance.m_name == null || __instance.m_name.IndexOf("haldor", StringComparison.OrdinalIgnoreCase) < 0)))
			{
				return;
			}
			foreach (KeyValuePair<string, RichesItemConfig> item in RichesRuneManager.Registered)
			{
				string key = item.Key;
				RichesItemConfig value = item.Value;
				GameObject prefab = PrefabManager.Instance.GetPrefab(key);
				if (!((Object)(object)prefab == (Object)null))
				{
					ItemDrop component = prefab.GetComponent<ItemDrop>();
					if (!((Object)(object)component == (Object)null) && !AlreadyInList(__result, key))
					{
						TradeItem val = new TradeItem();
						val.m_prefab = component;
						val.m_stack = value.Stack.Value;
						val.m_price = value.CoinsCost.Value;
						__result.Add(val);
					}
				}
			}
			for (int i = 0; i < ModConfig.LegendaryRunes.Count; i++)
			{
				LegendaryRuneDef legendaryRuneDef = ModConfig.LegendaryRunes[i];
				if (!ModConfig.IsLegendaryEnabled(legendaryRuneDef))
				{
					continue;
				}
				GameObject prefab2 = PrefabManager.Instance.GetPrefab(legendaryRuneDef.PrefabName);
				if (!((Object)(object)prefab2 == (Object)null))
				{
					ItemDrop component2 = prefab2.GetComponent<ItemDrop>();
					if (!((Object)(object)component2 == (Object)null) && !AlreadyInList(__result, legendaryRuneDef.PrefabName))
					{
						TradeItem val2 = new TradeItem();
						val2.m_prefab = component2;
						val2.m_stack = legendaryRuneDef.StackSize.Value;
						val2.m_price = legendaryRuneDef.Price.Value;
						__result.Add(val2);
					}
				}
			}
		}

		private static bool AlreadyInList(List<TradeItem> list, string prefabName)
		{
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i].m_prefab != (Object)null && ((Object)list[i].m_prefab).name == prefabName)
				{
					return true;
				}
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Humanoid), "UseItem")]
	public static class Humanoid_UseItem_Patch
	{
		[HarmonyPrefix]
		public static bool Prefix(Humanoid __instance, Inventory inventory, ItemData item, bool fromInventoryGui)
		{
			if (!ModConfig.Enabled.Value)
			{
				return true;
			}
			if ((Object)(object)__instance == (Object)null || item == null)
			{
				return true;
			}
			LegendaryRuneDef runeByItemData = LegendaryRuneManager.GetRuneByItemData(item);
			if (runeByItemData == null)
			{
				return true;
			}
			Player val = (Player)(object)((__instance is Player) ? __instance : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			ItemData val2 = FindSlotOneItem(inventory, item);
			if (val2 == null)
			{
				((Character)val).Message((MessageType)2, "Place the target item in inventory slot 1 (top-left).", 0, (Sprite)null);
				return false;
			}
			if (!LegendaryRuneManager.CanApplyTo(runeByItemData, val2))
			{
				string text = runeByItemData.AllowedItemTypes.Value;
				if (string.IsNullOrEmpty(text))
				{
					text = "matching item";
				}
				if (runeByItemData.RequireNoParryPower.Value)
				{
					text += " (tower shield, no parry)";
				}
				((Character)val).Message((MessageType)2, "Slot 1 item is wrong type. Need: " + text, 0, (Sprite)null);
				return false;
			}
			if (LegendaryRuneManager.TryApplyRune(runeByItemData, val2, out var message))
			{
				inventory.RemoveOneItem(item);
				((Character)val).Message((MessageType)2, message, 0, (Sprite)null);
			}
			else
			{
				((Character)val).Message((MessageType)2, message, 0, (Sprite)null);
			}
			return false;
		}

		private static ItemData FindSlotOneItem(Inventory inventory, ItemData runeItem)
		{
			if (inventory == null)
			{
				return null;
			}
			List<ItemData> allItems = inventory.GetAllItems();
			for (int i = 0; i < allItems.Count; i++)
			{
				ItemData val = allItems[i];
				if (val != null && val != runeItem && val.m_gridPos.x == 0 && val.m_gridPos.y == 0)
				{
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })]
	public static class Inventory_AddItem_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(ItemData item)
		{
			if (ModConfig.Enabled.Value && item != null)
			{
				RichesRuneManager.TryApplyMagicData(item);
			}
		}
	}
	[HarmonyPatch(typeof(ItemData), "Clone")]
	public static class ItemData_Clone_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(ItemData __instance, ItemData __result)
		{
			if (ModConfig.Enabled.Value && __result != null)
			{
				if ((Object)(object)__result.m_dropPrefab == (Object)null && __instance != null)
				{
					__result.m_dropPrefab = __instance.m_dropPrefab;
				}
				RichesRuneManager.TryApplyMagicData(__result);
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop), "Awake")]
	public static class ItemDrop_Awake_Patch
	{
		[HarmonyPostfix]
		public static void Postfix(ItemDrop __instance)
		{
			if (ModConfig.Enabled.Value && !((Object)(object)__instance == (Object)null) && __instance.m_itemData != null)
			{
				RichesRuneManager.TryApplyMagicData(__instance.m_itemData);
			}
		}
	}
}