Decompiled source of ReforgedPotential v2.0.10

ReforgedPotential.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using EpicLootAPI;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Extensions;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using ReforgedPotential.Compatibility;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("ReforgedPotential")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReforgedPotential")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("2.0.10")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.10.0")]
namespace ReforgedPotential
{
	[BepInPlugin("akuichi.ReforgedPotential", "Reforged Potential", "2.0.10")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	public class ReforgedPotential : BaseUnityPlugin
	{
		public static class ChatHelpers
		{
			public static void ResetChatHideTimer()
			{
				Chat.instance.m_hideTimer = 0f;
			}
		}

		[HarmonyPatch(typeof(InventoryGui))]
		private static class InventoryGuiPatch
		{
			private enum UpgradeOutcome
			{
				Upgraded,
				Degraded,
				Destroyed,
				Unknown
			}

			private static Dictionary<string, string> originalRequirements = new Dictionary<string, string>();

			private static int currentEquivalentTier;

			[HarmonyPrefix]
			[HarmonyPatch("DoCrafting")]
			private static bool DoCraftingPrefix(InventoryGui __instance, Player player)
			{
				//IL_0135: 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_03a9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a19: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a1e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a2c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a32: Unknown result type (might be due to invalid IL or missing references)
				//IL_0917: Unknown result type (might be due to invalid IL or missing references)
				//IL_09e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_09ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_09fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0a00: Unknown result type (might be due to invalid IL or missing references)
				//IL_09b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_09bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_09c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_09cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0708: Unknown result type (might be due to invalid IL or missing references)
				//IL_0713: Unknown result type (might be due to invalid IL or missing references)
				//IL_071d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0722: Unknown result type (might be due to invalid IL or missing references)
				//IL_0727: Unknown result type (might be due to invalid IL or missing references)
				//IL_072c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0731: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
					if (!((Object)(object)currentCraftingStation != (Object)null) || !currentCraftingStation.m_upgrader)
					{
						return true;
					}
					int quality = __instance.m_craftUpgradeItem.m_quality;
					int num = quality + 1;
					int num2 = 1;
					int num3 = default(int);
					ItemData val = default(ItemData);
					int amount = __instance.m_craftRecipe.GetAmount(num, ref num3, ref val, num2);
					string name = __instance.m_craftUpgradeItem.m_shared.m_name;
					bool flag = __instance.m_craftUpgradeItem == null || ((Humanoid)player).GetInventory().ContainsItem(__instance.m_craftUpgradeItem);
					bool flag2 = !__instance.m_craftRecipe.m_requireOnlyOneIngredient || val != null;
					bool flag3 = player.NoCostCheat() || ZoneSystem.instance.GetGlobalKey((GlobalKeys)25);
					bool flag4 = __instance.m_craftUpgradeItem != null || ((Humanoid)player).GetInventory().CanAddItem(((Component)__instance.m_craftRecipe.m_item).gameObject, 1);
					string text = __instance.m_craftUpgradeItem.m_shared.m_name ?? "Unknown Item";
					if (!flag4)
					{
						return false;
					}
					int num4 = __instance.m_craftVariant;
					Vector2i gridPos = default(Vector2i);
					((Vector2i)(ref gridPos))..ctor(-1, -1);
					if (__instance.m_craftUpgradeItem != null)
					{
						gridPos = __instance.m_craftUpgradeItem.m_gridPos;
						num4 = __instance.m_craftUpgradeItem.m_variant;
						((Humanoid)player).UnequipItem(__instance.m_craftUpgradeItem, true);
						((Humanoid)player).GetInventory().RemoveItem(__instance.m_craftUpgradeItem);
					}
					long playerID = player.GetPlayerID();
					string playerName = player.GetPlayerName();
					bool flag5 = ((Humanoid)player).GetInventory().ItemCheated(__instance.m_craftRecipe.m_resources, -1, true);
					bool flag6 = currentCraftingStation != null && ((Component)currentCraftingStation).GetComponent<ZNetView>().GetZDO().GetBool(ZDOVars.s_cheated, false);
					bool flag7 = (flag5 || player.NoCostCheat() || flag6) && !PlayerProfile.s_bypassCheatChecks;
					UpgradeOutcome upgradeOutcome = UpgradeOutcome.Unknown;
					ItemData craftedItem = null;
					bool flag8 = false;
					ItemData val2 = null;
					Requirement[] resources = __instance.m_craftRecipe.m_resources;
					foreach (Requirement val3 in resources)
					{
						if (val3.m_upgraderResource)
						{
							val2 = val3.m_resItem.m_itemData;
							break;
						}
					}
					if (val2 == null)
					{
						((Character)player).Message((MessageType)2, "$msg_missingrequirement", 0, (Sprite)null, false);
						ZLog.LogError((object)"No upgrader resource found in inventory");
						return false;
					}
					float num5 = Random.Range(0f, 1f);
					float num6 = Random.Range(0f, 1f);
					float num7 = UpgradeChance.Value;
					float num8 = BreakChance.Value;
					if (UseCustomChances.Value)
					{
						num7 = UpgradeHelper.GetUpgradeChance(quality);
						num8 = UpgradeHelper.GetBreakChance(quality);
					}
					Logger.LogInfo((object)$"DoCraftingPrefix: Upgrade roll: {num5 * 100f}, Break roll: {num6 * 100f}, Upgrade chance: {num7 * 100f}%, Break chance: {num8 * 100f}%");
					if (num7 >= num5)
					{
						ZLog.Log((object)("Upgrader <color=yellow>succeeded</color> on " + $"{__instance.m_craftUpgradeItem.m_shared.m_name} level {num}!"));
						((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_upgrader_success", new string[2]
						{
							__instance.m_craftUpgradeItem.m_shared.m_name,
							num.ToString()
						}), 0, (Sprite)null, true);
						craftedItem = ((Humanoid)player).GetInventory().AddItem(((Object)((Component)__instance.m_craftRecipe.m_item).gameObject).name, 1, num, num4, playerID, playerName, gridPos, flag7, false, true);
						flag8 = true;
						upgradeOutcome = UpgradeOutcome.Upgraded;
					}
					else if (num8 >= num6)
					{
						ZLog.Log((object)("Upgrader <color=red>BROKE</color> " + text + " level " + $"{num - 1} and was destroyed!"));
						((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_upgrader_broke", new string[2]
						{
							text,
							(num - 1).ToString()
						}), 0, (Sprite)null, true);
						upgradeOutcome = UpgradeOutcome.Destroyed;
						if (val2.m_shared.m_breakReturnIngreientsAmount > 0f)
						{
							Requirement[] resources2 = __instance.m_craftRecipe.m_resources;
							foreach (Requirement val4 in resources2)
							{
								if (val4.m_recover)
								{
									int num9 = Mathf.CeilToInt((float)(val4.GetAmount(1) + val4.GetAmount(num)) * val2.m_shared.m_breakReturnIngreientsAmount);
									if (num9 > 0)
									{
										craftedItem = ((Humanoid)player).GetInventory().AddItem(((Object)val4.m_resItem).name, num9, val4.m_resItem.m_itemData.m_quality, val4.m_resItem.m_itemData.m_variant, playerID, playerName, new Vector2i(-1, -1), flag7, false, true);
										ZLog.Log((object)("Upgrader returned " + val4.m_resItem.m_itemData.m_shared.m_name + " " + $"x{num9} to inventory"));
									}
								}
							}
						}
						if (RefundIdolsOnBreak.Value)
						{
							string name2 = ((Object)((RecipeDataPair)(ref __instance.m_selectedRecipe)).Recipe.m_item).name;
							string value;
							string originalResource = (originalRequirements.TryGetValue(name2, out value) ? value : null);
							Dictionary<string, int> totalIdolCosts = UpgradeHelper.GetTotalIdolCosts(originalResource, quality, RefundIdolsOnBreakStartingLevel.Value);
							foreach (KeyValuePair<string, int> item in totalIdolCosts)
							{
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)$"DoCraftingPostfix: Total idol cost for {text} at quality {quality}: {item.Key} = {item.Value}");
								}
								if (item.Value <= 0)
								{
									continue;
								}
								GameObject prefab = PrefabManager.Instance.GetPrefab(item.Key);
								if ((Object)(object)prefab != (Object)null)
								{
									if (EnableDebugLogging.Value)
									{
										Logger.LogInfo((object)$"Attempting to refund {RefundIdolsPercentageOnBreak.Value * 100f}% of {item.Key} x{item.Value}");
									}
									int num10 = Math.Max(1, (int)Math.Ceiling((float)item.Value * RefundIdolsPercentageOnBreak.Value));
									if (((Humanoid)player).GetInventory().AddItem(prefab, num10))
									{
										if (EnableDebugLogging.Value)
										{
											Logger.LogInfo((object)$"DoCraftingPostfix: Refunded {num10} of {item.Key} to player {player.GetPlayerName()}");
										}
										continue;
									}
									Object.Instantiate<GameObject>(prefab, ((Component)player).transform.position + ((Component)player).transform.forward * 2f + Vector3.up, Quaternion.identity);
									if (EnableDebugLogging.Value)
									{
										Logger.LogInfo((object)$"DoCraftingPostfix: Could not add {item.Key} to player {player.GetPlayerName()}'s inventory, dropped {num10} at player's position.");
									}
								}
								else if (EnableDebugLogging.Value)
								{
									Logger.LogWarning((object)("DoCraftingPostfix: Could not find item prefab for " + item.Key + " to refund to player " + player.GetPlayerName()));
								}
							}
						}
						else if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)"Refund idols on break is disabled, skipping..");
						}
					}
					else
					{
						int num11 = Mathf.Max(1, num - 2);
						ZLog.Log((object)("Upgrader <color=orange>FAILED</color> " + __instance.m_craftUpgradeItem.m_shared.m_name + " level " + $"{num - 1}, level was reduced!"));
						string text2 = "Upgrade failed!";
						if (ConsumeIdolsOnlyOnFailure.Value)
						{
							num11 = __instance.m_craftUpgradeItem.m_quality;
							if (EnableDebugLogging.Value)
							{
								Logger.LogInfo((object)("DoCraftingPostfix: Upgrade failed for " + text + ", level was not reduced due to 'Consume Idols Only On Failure' = True"));
							}
						}
						else if (quality == 1)
						{
							if (EnableDebugLogging.Value)
							{
								Logger.LogInfo((object)("DoCraftingPostfix: Upgrade failed for " + text + ", cannot change below level 1."));
							}
						}
						else
						{
							text2 = "Upgrade failed, " + text + "'s level was reduced!";
							if (EnableDebugLogging.Value)
							{
								Logger.LogInfo((object)("DoCraftingPostfix: Upgrade failed for " + text + ", item level was reduced."));
							}
						}
						craftedItem = ((Humanoid)player).GetInventory().AddItem(((Object)((Component)__instance.m_craftRecipe.m_item).gameObject).name, amount, num11, num4, playerID, playerName, gridPos, flag7, false, true);
						((Character)player).Message((MessageType)2, text2, 0, (Sprite)null, true);
						upgradeOutcome = UpgradeOutcome.Degraded;
					}
					if (!flag3)
					{
						if (val != null)
						{
							((Humanoid)player).GetInventory().RemoveItem(val.m_shared.m_name, num3, val.m_quality, true);
						}
						else
						{
							player.ConsumeResources(__instance.m_craftRecipe.m_resources, num, -1, num2);
						}
					}
					__instance.UpdateCraftingPanel(false);
					if ((Object)(object)currentCraftingStation != (Object)null)
					{
						if (flag8)
						{
							currentCraftingStation.m_craftItemDoneEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
						}
						else
						{
							currentCraftingStation.m_craftItemDoneFailEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
						}
					}
					else
					{
						__instance.m_craftItemDoneEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
					}
					string itemName = Localization.instance.Localize(name);
					int level = num;
					if (upgradeOutcome == UpgradeOutcome.Degraded || upgradeOutcome == UpgradeOutcome.Upgraded)
					{
						EpicLootCompatibility.TryCopyMagicItem(__instance.m_craftUpgradeItem, craftedItem);
					}
					bool success = upgradeOutcome == UpgradeOutcome.Upgraded;
					BroadcastUpgradeResult(playerName, itemName, level, success);
					Gogan.LogEvent("Game", "Crafted", __instance.m_craftRecipe.m_item.m_itemData.m_shared.m_name, (long)num);
					return false;
				}
				catch (Exception arg)
				{
					Logger.LogWarning((object)$"DoCrafting prefix exception: {arg}");
				}
				return true;
			}

			[HarmonyPrefix]
			[HarmonyPatch("SetupCrafting")]
			private static void SetupCraftingPrefix(ref float ___m_upgraderDuration, ref float ___m_upgraderDurationPerLevel)
			{
				___m_upgraderDuration = UpgradeBaseDuration.Value;
				___m_upgraderDurationPerLevel = UpgradeDurationIncreasePerLevel.Value;
			}

			[HarmonyPrefix]
			[HarmonyPatch("OnCraftPressed")]
			private static bool OnCraftPressedPrefix(InventoryGui __instance)
			{
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0032: Unknown result type (might be due to invalid IL or missing references)
				try
				{
					if (!EnableBossProgression.Value && !EnableLevelCap.Value)
					{
						return true;
					}
					RecipeDataPair selectedRecipe = __instance.m_selectedRecipe;
					Recipe recipe = ((RecipeDataPair)(ref selectedRecipe)).Recipe;
					ItemData itemData = ((RecipeDataPair)(ref selectedRecipe)).ItemData;
					if ((Object)(object)recipe == (Object)null)
					{
						return true;
					}
					Player localPlayer = Player.m_localPlayer;
					CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
					if (!((Object)(object)currentCraftingStation != (Object)null) || !currentCraftingStation.m_upgrader)
					{
						return true;
					}
					if (itemData != null)
					{
						Requirement[] array = recipe.m_resources ?? Array.Empty<Requirement>();
						foreach (Requirement val in array)
						{
							if (val == null || (Object)(object)val.m_resItem == (Object)null)
							{
								continue;
							}
							string name = ((Object)val.m_resItem).name;
							if (!name.Contains("Upgrader"))
							{
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)("Iterating resources needed to upgrade for " + itemData.m_shared.m_name + " skipping non upgrader resource: " + name + "."));
								}
								continue;
							}
							if (EnableDebugLogging.Value)
							{
								Logger.LogInfo((object)("Iterating resources needed to upgrade for " + itemData.m_shared.m_name + " found upgrader resource: " + name + "."));
							}
							int maxBossTier = UpgradeHelper.GetMaxBossTier();
							originalRequirements.TryGetValue(((Object)recipe.m_item).name, out var value);
							if (EnableDebugLogging.Value)
							{
								Logger.LogInfo((object)("Original upgrader resource: " + value));
							}
							int equipmentTier = UpgradeHelper.GetEquipmentTier(value);
							if (equipmentTier < 0)
							{
								Logger.LogWarning((object)("Could not determine equipment tier for upgrader '" + value + "'."));
								continue;
							}
							int num = UpgradeHelper.GetMaxUpgradeLevel(equipmentTier, maxBossTier);
							if (EnableLevelCap.Value)
							{
								Logger.LogInfo((object)$"Level cap is enabled, overriding max upgrade level for {itemData.m_shared.m_name} to {LevelCap.Value}.");
								num = Math.Max(1, LevelCap.Value);
							}
							int quality = itemData.m_quality;
							if (quality >= num)
							{
								int requiredBossForNextUpgrade = UpgradeHelper.GetRequiredBossForNextUpgrade(equipmentTier, quality);
								string value2;
								string text = ((requiredBossForNextUpgrade != -1 && bossNames.TryGetValue(requiredBossForNextUpgrade, out value2)) ? value2 : null);
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)("Player attempted to upgrade " + itemData.m_shared.m_name + " " + $"from quality {quality} to {quality + 1}. " + $"Item tier={equipmentTier}, " + $"highest boss tier={maxBossTier}, " + $"max allowed={num}, " + "required boss=" + (text ?? "none") + "."));
								}
								if (localPlayer != null)
								{
									((Character)localPlayer).Message((MessageType)2, (text != null) ? ("Defeat " + text + " to upgrade this gear any further.") : "Max upgrade level reached!", 0, (Sprite)null, false);
								}
								return false;
							}
							return true;
						}
						return false;
					}
					return true;
				}
				catch (Exception arg)
				{
					Logger.LogWarning((object)$"OnCraftPressed prefix exception: {arg}");
				}
				return true;
			}

			[HarmonyPostfix]
			[HarmonyPatch("SetRecipe")]
			private static void SetRecipePostfix(InventoryGui __instance)
			{
				//IL_0038: Unknown result type (might be due to invalid IL or missing references)
				//IL_003d: Unknown result type (might be due to invalid IL or missing references)
				string text = "SetRecipePostfix: ";
				try
				{
					Player localPlayer = Player.m_localPlayer;
					CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
					if (!((Object)(object)currentCraftingStation != (Object)null) || !currentCraftingStation.m_upgrader)
					{
						return;
					}
					RecipeDataPair selectedRecipe = __instance.m_selectedRecipe;
					Recipe recipe = ((RecipeDataPair)(ref selectedRecipe)).Recipe;
					ItemData itemData = ((RecipeDataPair)(ref selectedRecipe)).ItemData;
					if (!originalRequirements.ContainsKey(((Object)recipe.m_item).name))
					{
						Requirement[] array = recipe.m_resources ?? Array.Empty<Requirement>();
						foreach (Requirement val in array)
						{
							if (val.m_upgraderResource)
							{
								string name = ((Object)val.m_resItem).name;
								originalRequirements.Add(((Object)recipe.m_item).name, name);
								break;
							}
						}
						originalRequirements.TryGetValue(((Object)recipe.m_item).name, out var value);
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)(text + "Storing original upgrader resource for " + itemData.m_shared.m_name + " as " + value));
						}
					}
					if ((Object)(object)recipe == (Object)null || itemData == null)
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)(text + "No selected recipe or item data found."));
						}
						return;
					}
					for (int j = 0; recipe.m_resources.Length > j; j++)
					{
						if (!recipe.m_resources[j].m_upgraderResource || !originalRequirements.TryGetValue(((Object)recipe.m_item).name, out var value2))
						{
							continue;
						}
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)(text + "Found upgrader resource for " + itemData.m_shared.m_name + ": " + value2));
						}
						Requirement val2 = recipe.m_resources[j];
						int quality = itemData.m_quality;
						int equipmentTier = UpgradeHelper.GetEquipmentTier(value2);
						int configuredMaxBoss = ((bossUpgradeValues != null && bossUpgradeValues.Count > 0) ? bossUpgradeValues.Keys.Max() : 8);
						if (equipmentTier < 0)
						{
							Logger.LogWarning((object)(text + "Could not determine equipment tier for resource '" + value2 + "'."));
							continue;
						}
						UpgradeHelper.GetEquivalentUpgradeValues(equipmentTier, quality, configuredMaxBoss, out var equivalentTier, out var candidateQuality);
						currentEquivalentTier = equivalentTier;
						int upgradeCost = UpgradeHelper.GetUpgradeCost(candidateQuality);
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)(text + "Resource=" + value2 + ", " + $"baseTier={equipmentTier}, " + $"quality={quality}, " + $"equivalentTier={equivalentTier}, " + $"candidateQuality={candidateQuality}, " + $"cost={upgradeCost}."));
						}
						itemData.m_shared.m_breakReturnIngreientsAmount = 1f;
						ItemDrop val3 = null;
						if (!EnableIdolProgression.Value)
						{
							GameObject prefab = PrefabManager.Instance.GetPrefab(value2);
							if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref val3))
							{
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)$"{text}Keeping original resource {((Object)val3).name} and setting amount to {upgradeCost}.");
								}
							}
							else
							{
								Logger.LogError((object)(text + "Could not find prefab for original resource '" + value2 + "'."));
							}
						}
						else
						{
							string name2 = ((Object)val2.m_resItem).name;
							string text2 = (name2.Contains("Weapon") ? $"Upgrader{equivalentTier}Weapon" : (name2.Contains("Armor") ? $"Upgrader{equivalentTier}Armor" : null));
							if (text2 == null)
							{
								Logger.LogError((object)$"{text}Selected resource is neither weapon nor armor. Setting cost to {upgradeCost}.");
							}
							else
							{
								GameObject prefab2 = PrefabManager.Instance.GetPrefab(text2);
								if ((Object)(object)prefab2 != (Object)null && prefab2.TryGetComponent<ItemDrop>(ref val3))
								{
									if (EnableDebugLogging.Value)
									{
										Logger.LogInfo((object)$"{text}Found prefab for {text2}. Setting resource to {((Object)val3).name} with amount {upgradeCost}.");
									}
								}
								else
								{
									Logger.LogError((object)(text + "Could not find prefab '" + text2 + "'."));
								}
							}
						}
						if ((Object)(object)val3 != (Object)null)
						{
							val2.m_resItem = val3;
							val2.m_amount = upgradeCost;
						}
					}
				}
				catch (Exception arg)
				{
					Logger.LogWarning((object)$"{text} exception: {arg}");
				}
			}
		}

		[HarmonyPatch(typeof(ObjectDB))]
		private static class ObjectDBPatch
		{
			[HarmonyPostfix]
			[HarmonyPatch("Awake")]
			private static void AwakePostfix(ObjectDB __instance)
			{
				//IL_0138: Unknown result type (might be due to invalid IL or missing references)
				//IL_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0145: Unknown result type (might be due to invalid IL or missing references)
				//IL_014c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0153: Unknown result type (might be due to invalid IL or missing references)
				//IL_015f: Expected O, but got Unknown
				if (!PatchVanillaUpgraderRecipes.Value)
				{
					return;
				}
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)"Patching vanilla upgrader recipes...");
				}
				List<Recipe> recipes = __instance.m_recipes;
				if (recipes == null)
				{
					Logger.LogWarning((object)"ObjectDB recipes are not initialized.");
					return;
				}
				foreach (Recipe item in recipes)
				{
					if (((Object)item).name == "Recipe_HelmetBerserker")
					{
						Requirement[] resources = item.m_resources;
						Requirement[] array = resources;
						foreach (Requirement val in array)
						{
							if (val.m_upgraderResource)
							{
								val.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader1Armor").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_HelmetBerserker");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_HelmetGold")
					{
						List<Requirement> list = item.m_resources.ToList();
						GameObject prefab = PrefabManager.Instance.GetPrefab("Upgrader7Armor");
						ItemDrop resItem = ((prefab != null) ? prefab.GetComponent<ItemDrop>() : null);
						list.Add(new Requirement
						{
							m_resItem = resItem,
							m_amount = 1,
							m_upgraderResource = true,
							m_amountPerLevel = 0
						});
						item.m_resources = list.ToArray();
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)"Patched Recipe_HelmetGold");
						}
					}
					if (((Object)item).name == "Recipe_AxeJotunBane")
					{
						Requirement[] resources2 = item.m_resources;
						Requirement[] array2 = resources2;
						foreach (Requirement val2 in array2)
						{
							if (val2.m_upgraderResource)
							{
								val2.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader5Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_AxeJotunBane");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_SpearSplitner")
					{
						Requirement[] resources3 = item.m_resources;
						Requirement[] array3 = resources3;
						foreach (Requirement val3 in array3)
						{
							if (val3.m_upgraderResource)
							{
								val3.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader6Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_SpearSplitner");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_SpearSplitner_Blood")
					{
						Requirement[] resources4 = item.m_resources;
						Requirement[] array4 = resources4;
						foreach (Requirement val4 in array4)
						{
							if (val4.m_upgraderResource)
							{
								val4.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader6Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_SpearSplitner_Blood");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_SpearSplitner_Lightning")
					{
						Requirement[] resources5 = item.m_resources;
						Requirement[] array5 = resources5;
						foreach (Requirement val5 in array5)
						{
							if (val5.m_upgraderResource)
							{
								val5.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader6Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_SpearSplitner_Lightning");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_SpearSplitner_Nature")
					{
						Requirement[] resources6 = item.m_resources;
						Requirement[] array6 = resources6;
						foreach (Requirement val6 in array6)
						{
							if (val6.m_upgraderResource)
							{
								val6.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader6Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_SpearSplitner_Nature");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_KnifeChitin")
					{
						Requirement[] resources7 = item.m_resources;
						Requirement[] array7 = resources7;
						foreach (Requirement val7 in array7)
						{
							if (val7.m_upgraderResource)
							{
								val7.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader2Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_KnifeChitin");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_KnifeSkollAndHati")
					{
						Requirement[] resources8 = item.m_resources;
						Requirement[] array8 = resources8;
						foreach (Requirement val8 in array8)
						{
							if (val8.m_upgraderResource)
							{
								val8.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader5Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_KnifeSkollAndHati");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_FistweaponGold")
					{
						Requirement[] resources9 = item.m_resources;
						Requirement[] array9 = resources9;
						foreach (Requirement val9 in array9)
						{
							if (val9.m_upgraderResource)
							{
								val9.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader7Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_FistweaponGold");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_AxeEarly")
					{
						Requirement[] resources10 = item.m_resources;
						Requirement[] array10 = resources10;
						foreach (Requirement val10 in array10)
						{
							if (val10.m_upgraderResource)
							{
								val10.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader1Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_AxeEarly");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_BowDraugrFang")
					{
						Requirement[] resources11 = item.m_resources;
						Requirement[] array11 = resources11;
						foreach (Requirement val11 in array11)
						{
							if (val11.m_upgraderResource)
							{
								val11.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader3Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_BowDraugrFang");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_AxeIron")
					{
						Requirement[] resources12 = item.m_resources;
						Requirement[] array12 = resources12;
						foreach (Requirement val12 in array12)
						{
							if (val12.m_upgraderResource)
							{
								val12.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader2Weapon").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_AxeIron");
								}
							}
						}
					}
					if (!PatchVanillaCapes.Value)
					{
						continue;
					}
					if (((Object)item).name == "Recipe_CapeLinen")
					{
						Requirement[] resources13 = item.m_resources;
						Requirement[] array13 = resources13;
						foreach (Requirement val13 in array13)
						{
							if (val13.m_upgraderResource)
							{
								val13.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader0Armor").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_CapeLinen");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_CapeLox")
					{
						Requirement[] resources14 = item.m_resources;
						Requirement[] array14 = resources14;
						foreach (Requirement val14 in array14)
						{
							if (val14.m_upgraderResource)
							{
								val14.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader0Armor").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_CapeLox");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_CapeTrollHide")
					{
						Requirement[] resources15 = item.m_resources;
						Requirement[] array15 = resources15;
						foreach (Requirement val15 in array15)
						{
							if (val15.m_upgraderResource)
							{
								val15.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader0Armor").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_CapeTrollHide");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_CapeWolf")
					{
						Requirement[] resources16 = item.m_resources;
						Requirement[] array16 = resources16;
						foreach (Requirement val16 in array16)
						{
							if (val16.m_upgraderResource)
							{
								val16.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader0Armor").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_CapeWolf");
								}
							}
						}
					}
					if (((Object)item).name == "Recipe_CapeFeather")
					{
						Requirement[] resources17 = item.m_resources;
						Requirement[] array17 = resources17;
						foreach (Requirement val17 in array17)
						{
							if (val17.m_upgraderResource)
							{
								val17.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader0Armor").GetComponent<ItemDrop>();
								if (EnableDebugLogging.Value)
								{
									Logger.LogInfo((object)"Patched Recipe_CapeFeather");
								}
							}
						}
					}
					if (!(((Object)item).name == "Recipe_CapeAsksvin"))
					{
						continue;
					}
					Requirement[] resources18 = item.m_resources;
					Requirement[] array18 = resources18;
					foreach (Requirement val18 in array18)
					{
						if (val18.m_upgraderResource)
						{
							val18.m_resItem = PrefabManager.Instance.GetPrefab("Upgrader0Armor").GetComponent<ItemDrop>();
							if (EnableDebugLogging.Value)
							{
								Logger.LogInfo((object)"Patched Recipe_CapeAsksvin");
							}
						}
					}
				}
			}
		}

		public static class UpgradeHelper
		{
			[Serializable]
			public sealed class ChanceEntry
			{
				public int Level;

				public float UpgradeChance;

				public float BreakChance;
			}

			[Serializable]
			public sealed class ChanceConfiguration
			{
				public ChanceEntry[] Entries;
			}

			private static readonly List<ChanceEntry> ChanceEntries = new List<ChanceEntry>();

			private const string ChanceFileName = "upgrade_chances.json";

			private static readonly (string EnemyId, int Tier, string Name)[] BossTiers = new(string, int, string)[8]
			{
				("$enemy_frozenking_p3", 8, "Kall Fimbulbringer"),
				("$enemy_fader", 7, "Fader"),
				("$enemy_seekerqueen", 6, "Queen"),
				("$enemy_goblinking", 5, "Yagluth"),
				("$enemy_dragon", 4, "Moder"),
				("$enemy_bonemass", 3, "Bonemass"),
				("$enemy_gdking", 2, "Elder"),
				("$enemy_eikthyr", 1, "Eikthyr")
			};

			public static int GetMaxBossTier()
			{
				Dictionary<string, float> dictionary = Game.instance.GetPlayerProfile().m_playerStats[0].m_enemyStats[0];
				(string, int, string)[] bossTiers = BossTiers;
				for (int i = 0; i < bossTiers.Length; i++)
				{
					var (key, result, arg) = bossTiers[i];
					if (dictionary.TryGetValue(key, out var value))
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)$"GetMaxBossTier: {arg} defeated: {value}");
						}
						return result;
					}
				}
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)"GetMaxBossTier: No bosses defeated.");
				}
				return 0;
			}

			public static int GetEquipmentTier(string prefabName)
			{
				if (string.IsNullOrEmpty(prefabName))
				{
					return -2;
				}
				if (prefabName.Contains("Upgrader7"))
				{
					return 7;
				}
				if (prefabName.Contains("Upgrader6"))
				{
					return 6;
				}
				if (prefabName.Contains("Upgrader5"))
				{
					return 5;
				}
				if (prefabName.Contains("Upgrader4"))
				{
					return 4;
				}
				if (prefabName.Contains("Upgrader3"))
				{
					return 3;
				}
				if (prefabName.Contains("Upgrader2"))
				{
					return 2;
				}
				if (prefabName.Contains("Upgrader1"))
				{
					return 1;
				}
				if (prefabName.Contains("Upgrader0"))
				{
					return 0;
				}
				return -1;
			}

			public static int GetMaxUpgradeLevel(int itemTier, int highestBossTier)
			{
				int num = BaseUpgradeLimit.Value;
				int num2 = itemTier + 1;
				for (int i = num2; i <= highestBossTier; i++)
				{
					if (bossUpgradeValues.TryGetValue(i, out var value))
					{
						num += value;
					}
				}
				if (itemTier == highestBossTier && AllowExtraUpgradeLimitOnCurrentTier.Value)
				{
					num++;
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)$"GetMaxUpgradeLevel: itemTier={itemTier} matches highestBossTier={highestBossTier}, adding +1.");
					}
				}
				return num;
			}

			public static int GetRequiredBossForNextUpgrade(int itemTier, int currentUpgrade)
			{
				if (EnableLevelCap.Value)
				{
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)"GetRequiredBossForNextUpgrade: Level cap is enabled. Returning -1.");
					}
					return -1;
				}
				int num = BaseUpgradeLimit.Value;
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)$"GetRequiredBossForNextUpgrade: itemTier={itemTier}, currentUpgrade={currentUpgrade}, base={num}");
				}
				for (int i = itemTier + 1; bossUpgradeValues.ContainsKey(i); i++)
				{
					int num2 = bossUpgradeValues[i];
					num += num2;
					string text = (bossNames.ContainsKey(i) ? bossNames[i] : "<unknown>");
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)$"Checking bossTier={i}, bossValue={num2}, cumulativeUpgrade={num} (bossName={text})");
					}
					if (currentUpgrade < num)
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)$"Next required bossTier={i} ({text}) to unlock upgrades beyond {currentUpgrade}.");
						}
						return i;
					}
				}
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)$"No boss tier found that unlocks upgrades beyond currentUpgrade={currentUpgrade}. cumulativeUpgrade={num}");
				}
				return -1;
			}

			public static int GetEquivalentTier(int baseItemTier, int qualityLevel, int? highestBossTier = null)
			{
				int num = ((bossUpgradeValues != null && bossUpgradeValues.Count > 0) ? bossUpgradeValues.Keys.Max() : 0);
				int num2 = highestBossTier ?? num;
				if (baseItemTier > num2)
				{
					baseItemTier = num2;
				}
				int maxUpgradeLevel = GetMaxUpgradeLevel(baseItemTier, num2);
				int num3 = maxUpgradeLevel - qualityLevel;
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)($"GetEquivalentTier: baseTier={baseItemTier}, " + $"quality={qualityLevel}, " + $"currentMax={maxUpgradeLevel}, " + $"distanceFromMax={num3}, " + $"maxBossTier={num2}"));
				}
				for (int num4 = num2; num4 >= 0; num4--)
				{
					int maxUpgradeLevel2 = GetMaxUpgradeLevel(num4, num2);
					int num5 = maxUpgradeLevel2 - num3;
					if (num5 >= 1 && num5 <= maxUpgradeLevel2)
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)($"GetEquivalentTier: baseTier={baseItemTier}, " + $"quality={qualityLevel} => " + $"candidateTier={num4}, " + $"candidateQuality={num5}"));
						}
						return num4;
					}
				}
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)("GetEquivalentTier: no equivalent tier found for " + $"baseTier={baseItemTier}, quality={qualityLevel}; " + "returning baseTier."));
				}
				return baseItemTier;
			}

			public static Dictionary<string, int> GetTotalIdolCosts(string originalResource, int currentQuality, int startLevelToCalculateFrom)
			{
				Dictionary<string, int> dictionary = new Dictionary<string, int>();
				if (string.IsNullOrEmpty(originalResource) || currentQuality <= 1 || startLevelToCalculateFrom > currentQuality)
				{
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)("GetTotalIdolCosts: invalid input. originalResource=" + originalResource + ", " + $"currentQuality={currentQuality}, " + $"startLevelToCalculateFrom={startLevelToCalculateFrom}. " + "Returning empty idolCosts."));
					}
					return dictionary;
				}
				int equipmentTier = GetEquipmentTier(originalResource);
				if (equipmentTier < 0)
				{
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)("GetTotalIdolCosts: baseTier < 0 for originalResource=" + originalResource + ". Returning empty idolCosts."));
					}
					return dictionary;
				}
				string arg;
				if (originalResource.Contains("Weapon"))
				{
					arg = "Weapon";
				}
				else
				{
					if (!originalResource.Contains("Armor"))
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)("GetTotalIdolCosts: originalResource=" + originalResource + " is neither Weapon nor Armor. Returning empty idolCosts."));
						}
						return dictionary;
					}
					arg = "Armor";
				}
				int configuredMaxBoss = ((bossUpgradeValues != null && bossUpgradeValues.Count > 0) ? bossUpgradeValues.Keys.Max() : 8);
				int num = Math.Max(1, startLevelToCalculateFrom);
				for (int i = num; i < currentQuality; i++)
				{
					GetEquivalentUpgradeValues(equipmentTier, i, configuredMaxBoss, out var equivalentTier, out var candidateQuality);
					int upgradeCost = GetUpgradeCost(candidateQuality);
					string key = $"Upgrader{equivalentTier}{arg}";
					if (dictionary.ContainsKey(key))
					{
						dictionary[key] += upgradeCost;
					}
					else
					{
						dictionary.Add(key, upgradeCost);
					}
				}
				return dictionary;
			}

			public static int GetUpgradeCost(int candidateQuality)
			{
				int num = Math.Max(0, candidateQuality - 1);
				int num2 = Math.Max(1, CostScalingLevelStart.Value);
				int num3 = CostStart.Value;
				if (CostIncreaseInterval.Value > 0 && num >= num2)
				{
					num3 += ((num - num2) / CostIncreaseInterval.Value + 1) * CostIncreasePerInterval.Value;
				}
				return num3;
			}

			public static void GetEquivalentUpgradeValues(int baseTier, int qualityLevel, int configuredMaxBoss, out int equivalentTier, out int candidateQuality)
			{
				if (!EnableBossProgression.Value && !EnableIdolProgression.Value)
				{
					equivalentTier = baseTier;
					int maxUpgradeLevel = GetMaxUpgradeLevel(baseTier, configuredMaxBoss);
					candidateQuality = Math.Max(1, Math.Min(maxUpgradeLevel, qualityLevel));
				}
				else if (!EnableBossProgression.Value && EnableIdolProgression.Value)
				{
					int num = Math.Max(0, (qualityLevel - 1) / 4);
					int val = baseTier + num;
					int val2 = ((bossUpgradeValues != null && bossUpgradeValues.Count > 0) ? bossUpgradeValues.Keys.Max() : 8);
					val = Math.Min(val, val2);
					int num2 = Math.Max(0, val - baseTier);
					equivalentTier = val;
					candidateQuality = qualityLevel - num2 * 4;
					candidateQuality = Math.Max(1, Math.Min(4, candidateQuality));
				}
				else if (EnableBossProgression.Value && !EnableIdolProgression.Value)
				{
					equivalentTier = baseTier;
					int maxUpgradeLevel = GetMaxUpgradeLevel(baseTier, configuredMaxBoss);
					candidateQuality = Math.Max(1, Math.Min(maxUpgradeLevel, qualityLevel));
				}
				else
				{
					equivalentTier = GetEquivalentTier(baseTier, qualityLevel, configuredMaxBoss);
					int maxUpgradeLevel2 = GetMaxUpgradeLevel(baseTier, configuredMaxBoss);
					int maxUpgradeLevel = GetMaxUpgradeLevel(equivalentTier, configuredMaxBoss);
					int num3 = maxUpgradeLevel2 - qualityLevel;
					candidateQuality = maxUpgradeLevel - num3;
					candidateQuality = Math.Max(1, Math.Min(maxUpgradeLevel, candidateQuality));
				}
			}

			public static void LoadChanceConfiguration(string pluginLocation)
			{
				ChanceEntries.Clear();
				string directoryName = Path.GetDirectoryName(pluginLocation);
				string text = Path.Combine(directoryName, "upgrade_chances.json");
				try
				{
					if (!File.Exists(text))
					{
						ChanceConfiguration chanceConfiguration = new ChanceConfiguration
						{
							Entries = (from level in Enumerable.Range(1, 10)
								select new ChanceEntry
								{
									Level = level,
									UpgradeChance = UpgradeChance.Value,
									BreakChance = BreakChance.Value
								}).ToArray()
						};
					}
					string input = File.ReadAllText(text);
					MatchCollection matchCollection = Regex.Matches(input, "\\{[^{}]*\"Level\"\\s*:\\s*(?<level>-?\\d+)[^{}]*\"UpgradeChance\"\\s*:\\s*(?<upgradeChance>-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)[^{}]*\"BreakChance\"\\s*:\\s*(?<breakChance>-?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:[eE][+-]?\\d+)?)\\s*\\}", RegexOptions.IgnoreCase);
					foreach (Match item in matchCollection)
					{
						if (int.TryParse(item.Groups["level"].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) && float.TryParse(item.Groups["upgradeChance"].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result2) && float.TryParse(item.Groups["breakChance"].Value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result3) && result > 0)
						{
							ChanceEntries.Add(new ChanceEntry
							{
								Level = result,
								UpgradeChance = result2,
								BreakChance = result3
							});
						}
					}
					ChanceEntries.Sort((ChanceEntry left, ChanceEntry right) => left.Level.CompareTo(right.Level));
				}
				catch (Exception arg)
				{
					Logger.LogError((object)string.Format("Failed to load {0}: {1}", "upgrade_chances.json", arg));
				}
				if (ChanceEntries.Count == 0)
				{
					ChanceEntries.Add(new ChanceEntry
					{
						Level = 1,
						UpgradeChance = UpgradeChance.Value,
						BreakChance = BreakChance.Value
					});
					if (EnableDebugLogging.Value)
					{
						Logger.LogWarning((object)"upgrade_chances.json did not contain any valid entries. Using the configured global chances.");
					}
				}
				if (EnableDebugLogging.Value && EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)$"Loaded {ChanceEntries.Count} chance entries from {text}.");
				}
			}

			private static ChanceEntry GetChanceEntry(int qualityLevel)
			{
				if (ChanceEntries.Count == 0)
				{
					if (EnableDebugLogging.Value)
					{
						Logger.LogWarning((object)"GetChanceEntry: No chance entries loaded. Using default chances.");
					}
					return new ChanceEntry
					{
						Level = 1,
						UpgradeChance = UpgradeChance.Value,
						BreakChance = BreakChance.Value
					};
				}
				ChanceEntry result = ChanceEntries[0];
				foreach (ChanceEntry chanceEntry in ChanceEntries)
				{
					if (chanceEntry.Level > qualityLevel)
					{
						break;
					}
					result = chanceEntry;
				}
				return result;
			}

			public static float GetUpgradeChance(int qualityLevel)
			{
				return GetChanceEntry(qualityLevel).UpgradeChance;
			}

			public static float GetBreakChance(int qualityLevel)
			{
				return GetChanceEntry(qualityLevel).BreakChance;
			}
		}

		public const string PluginGUID = "akuichi.ReforgedPotential";

		public const string PluginName = "Reforged Potential";

		public const string PluginVersion = "2.0.10";

		private readonly Harmony harmony = new Harmony("akuichi.ReforgedPotential");

		internal static ConfigEntry<bool> EnableServerSync;

		internal static ConfigEntry<bool> EnableBossProgression;

		internal static ConfigEntry<int> BaseUpgradeLimit;

		internal static ConfigEntry<int> Boss1MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss2MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss3MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss4MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss5MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss6MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss7MaxUpgradeLevel;

		internal static ConfigEntry<int> Boss8MaxUpgradeLevel;

		internal static ConfigEntry<bool> AllowExtraUpgradeLimitOnCurrentTier;

		internal static Dictionary<int, int> bossUpgradeValues;

		internal static Dictionary<int, string> bossNames = new Dictionary<int, string>
		{
			{ -1, "No More Further Boss" },
			{ 0, "No Boss Defeated" },
			{ 1, "Eikthyr" },
			{ 2, "Elder" },
			{ 3, "Bonemass" },
			{ 4, "Moder" },
			{ 5, "Yagluth" },
			{ 6, "Queen" },
			{ 7, "Fader" },
			{ 8, "Kall Fimbulbringer" }
		};

		internal static ConfigEntry<bool> EnableIdolProgression;

		internal static ConfigEntry<bool> EnableRecipes;

		internal static ConfigEntry<string> Recipe_Upgrader0Armor;

		internal static ConfigEntry<string> Recipe_Upgrader0Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader1Armor;

		internal static ConfigEntry<string> Recipe_Upgrader1Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader2Armor;

		internal static ConfigEntry<string> Recipe_Upgrader2Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader3Armor;

		internal static ConfigEntry<string> Recipe_Upgrader3Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader4Armor;

		internal static ConfigEntry<string> Recipe_Upgrader4Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader5Armor;

		internal static ConfigEntry<string> Recipe_Upgrader5Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader6Armor;

		internal static ConfigEntry<string> Recipe_Upgrader6Weapon;

		internal static ConfigEntry<string> Recipe_Upgrader7Armor;

		internal static ConfigEntry<string> Recipe_Upgrader7Weapon;

		internal static ConfigEntry<string> Station_Global;

		internal static ConfigEntry<float> UpgradeChance;

		internal static ConfigEntry<float> BreakChance;

		internal static ConfigEntry<bool> UseCustomChances;

		internal static ConfigEntry<bool> ConsumeIdolsOnlyOnFailure;

		internal static ConfigEntry<int> CostStart;

		internal static ConfigEntry<int> CostIncreaseInterval;

		internal static ConfigEntry<int> CostIncreasePerInterval;

		internal static ConfigEntry<int> CostScalingLevelStart;

		internal static ConfigEntry<float> UpgradeBaseDuration;

		internal static ConfigEntry<float> UpgradeDurationIncreasePerLevel;

		internal static ConfigEntry<bool> RefundIdolsOnBreak;

		internal static ConfigEntry<int> RefundIdolsOnBreakStartingLevel;

		internal static ConfigEntry<float> RefundIdolsPercentageOnBreak;

		internal static ConfigEntry<bool> EnableLevelCap;

		internal static ConfigEntry<int> LevelCap;

		internal static ConfigEntry<bool> EnableGlobalUpgradeNotifications;

		internal static ConfigEntry<string> SuccessMessage;

		internal static ConfigEntry<string> FailedMessage;

		internal static ConfigEntry<bool> PatchVanillaUpgraderRecipes;

		internal static ConfigEntry<bool> PatchVanillaCapes;

		internal static ConfigEntry<bool> EnableDebugLogging;

		internal static CustomRPC RPC_Reforged;

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			//IL_0028: Expected O, but got Unknown
			RPC_Reforged = NetworkManager.Instance.AddRPC("RPC_Reforged", new CoroutineHandler(RPC_ReforgedServerReceive), new CoroutineHandler(RPC_ReforgedClientReceive));
			LoadConfig();
			CreateConfigWatcher();
			SynchronizationManager.OnConfigurationSynchronized += delegate(object obj, ConfigurationSynchronizationEventArgs attr)
			{
				LoadConfig();
				SyncRecipes();
				if (attr.InitialSynchronization)
				{
					Logger.LogMessage((object)"Initial Config sync event received");
				}
				else
				{
					Logger.LogMessage((object)"Config synced from server");
				}
			};
			PrefabManager.OnVanillaPrefabsAvailable += AddConfigurableRecipes;
			harmony.PatchAll();
		}

		private void Start()
		{
			EpicLootCompatibility.Init();
		}

		private IEnumerator RPC_ReforgedServerReceive(long sender, ZPackage package)
		{
			RPC_Reforged.SendPackage(ZNet.instance.m_peers, new ZPackage(package.GetArray()));
			string message = package.ReadString();
			if (message != "")
			{
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)("[SERVER] Adding message to chat: " + message));
				}
				ChatHelpers.ResetChatHideTimer();
				((Terminal)Chat.instance).AddString("Forge of Potential", message, (Type)2, false);
			}
			yield return null;
		}

		private IEnumerator RPC_ReforgedClientReceive(long sender, ZPackage package)
		{
			Logger.LogMessage((object)"Received blob, processing");
			string message = package.ReadString();
			if (message != "")
			{
				ChatHelpers.ResetChatHideTimer();
				((Terminal)Chat.instance).AddString("Forge of Potential", message, (Type)2, false);
			}
			yield return null;
		}

		public static void BroadcastUpgradeResult(string playerName, string itemName, int level, bool success)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			if (EnableGlobalUpgradeNotifications.Value)
			{
				string text = (success ? SuccessMessage.Value : FailedMessage.Value);
				string text2 = text.Replace("{PlayerName}", playerName).Replace("{ItemName}", itemName).Replace("{Level}", level.ToString());
				ZPackage val = new ZPackage();
				val.Write(text2);
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)("Broadcasting upgrade result: " + text2));
				}
				RPC_Reforged.SendPackage(ZRoutedRpc.instance.GetServerPeerID(), val);
			}
		}

		private void CreateConfigWatcher()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Expected O, but got Unknown
			ConfigFileWatcher val = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L);
			val.OnConfigFileReloaded += delegate
			{
				LoadConfig();
			};
		}

		private void LoadConfig()
		{
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			EnableServerSync = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Server Only", "Enable Server Sync", true, "If true, config values are synchronized from server to clients.", true, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			bool value = EnableServerSync.Value;
			EnableGlobalUpgradeNotifications = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Global Notifications", "Enable Global Upgrade Notifications", false, "Broadcast a message to all online players when someone attempts an upgrade.", value, (int?)3, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			SuccessMessage = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Global Notifications", "Success Message", "{PlayerName} successfully upgraded {ItemName} to level {Level}.", "Message shown on successful upgrade. Supports {PlayerName}, {ItemName}, {Level}.", value, (int?)2, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			FailedMessage = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Global Notifications", "Failed Message", "{PlayerName} tried to upgrade {ItemName} to level {Level}, but failed.", "Message shown on failed upgrade. Supports {PlayerName}, {ItemName}, {Level}.", value, (int?)1, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			AcceptableValueRange<float> val = new AcceptableValueRange<float>(0f, 1f);
			UpgradeChance = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Upgrade Chance", 1f, "Chance for an upgrade to succeed.", value, (int?)20, (AcceptableValueBase)(object)val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			BreakChance = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Break Chance", 0f, "When an upgrade fails, this is the chance for it to break (Ex. 1 = Item will always break on upgrade failure, 0 = Item will just degrade 1 level on upgrade failure)", value, (int?)20, (AcceptableValueBase)(object)val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UseCustomChances = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Use Custom Chances from Json file", false, "If true, you can map out custom values for upgrade/break chances per level. If false, the default upgrade chances will be used (See upgrade_chances.json)", value, (int?)19, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			ConsumeIdolsOnlyOnFailure = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Consume Idols Only On Failure", false, "If true, idols are just consumed and the item doesn't lose a level (Breaking still removes the item)", value, (int?)18, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			AcceptableValueRange<int> val2 = new AcceptableValueRange<int>(0, 1000);
			CostStart = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Cost Start", 1, "Base idol cost for upgrades. (Game Default is 1)", value, (int?)17, (AcceptableValueBase)(object)val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			CostIncreasePerInterval = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Cost Increase Per Interval", 1, "Additional ingredient cost each time the cost scaling interval is reached starting at CostScalingLevelStart. (Starting at level X, the upgrade cost increases by this amount every Y levels. For example, with an increase of 1 every 2 levels starting at level 6: levels 1–5 cost 1, levels 6–7 cost 2, levels 8–9 cost 3, and so on.)", value, (int?)16, (AcceptableValueBase)(object)val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			CostIncreaseInterval = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Cost Increase Interval", 1, "Number of levels between each cost increase. Set to 0 to disable cost scaling.", value, (int?)15, (AcceptableValueBase)(object)val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			CostScalingLevelStart = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Cost Scaling Level Start", 1, "Level after at which cost scaling starts.", value, (int?)14, (AcceptableValueBase)(object)val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			val = new AcceptableValueRange<float>(0f, 100f);
			UpgradeBaseDuration = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Upgrade Crafting Time Base Duration", 2f, "Base crafting duration for upgrading. This is the base time it takes to upgrade an equipment (Game Default is 8)", value, (int?)13, (AcceptableValueBase)(object)val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UpgradeDurationIncreasePerLevel = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Upgrade Crafting Time Duration Increase Per Level", 1f, "Additional crafting duration per item level. This is the additional time added per item level to the total crafting time. (Game Default is 1)", value, (int?)12, (AcceptableValueBase)(object)val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			RefundIdolsOnBreak = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Refund Idols On Break", false, "If true, a percentage of the idols used are refunded when an equipment breaks", value, (int?)11, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			RefundIdolsOnBreakStartingLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Refund Idols On Break Starting Level", 5, "Calculation of the refunded idols starts at this level. (Ex. at value 5: Levels 1-4 are not included for the idol refund calculations)", value, (int?)10, (AcceptableValueBase)(object)val2, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			val = new AcceptableValueRange<float>(0f, 1f);
			RefundIdolsPercentageOnBreak = ConfigFileExtensions.BindConfig<float>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Refund Idols Percentage On Break", 0.3f, "Percentage of idols refunded when an equipment breaks.", value, (int?)9, (AcceptableValueBase)(object)val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableLevelCap = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Enable Level Cap", false, "If true, a level cap is enforced for all equipment upgrades (This takes precedence over boss upgrade limits)", value, (int?)8, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			LevelCap = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Upgrade Settings", "Level Cap", 10, "The maximum level that an equipment can be upgraded to if Enable Level Cap is set to true.", value, (int?)8, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableBossProgression = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Boss Progression", "Enable Boss Progression", true, "If true, upgrades are limited by boss progression. Defeat bosses to unlock higher upgrade levels.", value, (int?)10, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			BaseUpgradeLimit = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Base Upgrade Limit", 5, "Base upgrade limit for all items before any additional calculations are made", value, (int?)9, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss1MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 1 Max Upgrade Level", 4, "Additional max upgrade level unlocked for wooden tier after defeating Eikthyr.", value, (int?)8, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss2MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 2 Max Upgrade Level", 4, "Additional max upgrade level unlocked for bronze tier and below after defeating Elder.", value, (int?)8, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss3MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 3 Max Upgrade Level", 4, "Additional max upgrade level unlocked for iron tier and below after defeating Bonemass.", value, (int?)7, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss4MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 4 Max Upgrade Level", 4, "Additional max upgrade level unlocked for silver tier and below after defeating Moder.", value, (int?)6, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss5MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 5 Max Upgrade Level", 4, "Additional max upgrade level unlocked for black metal tier and below after defeating Yagluth.", value, (int?)5, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss6MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 6 Max Upgrade Level", 4, "Additional max upgrade level unlocked for black marble tier and below after defeating Queen.", value, (int?)4, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss7MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 7 Max Upgrade Level", 4, "Additional max upgrade level unlocked for flametal tier and below after defeating Fader.", value, (int?)3, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Boss8MaxUpgradeLevel = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "Boss Progression", "Boss 8 Max Upgrade Level", 100, "Additional max upgrade level unlocked for bloodgold tier and below after defeating Kall Fimbulbringer.", value, (int?)2, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			bossUpgradeValues = new Dictionary<int, int>
			{
				{ 0, 0 },
				{ 1, Boss1MaxUpgradeLevel.Value },
				{ 2, Boss2MaxUpgradeLevel.Value },
				{ 3, Boss3MaxUpgradeLevel.Value },
				{ 4, Boss4MaxUpgradeLevel.Value },
				{ 5, Boss5MaxUpgradeLevel.Value },
				{ 6, Boss6MaxUpgradeLevel.Value },
				{ 7, Boss7MaxUpgradeLevel.Value },
				{ 8, Boss8MaxUpgradeLevel.Value }
			};
			AllowExtraUpgradeLimitOnCurrentTier = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Boss Progression", "Allow Extra Upgrade Limit On Current Tier", true, "If true, the current boss tier will allow for an extra upgrade limit on the current tier. (Ex. If you have defeated Eikthyr, you can upgrade Bronze tier items one level past the base limit)", value, (int?)1, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableIdolProgression = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Idol Progression", "Enable Idol Progression", true, "If true, the required idol to upgrade an equipment will change to match it's current equivalent item tier and level (If boss progression is off, tiers will change every 4 levels)", value, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Station_Global = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Crafting Station", "Global Station", "piece_artisanstation", "Global crafting station for all configurable upgrader recipes. Use station m_name (e.g. 'piece_workbench').", value, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableRecipes = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Recipes", "Enable Recipes", true, "Enable or disable all idol crafting recipes.", value, (int?)20, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader0Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Wooden Protection Idol", "Wood:50,GreydwarfEye:10", "Ingredients for Wooden Protection Idol: comma-separated entries 'PrefabName:Amount'.", value, (int?)19, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader0Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Wooden Battle Idol", "Wood:50,GreydwarfEye:10", "Ingredients for Wooden Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)18, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader1Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Bronze Protection Idol", "Bronze:10,SurtlingCore:1", "Ingredients for Bronze Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)17, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader1Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Bronze Battle Idol", "Bronze:10,SurtlingCore:1", "Ingredients for Bronze Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)16, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader2Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Iron Protection Idol", "Iron:10,ElderBark:5", "Ingredients for Iron Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)15, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader2Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Iron Battle Idol", "Iron:10,ElderBark:5", "Ingredients for Iron Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)14, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader3Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Silver Protection Idol", "Silver:10,FreezeGland:5,Obsidian:5", "Ingredients for Silver Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)13, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader3Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Silver Battle Idol", "Silver:10,FreezeGland:5,Obsidian:5", "Ingredients for Silver Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)12, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader4Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Black Metal Protection Idol", "BlackMetal:10,Needle:2,Tar:5", "Ingredients for Black Metal Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)11, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader4Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Black Metal Battle Idol", "BlackMetal:10,Needle:2,Tar:5", "Ingredients for Black Metal Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)10, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader5Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Black Marble Protection Idol", "BlackMarble:20,BugMeat:10,Carapace:10", "Ingredients for Black Marble Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)9, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader5Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Black Marble Battle Idol", "BlackMarble:20,BugMeat:10,Carapace:10", "Ingredients for Black Marble Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)8, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader6Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Flametal Protection Idol", "FlametalNew:10,CharredBone:15", "Ingredients for Flametal Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)7, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader6Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Flametal Battle Idol", "FlametalNew:10,CharredBone:15", "Ingredients for Flametal Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)6, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader7Armor = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Bloodgold Protection Idol", "Gold:10,Coins:40,AncientCoin:10", "Ingredients for Bloodgold Protection Idol: comma-separated 'PrefabName:Amount'.", value, (int?)5, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			Recipe_Upgrader7Weapon = ConfigFileExtensions.BindConfig<string>(((BaseUnityPlugin)this).Config, "Recipes", "Bloodgold Battle Idol", "Gold:10,Coins:40,AncientCoin:10", "Ingredients for Bloodgold Battle Idol: comma-separated 'PrefabName:Amount'.", value, (int?)4, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			PatchVanillaUpgraderRecipes = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Vanilla Recipe Fixes", "Patch Vanilla Upgrader Recipes", true, "If true, some known recipes that uses the wrong upgrader resources will be patched; (Ex. Headdress of the Bear will now ask for Bronze Protection Idol instead of Black Marble Protection Idol)", value, (int?)3, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			PatchVanillaCapes = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Vanilla Recipe Fixes", "Patch Vanilla Capes", true, "If true, capes that start with 1 armor will now use the Wooden Idol as its base; (Affected: Linen Cape, Lox Cape, Troll Cape, Wolf Cape)", value, (int?)2, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			EnableDebugLogging = ConfigFileExtensions.BindConfig<bool>(((BaseUnityPlugin)this).Config, "Logging", "Enable Debug Logging", false, "Show debug logging", false, (int?)null, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null);
			UpgradeHelper.LoadChanceConfiguration(((BaseUnityPlugin)this).Info.Location);
			((BaseUnityPlugin)this).Config.Save();
		}

		private void AddConfigurableRecipes()
		{
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_024c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Expected O, but got Unknown
			//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Expected O, but got Unknown
			try
			{
				(string, ConfigEntry<string>)[] array = new(string, ConfigEntry<string>)[16]
				{
					("Upgrader0Armor", Recipe_Upgrader0Armor),
					("Upgrader0Weapon", Recipe_Upgrader0Weapon),
					("Upgrader1Armor", Recipe_Upgrader1Armor),
					("Upgrader1Weapon", Recipe_Upgrader1Weapon),
					("Upgrader2Armor", Recipe_Upgrader2Armor),
					("Upgrader2Weapon", Recipe_Upgrader2Weapon),
					("Upgrader3Armor", Recipe_Upgrader3Armor),
					("Upgrader3Weapon", Recipe_Upgrader3Weapon),
					("Upgrader4Armor", Recipe_Upgrader4Armor),
					("Upgrader4Weapon", Recipe_Upgrader4Weapon),
					("Upgrader5Armor", Recipe_Upgrader5Armor),
					("Upgrader5Weapon", Recipe_Upgrader5Weapon),
					("Upgrader6Armor", Recipe_Upgrader6Armor),
					("Upgrader6Weapon", Recipe_Upgrader6Weapon),
					("Upgrader7Armor", Recipe_Upgrader7Armor),
					("Upgrader7Weapon", Recipe_Upgrader7Weapon)
				};
				int num = 0;
				(string, ConfigEntry<string>)[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					(string, ConfigEntry<string>) tuple = array2[i];
					string item = tuple.Item1;
					string text = tuple.Item2?.Value?.Trim();
					if (string.IsNullOrEmpty(text))
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)("AddConfigurableRecipes: '" + item + "' configuration is empty, skipping."));
						}
						continue;
					}
					string craftingStation = (string.IsNullOrEmpty(Station_Global.Value.Trim().Trim(new char[1] { '$' })) ? null : Station_Global.Value.Trim().Trim(new char[1] { '$' }));
					RecipeConfig val = new RecipeConfig
					{
						Name = "RFG_" + item,
						Item = item,
						CraftingStation = craftingStation,
						Enabled = EnableRecipes.Value,
						MinStationLevel = 1
					};
					bool flag = false;
					string[] array3 = text.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
					string[] array4 = array3;
					foreach (string text2 in array4)
					{
						string text3 = text2.Trim();
						if (string.IsNullOrEmpty(text3))
						{
							continue;
						}
						string[] array5 = text3.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries);
						if (array5.Length != 2)
						{
							Logger.LogWarning((object)("AddConfigurableRecipes: invalid token '" + text3 + "' for '" + item + "'. Use 'PrefabName:Amount'."));
							continue;
						}
						string text4 = array5[0].Trim();
						if (!int.TryParse(array5[1].Trim(), out var result) || result <= 0)
						{
							Logger.LogWarning((object)("AddConfigurableRecipes: invalid amount in token '" + text3 + "' for '" + item + "'. Must be positive integer."));
						}
						else
						{
							val.AddRequirement(text4, result, 0);
							flag = true;
						}
					}
					if (!flag)
					{
						Logger.LogWarning((object)("AddConfigurableRecipes: no valid ingredients for '" + item + "' from '" + text + "'; skipping."));
						continue;
					}
					ItemManager.Instance.AddRecipe(new CustomRecipe(val));
					num++;
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)("AddConfigurableRecipes: added recipe for '" + item + "' (requirements: " + text + ")."));
					}
				}
				if (EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)$"AddConfigurableRecipes: finished. Added {num} configurable recipe(s).");
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"AddConfigurableRecipes exception: {arg}");
			}
		}

		private void SyncRecipes()
		{
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Expected O, but got Unknown
			try
			{
				(string, ConfigEntry<string>)[] array = new(string, ConfigEntry<string>)[16]
				{
					("Upgrader0Armor", Recipe_Upgrader0Armor),
					("Upgrader0Weapon", Recipe_Upgrader0Weapon),
					("Upgrader1Armor", Recipe_Upgrader1Armor),
					("Upgrader1Weapon", Recipe_Upgrader1Weapon),
					("Upgrader2Armor", Recipe_Upgrader2Armor),
					("Upgrader2Weapon", Recipe_Upgrader2Weapon),
					("Upgrader3Armor", Recipe_Upgrader3Armor),
					("Upgrader3Weapon", Recipe_Upgrader3Weapon),
					("Upgrader4Armor", Recipe_Upgrader4Armor),
					("Upgrader4Weapon", Recipe_Upgrader4Weapon),
					("Upgrader5Armor", Recipe_Upgrader5Armor),
					("Upgrader5Weapon", Recipe_Upgrader5Weapon),
					("Upgrader6Armor", Recipe_Upgrader6Armor),
					("Upgrader6Weapon", Recipe_Upgrader6Weapon),
					("Upgrader7Armor", Recipe_Upgrader7Armor),
					("Upgrader7Weapon", Recipe_Upgrader7Weapon)
				};
				string text = (string.IsNullOrEmpty(Station_Global.Value.Trim().Trim(new char[1] { '$' })) ? "" : Station_Global.Value.Trim().Trim(new char[1] { '$' }));
				GameObject prefab = PrefabManager.Instance.GetPrefab(text);
				CraftingStation craftingStation = ((prefab != null) ? prefab.GetComponent<CraftingStation>() : null);
				(string, ConfigEntry<string>)[] array2 = array;
				for (int i = 0; i < array2.Length; i++)
				{
					(string, ConfigEntry<string>) tuple = array2[i];
					string item = tuple.Item1;
					string text2 = tuple.Item2?.Value?.Trim();
					if (string.IsNullOrEmpty(text2))
					{
						if (EnableDebugLogging.Value)
						{
							Logger.LogInfo((object)("SyncRecipes: '" + item + "' configuration is empty, skipping."));
						}
						continue;
					}
					Recipe recipe = ItemManager.Instance.GetRecipe("RFG_" + item).Recipe;
					recipe.m_item = PrefabManager.Instance.GetPrefab(item).GetComponent<ItemDrop>();
					recipe.m_craftingStation = craftingStation;
					recipe.m_enabled = EnableRecipes.Value;
					List<Requirement> list = new List<Requirement>();
					bool flag = false;
					string[] array3 = text2.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
					string[] array4 = array3;
					foreach (string text3 in array4)
					{
						string text4 = text3.Trim();
						if (string.IsNullOrEmpty(text4))
						{
							continue;
						}
						string[] array5 = text4.Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries);
						if (array5.Length != 2)
						{
							Logger.LogWarning((object)("SyncRecipes: invalid token '" + text4 + "' for '" + item + "'. Use 'PrefabName:Amount'."));
							continue;
						}
						string text5 = array5[0].Trim();
						if (!int.TryParse(array5[1].Trim(), out var result) || result <= 0)
						{
							Logger.LogWarning((object)("SyncRecipes: invalid amount in token '" + text4 + "' for '" + item + "'. Must be positive integer."));
						}
						else
						{
							Requirement val = new Requirement();
							GameObject prefab2 = PrefabManager.Instance.GetPrefab(text5);
							val.m_resItem = ((prefab2 != null) ? prefab2.GetComponent<ItemDrop>() : null);
							val.m_amount = result;
							list.Add(val);
							flag = true;
						}
					}
					if (!flag)
					{
						Logger.LogWarning((object)("SyncRecipes: no valid ingredients for '" + item + "' from '" + text2 + "'; skipping."));
						continue;
					}
					recipe.m_resources = list.ToArray();
					if (EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)("SyncRecipes: updated recipe for '" + item + "' (requirements: " + text2 + ")."));
					}
				}
			}
			catch (Exception arg)
			{
				Logger.LogError((object)$"SyncRecipes exception: {arg}");
			}
		}
	}
	public sealed class UpgradeCalculationSettings
	{
		public int BaseUpgradeLimit { get; set; }

		public int CostStart { get; set; }

		public int CostIncreaseInterval { get; set; }

		public int CostIncreasePerInterval { get; set; }

		public int CostScalingLevelStart { get; set; }

		public bool EnableBossProgression { get; set; }

		public bool EnableIdolProgression { get; set; }
	}
	public sealed class UpgradeCalculations
	{
		private readonly UpgradeCalculationSettings settings;

		private readonly IReadOnlyDictionary<int, int> bossUpgradeValues;

		public UpgradeCalculations(UpgradeCalculationSettings settings, IReadOnlyDictionary<int, int> bossUpgradeValues)
		{
			this.settings = settings ?? throw new ArgumentNullException("settings");
			this.bossUpgradeValues = bossUpgradeValues ?? throw new ArgumentNullException("bossUpgradeValues");
		}

		public int GetEquipmentTier(string prefabName)
		{
			if (string.IsNullOrEmpty(prefabName))
			{
				return -2;
			}
			for (int num = 7; num >= 0; num--)
			{
				if (prefabName.Contains($"Upgrader{num}"))
				{
					return num;
				}
			}
			return -1;
		}

		public int GetMaxUpgradeLevel(int itemTier, int highestBossTier)
		{
			int num = settings.BaseUpgradeLimit;
			for (int i = itemTier + 1; i <= highestBossTier; i++)
			{
				if (bossUpgradeValues.TryGetValue(i, out var value))
				{
					num += value;
				}
			}
			if (itemTier == highestBossTier)
			{
				num++;
			}
			return num;
		}

		public int GetRequiredBossForNextUpgrade(int itemTier, int currentUpgrade)
		{
			int num = settings.BaseUpgradeLimit;
			for (int i = itemTier + 1; bossUpgradeValues.ContainsKey(i); i++)
			{
				num += bossUpgradeValues[i];
				if (currentUpgrade < num)
				{
					return i;
				}
			}
			return -1;
		}

		public int GetUpgradeCost(int candidateQuality)
		{
			int num = Math.Max(0, candidateQuality - 1);
			int num2 = Math.Max(1, settings.CostScalingLevelStart);
			int num3 = settings.CostStart;
			if (settings.CostIncreaseInterval > 0 && num >= num2)
			{
				num3 += ((num - num2) / settings.CostIncreaseInterval + 1) * settings.CostIncreasePerInterval;
			}
			return num3;
		}

		public void GetEquivalentUpgradeValues(int baseTier, int qualityLevel, int configuredMaxBoss, out int equivalentTier, out int candidateQuality)
		{
			if (!settings.EnableBossProgression && !settings.EnableIdolProgression)
			{
				equivalentTier = baseTier;
				int maxUpgradeLevel = GetMaxUpgradeLevel(baseTier, configuredMaxBoss);
				candidateQuality = Math.Max(1, Math.Min(maxUpgradeLevel, qualityLevel));
			}
			else if (!settings.EnableBossProgression && settings.EnableIdolProgression)
			{
				int num = Math.Max(0, (qualityLevel - 1) / 4);
				int val = bossUpgradeValues.Keys.Max();
				equivalentTier = Math.Min(baseTier + num, val);
				int num2 = Math.Max(0, equivalentTier - baseTier);
				candidateQuality = qualityLevel - num2 * 4;
				candidateQuality = Math.Max(1, Math.Min(4, candidateQuality));
			}
			else if (settings.EnableBossProgression && !settings.EnableIdolProgression)
			{
				equivalentTier = baseTier;
				int maxUpgradeLevel2 = GetMaxUpgradeLevel(baseTier, configuredMaxBoss);
				candidateQuality = Math.Max(1, Math.Min(maxUpgradeLevel2, qualityLevel));
			}
			else
			{
				equivalentTier = GetEquivalentTier(baseTier, qualityLevel, configuredMaxBoss);
				int maxUpgradeLevel3 = GetMaxUpgradeLevel(baseTier, configuredMaxBoss);
				int maxUpgradeLevel4 = GetMaxUpgradeLevel(equivalentTier, configuredMaxBoss);
				int num3 = maxUpgradeLevel3 - qualityLevel;
				candidateQuality = maxUpgradeLevel4 - num3;
				candidateQuality = Math.Max(1, Math.Min(maxUpgradeLevel4, candidateQuality));
			}
		}

		private int GetEquivalentTier(int baseItemTier, int qualityLevel, int highestBossTier)
		{
			if (baseItemTier > highestBossTier)
			{
				baseItemTier = highestBossTier;
			}
			int maxUpgradeLevel = GetMaxUpgradeLevel(baseItemTier, highestBossTier);
			int num = maxUpgradeLevel - qualityLevel;
			for (int num2 = highestBossTier; num2 >= 0; num2--)
			{
				int maxUpgradeLevel2 = GetMaxUpgradeLevel(num2, highestBossTier);
				int num3 = maxUpgradeLevel2 - num;
				if (num3 >= 1 && num3 <= maxUpgradeLevel2)
				{
					return num2;
				}
			}
			return baseItemTier;
		}
	}
}
namespace ReforgedPotential.Compatibility
{
	public static class EpicLootCompatibility
	{
		private const string EpicLootGuid = "randyknapp.mods.epicloot";

		private static bool _isEpicLootLoaded;

		public static void Init()
		{
			if (Chainloader.PluginInfos.TryGetValue("randyknapp.mods.epicloot", out var value) && ((value != null) ? value.Instance : null) != null)
			{
				if (!EpicLoot.IsLoaded())
				{
					Logger.LogWarning((object)"[ReforgedPotential] EpicLoot detected but not loaded. Disabling compatibility.");
					return;
				}
				_isEpicLootLoaded = true;
				Logger.LogInfo((object)"[ReforgedPotential] EpicLoot detected. Enabling compatibility.");
			}
		}

		internal static bool TryCopyMagicItem(ItemData sourceItem, ItemData craftedItem)
		{
			if (!_isEpicLootLoaded)
			{
				if (ReforgedPotential.EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)"EpicLoot is not installed, skipping..");
				}
				return false;
			}
			if (sourceItem == null || craftedItem == null)
			{
				if (ReforgedPotential.EnableDebugLogging.Value)
				{
					Logger.LogInfo((object)"Source or crafted item is null, skipping..");
				}
				return false;
			}
			if (sourceItem.IsMagicItem())
			{
				MagicItem magicItem = sourceItem.GetMagicItem();
				if (craftedItem.ApplyMagicItem(magicItem))
				{
					if (ReforgedPotential.EnableDebugLogging.Value)
					{
						Logger.LogInfo((object)"[ReforgedPotential] Successfully copied EpicLoot magic item data.");
					}
					return true;
				}
			}
			if (ReforgedPotential.EnableDebugLogging.Value)
			{
				Logger.LogInfo((object)"[ReforgedPotential] No EpicLoot magic item data found to copy.");
			}
			return false;
		}
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EpicLootAPI
{
	[Serializable]
	[PublicAPI]
	internal enum AbilityActivationMode
	{
		Passive,
		Triggerable,
		Activated
	}
	[Serializable]
	[PublicAPI]
	internal enum AbilityAction
	{
		Custom,
		StatusEffect
	}
	[Serializable]
	[PublicAPI]
	internal class AbilityDefinition
	{
		public string ID = "";

		public string IconAsset = "";

		public AbilityActivationMode ActivationMode;

		public float Cooldown;

		public AbilityAction Action;

		public List<string> ActionParams = new List<string>();

		internal static readonly Method API_AddAbility = new Method("AddAbility");

		internal static readonly Method API_UpdateAbility = new Method("UpdateAbility");

		internal static List<AbilityDefinition> Abilities = new List<AbilityDefinition>();

		[Description("Register a status effect ability which activates on player input")]
		public AbilityDefinition(string ID, string iconAsset, float cooldown, string statusEffectName)
		{
			this.ID = ID;
			ActivationMode = AbilityActivationMode.Activated;
			Cooldown = cooldown;
			Action = AbilityAction.StatusEffect;
			ActionParams.Add(statusEffectName);
			IconAsset = iconAsset;
			Abilities.Add(this);
		}

		internal AbilityDefinition(string ID, AbilityActivationMode mode)
		{
			this.ID = ID;
			ActivationMode = mode;
		}

		public AbilityDefinition()
		{
		}

		public static void RegisterAll()
		{
			foreach (AbilityDefinition item in new List<AbilityDefinition>(Abilities))
			{
				item.Register();
			}
		}

		public bool Register()
		{
			string text = JsonConvert.SerializeObject((object)this);
			object[] array = API_AddAbility.Invoke(text);
			if (!(array[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(this, value);
			Abilities.Remove(this);
			EpicLoot.logger.LogDebug("Registered ability: " + ID);
			return true;
		}

		public bool Update()
		{
			if (!RunTimeRegistry.TryGetValue(this, out string value))
			{
				return false;
			}
			string text = JsonConvert.SerializeObject((object)this);
			object[] array = API_UpdateAbility.Invoke(value, text);
			bool flag = (bool)(array[0] ?? ((object)false));
			EpicLoot.logger.LogDebug($"Updated ability {ID}: {flag}");
			return flag;
		}
	}
	[PublicAPI]
	internal class AbilityProxyDefinition
	{
		public readonly AbilityDefinition Ability;

		public readonly Dictionary<string, Delegate> Callbacks = new Dictionary<string, Delegate>();

		internal static readonly List<AbilityProxyDefinition> ProxyAbilities = new List<AbilityProxyDefinition>();

		internal static readonly Method API_RegisterProxyAbility = new Method("RegisterProxyAbility");

		internal static readonly Method API_UpdateProxyAbility = new Method("UpdateProxyAbility");

		[Description("Register a complex ability behavior using Proxy class")]
		public AbilityProxyDefinition(string ID, AbilityActivationMode mode, Proxy definition)
		{
			Ability = new AbilityDefinition(ID, mode);
			RegisterCallbacks(definition);
			ProxyAbilities.Add(this);
		}

		[Description("Register a complex ability behavior using Proxy class")]
		public AbilityProxyDefinition(string ID, AbilityActivationMode mode, Type type)
		{
			Ability = new AbilityDefinition(ID, mode);
			if (!typeof(Proxy).IsAssignableFrom(type))
			{
				EpicLoot.logger.LogError("Ability Proxy " + ID + " Type " + type.Name + " does not implement Proxy class");
				return;
			}
			try
			{
				object obj = Activator.CreateInstance(type);
				RegisterCallbacks((Proxy)obj);
				ProxyAbilities.Add(this);
			}
			catch (Exception ex)
			{
				EpicLoot.logger.LogError("Failed to create instance of " + type.Name + ": " + ex.Message);
			}
		}

		private void RegisterCallbacks(Proxy implementation)
		{
			Type type = implementation.GetType();
			Type typeFromHandle = typeof(Proxy);
			MethodInfo[] methods = typeFromHandle.GetMethods();
			MethodInfo[] array = methods;
			foreach (MethodInfo methodInfo in array)
			{
				try
				{
					Type[] array2 = (from p in methodInfo.GetParameters()
						select p.ParameterType).ToArray();
					MethodInfo method = type.GetMethod(methodInfo.Name, array2);
					if (method == null)
					{
						EpicLoot.logger.LogWarning("Method " + methodInfo.Name + " not found in implementation");
						continue;
					}
					Type type2;
					if (methodInfo.ReturnType == typeof(void))
					{
						type2 = ((array2.Length != 0) ? Expression.GetActionType(array2) : typeof(Action));
					}
					else
					{
						Type[] typeArgs = array2.Concat(new Type[1] { methodInfo.ReturnType }).ToArray();
						type2 = Expression.GetFuncType(typeArgs);
					}
					Delegate value = Delegate.CreateDelegate(type2, implementation, method);
					Callbacks[methodInfo.Name] = value;
				}
				catch (Exception ex)
				{
					EpicLoot.logger.LogError("Failed to register callback for method " + methodInfo.Name + ": " + ex.Message);
				}
			}
		}

		public static void RegisterAll()
		{
			foreach (AbilityProxyDefinition item in new List<AbilityProxyDefinition>(ProxyAbilities))
			{
				item.Register();
			}
		}

		public bool Register()
		{
			string text = JsonConvert.SerializeObject((object)Ability);
			object[] array = API_RegisterProxyAbility.Invoke(text, Callbacks);
			if (!(array[0] is string value))
			{
				return false;
			}
			RunTimeRegistry.Register(this, value);
			ProxyAbilities.Remove(this);
			EpicLoot.logger.LogDebug("Registered proxy ability: " + Ability.ID);
			return true;
		}

		public bool Update()
		{
			if (!RunTimeRegistry.TryGetValue(this, out string value))
			{
				return false;
			}
			string text = JsonConvert.SerializeObject((object)Ability);
			object[] array = API_UpdateProxyAbility.Invoke(value, text, Callbacks);
			bool flag = (bool)(array[0] ?? ((object)false));
			EpicLoot.logger.LogDebug($"Updated proxy ability: {Ability.ID}, {flag}");
			return flag;
		}
	}
	[Description("Functions are converted into delegates when registered to epic loot")]
	[PublicAPI]
	internal class Proxy
	{
		protected Player Player;

		public string AbilityID = "";

		public float Cooldown;

		public virtual string CooldownEndKey => "EpicLoot." + AbilityID + ".CooldownEnd";

		public virtual void Initialize(Player player, string id, float cooldown)
		{
			Player = player;
			AbilityID = id;
			Cooldown = cooldown;
		}

		public virtual void OnUpdate()
		{
		}

		public virtual bool ShouldTrigger()
		{
			return false;
		}

		public virtual bool IsOnCooldown()
		{
			if (HasCooldown())
			{
				return GetTime() < GetCooldownEndTime();
			}
			return false;
		}

		public virtual float TimeUntilCooldownEnds()
		{
			return Mathf.Max(0f, GetCooldownEndTime() - GetTime());
		}

		public virtual float PercentCooldownComplete()
		{
			if (HasCooldown() && IsOnCooldown())
			{
				return 1f - TimeUntilCooldownEnds() / Cooldown;
			}
			return 1f;
		}

		public virtual bool CanActivate()
		{
			return !IsOnCooldown();
		}

		public virtual void TryActivate()
		{
			if (CanActivate())
			{
				Activate();
			}
		}

		public virtual void Activate()
		{
			if (HasCooldown())
			{
				float cooldownEndTime = GetTime() + Cooldown;
				SetCooldownEndTime(cooldownEndTime);
			}
		}

		public virtual void ActivateCustomAction()
		{
		}

		public virtual void ActivateStatusEffectAction()
		{
		}

		public virtual bool HasCooldown()
		{
			return Cooldown > 0f;
		}

		public virtual void SetCooldownEndTime(float cooldownEndTime)
		{
			if (!((Object)(object)Player == (Object)null))
			{
				((Character)Player).m_nview.GetZDO().Set(CooldownEndKey, cooldownEndTime);
			}
		}

		public virtual float GetCooldownEndTime()
		{
			if ((Object)(object)Player == (Object)null)
			{
				return 0f;
			}
			return ((Character)Player).m_nview.GetZDO().GetFloat(CooldownEndKey, 0f);
		}

		public virtual void OnRemoved()
		{
		}

		protected static float GetTime()
		{
			return (float)ZNet.instance.GetTimeSeconds();
		}
	}
	internal static class EpicLoot
	{
		[PublicAPI]
		public static class ChangeReason
		{
			public const string Enchant = "Enchant";

			public const string Augment = "Augment";

			public const string Disenchant = "Disenchant";

			public const string Rune = "Rune";

			public const string Temper = "Temper";

			public const string Socket = "Socket";

			public const string Unsocket = "Unsocket";

			public const string LootRoll = "LootRoll";

			public const string Transfer = "Transfer";

			public const string AddSocket = "AddSocket";

			public const string Unspecified = "Unspecified";
		}

		public static readonly Logger logger = new Logger();

		private static readonly Method API_GetTotalActiveMagicEffectValue = new Method("GetTotalActiveMagicEffectValue");

		private static readonly Method API_GetTotalActiveMagicEffectValueForWeapon = new Method("GetTotalActiveMagicEffectValueForWeapon");

		private static readonly Method API_HasActiveMagicEffect = new Method("HasActiveMagicEffect");

		private static readonly Method API_HasActiveMagicEffectOnWeapon = new Method("HasActiveMagicEffectOnWeapon");

		private static readonly Method API_GetTotalActiveSetEffectValue = new Method("GetTotalActiveSetEffectValue");

		private static readonly Method API_GetAllActiveMagicEffects = new Method("GetAllActiveMagicEffects");

		private static readonly Method API_GetAllSetMagicEffects = new Method("GetAllActiveSetMagicEffects");

		private static readonly Method API_GetPlayerTotalActiveMagicEffectValue = new Method("GetTotalPlayerActiveMagicEffectValue");

		private static readonly Method API_PlayerHasActiveMagicEffect = new Method("PlayerHasActiveMagicEffect");

		private static readonly Method API_HasLegendaryItem = new Method("HasLegendaryItem");

		private static readonly Method API_HasLegendarySet = new Method("HasLegendarySet");

		private static readonly Method API_RegisterAsset = new Method("RegisterAsset");

		private static readonly Method API_GetMagicItemJson = new Method("GetMagicItemJson");

		private static readonly Method API_RegisterMagicEffectRequirement = new Method("RegisterMagicEffectRequirement", typeof(string), typeof(Func<ItemData, object, string, bool, bool, bool, bool>));

		private static readonly Method API_AddMagicItemChangedListener = new Method("AddMagicItemChangedListener", typeof(Action<ItemData, string>));

		private static readonly Method API_RemoveMagicItemChangedListener = new Method("RemoveMagicItemChangedListener", typeof(Action<ItemData, string>));

		private static readonly Method API_AddLootGeneratedListener = new Method("AddLootGeneratedListener", typeof(Action<ItemData>));

		private static readonly Method API_RemoveLootGeneratedListener = new Method("RemoveLootGeneratedListener", typeof(Action<ItemData>));

		private static readonly Method API_AddBountyCompletedListener = new Method("AddBountyCompletedListener", typeof(Action<Player, string>));

		private static readonly Method API_RemoveBountyCompletedListener = new Method("RemoveBountyCompletedListener", typeof(Action<Player, string>));

		private static readonly Method API_TryMakeMagicItem = new Method("TryMakeMagicItem");

		private static readonly Method API_RollMagicItemJson = new Method("RollMagicItemJson");

		private static readonly Method API_ApplyMagicItemJson = new Method("ApplyMagicItemJson");

		private static readonly Method API_GetLuckFactor = new Method("GetLuckFactor");

		private static readonly Method API_RollEffectCountForRarity = new Method("RollEffectCountForRarity");

		private static readonly Method API_GetLegendaryIDs = new Method("GetLegendaryIDs");

		private static readonly Method API_GetLegendaryInfoJson = new Method("GetLegendaryInfoJson");

		private static readonly Method API_GetAvailableEffectTypes = new Method("GetAvailableEffectTypes");

		private static readonly Method API_AddLootTables = new Method("AddLootTables");

		private static readonly Method API_UpdateLootTables = new Method("UpdateLootTables");

		private static readonly Method API_RegisterInventoryProvider = new Method("RegisterInventoryProvider", typeof(string), typeof(Func<List<ItemData>>), typeof(Func<string, int>), typeof(Func<string, int, int>), typeof(Func<ItemData, int, int>));

		private static readonly Method API_UnregisterInventoryProvider = new Method("UnregisterInventoryProvider");

		private static readonly Method API_RegisterEquipmentProv