Decompiled source of NokepArmorSets v1.5.0

plugins\NokepArmorSets.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using NokepCommon;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("JotunnModStub")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("JotunnModStub")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.5.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.0.0")]
namespace NokepCommon
{
	internal static class Icons
	{
		private static readonly Dictionary<string, Sprite> cache = new Dictionary<string, Sprite>();

		public static Sprite Get(string name)
		{
			if (cache.TryGetValue(name, out var value))
			{
				return value;
			}
			Sprite val = Load(name);
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)("Иконка " + name + " не загрузилась"));
			}
			cache[name] = val;
			return val;
		}

		private static Sprite Load(string name)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string text = executingAssembly.GetName().Name + ".Assets." + name.Replace("/", ".") + ".png";
			using Stream stream = executingAssembly.GetManifestResourceStream(text);
			if (stream == null)
			{
				Logger.LogWarning((object)("Не нашёл ресурс " + text));
				return null;
			}
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = AssetUtils.LoadImage(array);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}

		public static void LogResourceNames()
		{
			string[] manifestResourceNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
			Logger.LogInfo((object)("Встроенные ресурсы: " + string.Join(", ", manifestResourceNames)));
		}
	}
	internal static class Translations
	{
		private static readonly string[] Languages = new string[3] { "English", "Russian", "German" };

		public static void Load()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			Assembly executingAssembly = Assembly.GetExecutingAssembly();
			string name = executingAssembly.GetName().Name;
			string[] languages = Languages;
			foreach (string text in languages)
			{
				string text2 = name + ".Translations." + text + ".strings.json";
				using Stream stream = executingAssembly.GetManifestResourceStream(text2);
				if (stream == null)
				{
					Logger.LogWarning((object)("Не нашёл перевод " + text2));
					continue;
				}
				using StreamReader streamReader = new StreamReader(stream);
				localization.AddJsonFile(text, streamReader.ReadToEnd());
			}
		}

		public static string Get(string text)
		{
			return Localization.instance.Localize(text);
		}
	}
	internal static class NokepUtils
	{
		public static Dictionary<string, int> ParseRecipe(string text)
		{
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			if (string.IsNullOrEmpty(text))
			{
				return dictionary;
			}
			string[] array = text.Split(new char[1] { ',' });
			for (int i = 0; i < array.Length; i++)
			{
				string[] array2 = array[i].Trim().Split(new char[1] { ':' });
				if (array2.Length == 2)
				{
					string text2 = array2[0].Trim();
					if (text2.Length != 0 && int.TryParse(array2[1].Trim(), out var result) && result >= 1)
					{
						dictionary[text2] = result;
					}
				}
			}
			return dictionary;
		}
	}
	internal enum DamageGroup
	{
		Melee,
		Ranged,
		Magic
	}
	internal static class DamageGroups
	{
		private static readonly Dictionary<DamageGroup, HashSet<SkillType>> GroupSkills = new Dictionary<DamageGroup, HashSet<SkillType>>
		{
			[DamageGroup.Melee] = new HashSet<SkillType>
			{
				(SkillType)1,
				(SkillType)2,
				(SkillType)3,
				(SkillType)7,
				(SkillType)4,
				(SkillType)5,
				(SkillType)11
			},
			[DamageGroup.Ranged] = new HashSet<SkillType>
			{
				(SkillType)8,
				(SkillType)14
			},
			[DamageGroup.Magic] = new HashSet<SkillType>
			{
				(SkillType)9,
				(SkillType)10
			}
		};

		private static readonly Dictionary<int, Dictionary<DamageGroup, float>> Bonuses = new Dictionary<int, Dictionary<DamageGroup, float>>();

		public static void Set(StatusEffect effect, DamageGroup group, float percent)
		{
			int key = effect.NameHash();
			if (!Bonuses.TryGetValue(key, out var value))
			{
				value = (Bonuses[key] = new Dictionary<DamageGroup, float>());
			}
			if (percent == 0f)
			{
				value.Remove(group);
			}
			else
			{
				value[group] = percent;
			}
		}

		public static IEnumerable<KeyValuePair<DamageGroup, float>> Get(StatusEffect effect)
		{
			if (Bonuses.TryGetValue(effect.NameHash(), out var value))
			{
				return value;
			}
			return new KeyValuePair<DamageGroup, float>[0];
		}

		public static float Multiplier(StatusEffect effect, SkillType skill)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!Bonuses.TryGetValue(effect.NameHash(), out var value))
			{
				return 1f;
			}
			float num = 0f;
			foreach (KeyValuePair<DamageGroup, float> item in value)
			{
				if (GroupSkills[item.Key].Contains(skill))
				{
					num += item.Value;
				}
			}
			return 1f + num / 100f;
		}
	}
	[HarmonyPatch(typeof(SE_Stats), "ModifyAttack")]
	internal static class DamageGroups_ModifyAttack
	{
		private static void Postfix(SE_Stats __instance, SkillType skill, ref HitData hitData)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			float num = DamageGroups.Multiplier((StatusEffect)(object)__instance, skill);
			if (num != 1f)
			{
				((DamageTypes)(ref hitData.m_damage)).Modify(num);
			}
		}
	}
}
namespace JotunnModStub
{
	internal static class Armor
	{
		public static void AddAll()
		{
			foreach (ArmorSet set in Plugin.Sets)
			{
				AddEffect(set);
				AddPart(set, set.HelmetPrefab, set.VanillaHelmet, set.ItemName("helmet"), set.CfgHelmet, set.IconName("Helmet"));
				AddPart(set, set.ChestPrefab, set.VanillaChest, set.ItemName("chest"), set.CfgChest, set.IconName("Chest"));
				AddPart(set, set.LegsPrefab, set.VanillaLegs, set.ItemName("legs"), set.CfgLegs, set.IconName("Legs"));
			}
		}

		public static void RefreshEffects()
		{
			foreach (ArmorSet set in Plugin.Sets)
			{
				if ((Object)(object)set.Effect != (Object)null)
				{
					ApplyConfigValues(set.Effect, set);
				}
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			foreach (StatusEffect active in ((Character)Player.m_localPlayer).GetSEMan().GetStatusEffects())
			{
				StatusEffect obj = active;
				SE_Stats val = (SE_Stats)(object)((obj is SE_Stats) ? obj : null);
				if (val != null)
				{
					ArmorSet armorSet = Plugin.Sets.Find((ArmorSet s) => (Object)(object)s.Effect != (Object)null && s.EffectHash == active.NameHash());
					if (armorSet != null)
					{
						ApplyConfigValues(val, armorSet);
					}
				}
			}
		}

		private static void ApplyConfigValues(SE_Stats effect, ArmorSet set)
		{
			((StatusEffect)effect).m_tooltip = BuildTooltip(set);
			effect.m_addArmor = ((set.Bonus == "Armored") ? set.CfgBonus.Value : 0f);
			float num = ((set.CfgSpeed != null) ? (set.CfgSpeed.Value / 100f) : 0f);
			float num2 = set.RunStamina / 100f;
			if (set.Bonus == "Stamina")
			{
				effect.m_runStaminaDrainModifier = num + num2;
				return;
			}
			effect.m_speedModifier = num;
			effect.m_runStaminaDrainModifier = num2;
		}

		private static void AddEffect(ArmorSet set)
		{
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			SE_Stats val = ScriptableObject.CreateInstance<SE_Stats>();
			((Object)val).name = set.EffectName;
			((StatusEffect)val).m_name = set.EffectDisplayName;
			ApplyConfigValues(val, set);
			if (set.HealthRegen != 0f)
			{
				val.m_healthRegenMultiplier = 1f + set.HealthRegen / 100f;
			}
			if (set.StaminaRegen != 0f)
			{
				val.m_staminaRegenMultiplier = 1f + set.StaminaRegen / 100f;
			}
			val.m_addMaxCarryWeight = set.CarryWeight;
			val.m_jumpStaminaUseModifier = set.JumpStamina / 100f;
			val.m_blockStaminaUseModifier = set.BlockStamina / 100f;
			val.m_sneakStaminaUseModifier = set.SneakStamina / 100f;
			val.m_attackStaminaUseModifier = set.AttackStamina / 100f;
			val.m_dodgeStaminaUseModifier = set.DodgeStamina / 100f;
			if (set.EitrRegen != 0f)
			{
				val.m_eitrRegenMultiplier = 1f + set.EitrRegen / 100f;
			}
			if (set.Skill1.HasValue)
			{
				val.m_skillLevel = set.Skill1.Value;
				val.m_skillLevelModifier = set.Skill1Level;
				if (set.Skill2.HasValue)
				{
					val.m_skillLevel2 = set.Skill2.Value;
					val.m_skillLevelModifier2 = set.Skill2Level;
				}
			}
			if (set.WeaponSkill.HasValue)
			{
				val.m_modifyAttackSkill = set.WeaponSkill.Value;
				val.m_damageModifier = 1f + set.WeaponDamage / 100f;
			}
			if (set.ResistType.HasValue)
			{
				val.m_mods.Add(new DamageModPair
				{
					m_type = set.ResistType.Value,
					m_modifier = (DamageModifier)1
				});
			}
			set.Effect = val;
			set.EffectHash = ((StatusEffect)val).NameHash();
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val, false));
		}

		private static string BuildTooltip(ArmorSet set)
		{
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			float value = set.CfgBonus.Value;
			string text;
			switch (set.Bonus)
			{
			case "Vitality":
				text = $"+{value:0} $nokep_bonus_health";
				break;
			case "Armored":
				text = $"+{value:0} $nokep_bonus_armor";
				break;
			case "Magic":
				text = $"+{value:0} $nokep_bonus_eitr";
				break;
			case "Stamina":
				text = $"+{value:0} $nokep_bonus_stamina";
				break;
			default:
				return "";
			}
			if (set.CfgSpeed != null && set.CfgSpeed.Value != 0f)
			{
				float value2 = set.CfgSpeed.Value;
				text = ((!(set.Bonus == "Stamina")) ? (text + $"\n{value2:+0;-0}% $nokep_bonus_speed") : (text + $"\n{value2:+0;-0}% $nokep_bonus_run_stamina"));
			}
			if (set.WeaponSkill.HasValue && set.WeaponDamage != 0f)
			{
				text += $"\n{set.WeaponDamage:+0;-0}% $nokep_bonus_damage: $skill_{((object)set.WeaponSkill.Value/*cast due to .constrained prefix*/).ToString().ToLower()}";
			}
			return text;
		}

		private static float MagicItemEitrRegen(int biomeLevel)
		{
			if (biomeLevel <= 2)
			{
				return 0.02f;
			}
			if (biomeLevel <= 4)
			{
				return 0.04f;
			}
			if (biomeLevel <= 6)
			{
				return 0.06f;
			}
			return 0.08f;
		}

		private static void AddPart(ArmorSet set, string prefabName, string vanillaPrefab, string displayName, ConfigEntry<string> recipeFromConfig, string iconName)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			CustomItem val = new CustomItem(prefabName, vanillaPrefab);
			val.ItemDrop.m_itemData.m_shared.m_name = displayName;
			val.ItemDrop.m_itemData.m_shared.m_description = set.ItemDescription;
			Sprite val2 = Icons.Get(iconName);
			if ((Object)(object)val2 != (Object)null)
			{
				val.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 };
			}
			if (set.Bonus == "Magic")
			{
				float num = MagicItemEitrRegen(StationLevel.ForSet(set));
				SharedData shared = val.ItemDrop.m_itemData.m_shared;
				if (shared.m_eitrRegenModifier < num)
				{
					shared.m_eitrRegenModifier = num;
				}
			}
			val.ItemDrop.m_itemData.m_shared.m_setName = set.SetName;
			val.ItemDrop.m_itemData.m_shared.m_setSize = 3;
			val.ItemDrop.m_itemData.m_shared.m_setStatusEffect = (StatusEffect)(object)set.Effect;
			if (!ItemManager.Instance.AddItem(val))
			{
				Logger.LogError((object)("Не удалось добавить " + prefabName));
			}
			else
			{
				Recipes.Add(set, prefabName, vanillaPrefab, recipeFromConfig);
			}
		}
	}
	internal static class BenchModel
	{
		private const string BundleName = "nokep_bench";

		private const string ModelName = "nokep_bench_model";

		private static readonly int MainTex = Shader.PropertyToID("_MainTex");

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		public static void Apply(GameObject prefab, Material material)
		{
			AssetBundle val = AssetUtils.LoadAssetBundleFromResources("nokep_bench", Assembly.GetExecutingAssembly());
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"Модель верстака: не загрузился архив nokep_bench");
				return;
			}
			GameObject val2 = val.LoadAsset<GameObject>("nokep_bench_model");
			if ((Object)(object)val2 == (Object)null)
			{
				Logger.LogWarning((object)"Модель верстака: в архиве нет nokep_bench_model");
				return;
			}
			WearNTear component = prefab.GetComponent<WearNTear>();
			int layer = prefab.layer;
			Renderer[] componentsInChildren;
			if ((Object)(object)component != (Object)null)
			{
				if ((Object)(object)component.m_new != (Object)null)
				{
					layer = component.m_new.layer;
				}
				GameObject[] array = (GameObject[])(object)new GameObject[3] { component.m_new, component.m_worn, component.m_broken };
				foreach (GameObject val3 in array)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						componentsInChildren = val3.GetComponentsInChildren<Renderer>(true);
						for (int j = 0; j < componentsInChildren.Length; j++)
						{
							componentsInChildren[j].enabled = false;
						}
					}
				}
			}
			GameObject val4 = Object.Instantiate<GameObject>(val2, prefab.transform, false);
			((Object)val4).name = "nokep_bench_model";
			Transform[] componentsInChildren2 = val4.GetComponentsInChildren<Transform>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Component)componentsInChildren2[i]).gameObject.layer = layer;
			}
			int num = 0;
			componentsInChildren = val4.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val5 in componentsInChildren)
			{
				if ((Object)(object)material != (Object)null)
				{
					Material[] sharedMaterials = val5.sharedMaterials;
					for (int k = 0; k < sharedMaterials.Length; k++)
					{
						sharedMaterials[k] = WithValheimShader(material, sharedMaterials[k]);
					}
					val5.sharedMaterials = sharedMaterials;
				}
				num++;
			}
			Logger.LogInfo((object)string.Format("Модель верстака из архива подключена: частей {0}, шейдер {1}", num, ((Object)(object)material != (Object)null) ? ((Object)material.shader).name : "из архива"));
		}

		private static Material WithValheimShader(Material valheim, Material fromBundle)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			Texture val = (((Object)(object)fromBundle != (Object)null && fromBundle.HasProperty(MainTex)) ? fromBundle.GetTexture(MainTex) : null);
			if ((Object)(object)val == (Object)null)
			{
				return valheim;
			}
			Material val2 = new Material(valheim)
			{
				name = "nokep_bench (" + ((Object)val).name + ")"
			};
			string[] texturePropertyNames = val2.GetTexturePropertyNames();
			foreach (string text in texturePropertyNames)
			{
				if (text != "_MainTex")
				{
					val2.SetTexture(text, (Texture)null);
				}
			}
			val2.SetTexture(MainTex, val);
			if (val2.HasProperty(ColorId))
			{
				val2.SetColor(ColorId, Color.white);
			}
			Logger.LogInfo((object)($"Модель верстака: текстура {((Object)val).name} ({val.width}x{val.height}) на шейдере {((Object)val2.shader).name}; " + "убраны текстуры: " + string.Join(", ", Array.FindAll(val2.GetTexturePropertyNames(), (string p) => p != "_MainTex"))));
			return val2;
		}
	}
	internal static class CapeItems
	{
		public static void AddAll()
		{
			foreach (Cape cape in Plugin.Capes)
			{
				Add(cape);
			}
		}

		private static void Add(Cape cape)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Invalid comparison between Unknown and I4
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			CustomItem val = new CustomItem(cape.Prefab, cape.Vanilla);
			SharedData shared = val.ItemDrop.m_itemData.m_shared;
			shared.m_name = cape.ItemName;
			shared.m_description = "$nokep_cape_desc";
			Sprite val2 = Icons.Get(cape.IconName);
			if ((Object)(object)val2 != (Object)null)
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { val2 };
			}
			if (cape.ItemEitrRegen > shared.m_eitrRegenModifier)
			{
				shared.m_eitrRegenModifier = cape.ItemEitrRegen;
			}
			if (cape.FireInsteadOfFrost)
			{
				List<DamageModPair> list = new List<DamageModPair>();
				foreach (DamageModPair damageModifier in shared.m_damageModifiers)
				{
					DamageModPair current = damageModifier;
					if ((int)current.m_type == 64)
					{
						current.m_type = (DamageType)32;
					}
					list.Add(current);
				}
				shared.m_damageModifiers = list;
			}
			StatusEffect equipStatusEffect = shared.m_equipStatusEffect;
			SE_Stats val3 = (SE_Stats)(object)((equipStatusEffect is SE_Stats) ? equipStatusEffect : null);
			SE_Stats val4;
			if (val3 != null)
			{
				val4 = Object.Instantiate<SE_Stats>(val3);
			}
			else
			{
				if ((Object)(object)shared.m_equipStatusEffect != (Object)null)
				{
					Logger.LogWarning((object)("У " + cape.Vanilla + " эффект не SE_Stats — ванильный эффект не сохранится"));
				}
				val4 = ScriptableObject.CreateInstance<SE_Stats>();
			}
			((Object)val4).name = cape.EffectName;
			((StatusEffect)val4).m_name = "$nokep_role_" + cape.Role.ToLower();
			if ((Object)(object)val2 != (Object)null)
			{
				((StatusEffect)val4).m_icon = val2;
			}
			cape.Effect = val4;
			cape.VanillaTooltip = ((StatusEffect)val4).m_tooltip;
			ApplyValues(val4, cape);
			ItemManager.Instance.AddStatusEffect(new CustomStatusEffect((StatusEffect)(object)val4, false));
			shared.m_equipStatusEffect = (StatusEffect)(object)val4;
			if (!ItemManager.Instance.AddItem(val))
			{
				Logger.LogError((object)("Не удалось добавить " + cape.Prefab));
			}
			else
			{
				Recipes.Add(StationLevel.ForFolder(cape.IconFolder), cape.CfgResources, cape.Prefab, cape.Vanilla, cape.CfgRecipe);
			}
		}

		private static void ApplyValues(SE_Stats effect, Cape cape)
		{
			float value = cape.CfgDamage.Value;
			float value2 = cape.CfgExtra.Value;
			string role = cape.Role;
			DamageGroup damageGroup;
			if (!(role == "Warrior"))
			{
				if (role == "Hunter")
				{
					damageGroup = DamageGroup.Ranged;
					SetSkill(effect, (SkillType)101, value2);
				}
				else
				{
					damageGroup = DamageGroup.Magic;
					effect.m_eitrRegenMultiplier = 1f + value2 / 100f;
				}
			}
			else
			{
				damageGroup = DamageGroup.Melee;
				effect.m_staggerModifier = (0f - value2) / 100f;
			}
			DamageGroups.Set((StatusEffect)(object)effect, damageGroup, value);
			string text = $"+{value:0}% $nokep_bonus_dmg_{damageGroup.ToString().ToLower()}";
			if (cape.CfgMaxEitr != null && cape.CfgMaxEitr.Value != 0f)
			{
				text += $"\n+{cape.CfgMaxEitr.Value:0} $nokep_bonus_eitr";
			}
			((StatusEffect)effect).m_tooltip = (string.IsNullOrEmpty(cape.VanillaTooltip) ? text : (cape.VanillaTooltip + "\n" + text));
		}

		private static void SetSkill(SE_Stats effect, SkillType skill, float level)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			if ((int)effect.m_skillLevel == 0 || effect.m_skillLevel == skill)
			{
				effect.m_skillLevel = skill;
				effect.m_skillLevelModifier = level;
			}
			else
			{
				effect.m_skillLevel2 = skill;
				effect.m_skillLevelModifier2 = level;
			}
		}

		public static void RefreshEffects()
		{
			foreach (Cape cape2 in Plugin.Capes)
			{
				if ((Object)(object)cape2.Effect != (Object)null)
				{
					ApplyValues(cape2.Effect, cape2);
				}
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			foreach (StatusEffect active in ((Character)Player.m_localPlayer).GetSEMan().GetStatusEffects())
			{
				StatusEffect obj = active;
				SE_Stats val = (SE_Stats)(object)((obj is SE_Stats) ? obj : null);
				if (val != null)
				{
					Cape cape = Plugin.Capes.Find((Cape c) => (Object)(object)c.Effect != (Object)null && ((StatusEffect)c.Effect).NameHash() == active.NameHash());
					if (cape != null)
					{
						ApplyValues(val, cape);
					}
				}
			}
		}
	}
	internal static class Recipes
	{
		private class Entry
		{
			public ConfigEntry<string> Extra;

			public string Prefab;

			public string Vanilla;

			public ConfigEntry<string> Custom;
		}

		private static readonly List<Entry> Entries = new List<Entry>();

		public static readonly HashSet<string> VanillaArmorNames = new HashSet<string>();

		public static void Add(ArmorSet set, string prefabName, string vanillaPrefab, ConfigEntry<string> custom)
		{
			Add(StationLevel.ForSet(set), set.CfgExtra, prefabName, vanillaPrefab, custom);
		}

		public static void Add(int level, ConfigEntry<string> extra, string prefabName, string vanillaPrefab, ConfigEntry<string> custom)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			RecipeConfig val = new RecipeConfig();
			val.Name = "Recipe_" + prefabName;
			val.Item = prefabName;
			val.CraftingStation = "piece_nokep_leatherbench";
			val.MinStationLevel = level;
			val.AddRequirement("Wood", 1, 0);
			Entries.Add(new Entry
			{
				Extra = extra,
				Prefab = prefabName,
				Vanilla = vanillaPrefab,
				Custom = custom
			});
			ItemManager.Instance.AddRecipe(new CustomRecipe(val));
		}

		public static void Apply()
		{
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: 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_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			if ((Object)(object)ObjectDB.instance == (Object)null || ObjectDB.instance.m_recipes == null)
			{
				return;
			}
			int num = 0;
			foreach (Entry entry in Entries)
			{
				Recipe val = Find(entry.Prefab);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning((object)("Не нашёл свой рецепт для " + entry.Prefab));
					continue;
				}
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(entry.Vanilla);
				ItemDrop val2 = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 != (Object)null)
				{
					VanillaArmorNames.Add(val2.m_itemData.m_shared.m_name);
				}
				List<Requirement> list = new List<Requirement>();
				Dictionary<string, int> dictionary = NokepUtils.ParseRecipe(entry.Custom.Value);
				if (dictionary.Count > 0)
				{
					AddItems(list, dictionary);
				}
				else
				{
					Recipe val3 = Find(entry.Vanilla);
					if ((Object)(object)val3 == (Object)null || val3.m_resources == null)
					{
						Logger.LogWarning((object)("Не нашёл ванильный рецепт " + entry.Vanilla));
						continue;
					}
					if (ModConfig.CraftFromVanilla.Value)
					{
						list.Add(new Requirement
						{
							m_resItem = val3.m_item,
							m_amount = 1,
							m_amountPerLevel = 0
						});
						Requirement[] resources = val3.m_resources;
						for (int i = 0; i < resources.Length; i++)
						{
							Requirement val4 = Copy(resources[i]);
							if (!val4.m_upgraderResource)
							{
								val4.m_amount = 0;
							}
							list.Add(val4);
						}
					}
					else
					{
						Requirement[] resources = val3.m_resources;
						foreach (Requirement req in resources)
						{
							list.Add(Copy(req));
						}
					}
					AddItems(list, NokepUtils.ParseRecipe(entry.Extra.Value), 0);
				}
				if (list.Count == 0)
				{
					Logger.LogWarning((object)("Пустой рецепт для " + entry.Prefab + " — оставляю прежний"));
					continue;
				}
				val.m_resources = Merge(list).ToArray();
				num++;
			}
			Logger.LogInfo((object)$"Рецепты брони обновлены: {num} из {Entries.Count}");
		}

		private static Requirement Copy(Requirement req)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			return new Requirement
			{
				m_resItem = req.m_resItem,
				m_amount = req.m_amount,
				m_extraAmountOnlyOneIngredient = req.m_extraAmountOnlyOneIngredient,
				m_amountPerLevel = req.m_amountPerLevel,
				m_upgraderResource = req.m_upgraderResource,
				m_recover = req.m_recover
			};
		}

		private static List<Requirement> Merge(List<Requirement> list)
		{
			List<Requirement> list2 = new List<Requirement>();
			foreach (Requirement req in list)
			{
				Requirement val = list2.Find((Requirement r) => (Object)(object)r.m_resItem == (Object)(object)req.m_resItem && r.m_upgraderResource == req.m_upgraderResource);
				if (val == null)
				{
					list2.Add(req);
					continue;
				}
				val.m_amount += req.m_amount;
				val.m_amountPerLevel += req.m_amountPerLevel;
			}
			return list2;
		}

		public static void AddItems(List<Requirement> list, Dictionary<string, int> items, int perLevel = 1)
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			foreach (KeyValuePair<string, int> item in items)
			{
				GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(item.Key);
				ItemDrop val = (((Object)(object)itemPrefab != (Object)null) ? itemPrefab.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val == (Object)null)
				{
					Logger.LogWarning((object)("Не нашёл ресурс " + item.Key + " — проверь написание в настройках"));
					continue;
				}
				list.Add(new Requirement
				{
					m_resItem = val,
					m_amount = item.Value,
					m_amountPerLevel = perLevel,
					m_recover = true
				});
			}
		}

		private static Recipe Find(string itemPrefabName)
		{
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && ((Object)((Component)recipe.m_item).gameObject).name == itemPrefabName)
				{
					return recipe;
				}
			}
			return null;
		}
	}
	internal static class Table
	{
		public const string PrefabName = "piece_nokep_leatherbench";

		private static readonly Dictionary<Material, Color> darkMaterials = new Dictionary<Material, Color>();

		private static readonly int ColorId = Shader.PropertyToID("_Color");

		public static string StationName { get; private set; }

		public static void Add()
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			string text = ModConfig.TableName.Value?.Trim();
			StationName = (string.IsNullOrEmpty(text) ? "$nokep_table" : text);
			PieceConfig val = new PieceConfig();
			val.Name = StationName;
			val.Description = "$nokep_table_desc";
			val.PieceTable = "Hammer";
			val.Category = "Crafting";
			foreach (KeyValuePair<string, int> item in NokepUtils.ParseRecipe(ModConfig.TableRecipe.Value))
			{
				val.AddRequirement(item.Key, item.Value, true);
			}
			CustomPiece val2 = new CustomPiece("piece_nokep_leatherbench", "piece_workbench", val);
			CraftingStation component = val2.PiecePrefab.GetComponent<CraftingStation>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = StationName;
				component.m_craftRequireRoof = ModConfig.RequireRoof.Value;
				component.m_craftRequireFire = ModConfig.RequireFire.Value;
				component.m_showBasicRecipies = false;
			}
			else
			{
				Logger.LogError((object)"На верстаке нет компонента CraftingStation");
			}
			CopyMaterials(val2.PiecePrefab);
			BenchModel.Apply(val2.PiecePrefab, MainMaterial());
			val2.PiecePrefab.AddComponent<TableVisuals>();
			PieceManager.Instance.AddPiece(val2);
		}

		private static void CopyMaterials(GameObject prefab)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<Material, Material> dictionary = new Dictionary<Material, Material>();
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer))
				{
					continue;
				}
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					Material val2 = sharedMaterials[j];
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					if (!dictionary.TryGetValue(val2, out var value))
					{
						value = new Material(val2);
						((Object)value).name = ((Object)val2).name + " (nokep)";
						dictionary[val2] = value;
						bool flag = value.HasProperty(ColorId);
						if (flag)
						{
							darkMaterials[value] = value.GetColor(ColorId);
						}
						Logger.LogInfo((object)("Материал верстака: " + ((Object)val2).name + ", шейдер " + ((Object)val2.shader).name + ", " + (flag ? $"_Color = {value.GetColor(ColorId)}" : "нет _Color — не затемняю")));
					}
					sharedMaterials[j] = value;
				}
				val.sharedMaterials = sharedMaterials;
			}
			ApplyBrightness();
		}

		private static Material MainMaterial()
		{
			foreach (Material key in darkMaterials.Keys)
			{
				if (((Object)key).name.StartsWith("Workbench_mat"))
				{
					return key;
				}
			}
			return null;
		}

		private static void ApplyBrightness()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			float value = ModConfig.TableBrightness.Value;
			foreach (KeyValuePair<Material, Color> darkMaterial in darkMaterials)
			{
				Color value2 = darkMaterial.Value;
				darkMaterial.Key.SetColor(ColorId, new Color(value2.r * value, value2.g * value, value2.b * value, value2.a));
			}
		}

		public static void Apply()
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			ApplyBrightness();
			GameObject prefab = PrefabManager.Instance.GetPrefab("piece_nokep_leatherbench");
			if ((Object)(object)prefab == (Object)null)
			{
				Logger.LogWarning((object)"Не нашёл префаб верстака piece_nokep_leatherbench");
				return;
			}
			List<Requirement> list = new List<Requirement>();
			Recipes.AddItems(list, NokepUtils.ParseRecipe(ModConfig.TableRecipe.Value));
			Piece component = prefab.GetComponent<Piece>();
			if ((Object)(object)component != (Object)null && list.Count > 0)
			{
				component.m_resources = list.ToArray();
			}
			ApplyStation(prefab.GetComponent<CraftingStation>());
			foreach (CraftingStation allStation in CraftingStation.m_allStations)
			{
				if ((Object)(object)allStation != (Object)null && allStation.m_name == StationName)
				{
					ApplyStation(allStation);
				}
			}
		}

		private static void ApplyStation(CraftingStation station)
		{
			if (!((Object)(object)station == (Object)null))
			{
				station.m_craftRequireRoof = ModConfig.RequireRoof.Value;
				station.m_craftRequireFire = ModConfig.RequireFire.Value;
			}
		}
	}
	internal class TableItemSlot
	{
		public int Level;

		public string Item;

		public string Source;

		public Vector3 Position;

		public Vector3 Rotation;

		public float Size;

		public int Count = 1;

		public bool Bunch;
	}
	internal class TableVisuals : MonoBehaviour
	{
		private static readonly TableItemSlot[] Items = new TableItemSlot[6]
		{
			new TableItemSlot
			{
				Level = 2,
				Item = "Thistle",
				Source = "Pickable_Thistle",
				Bunch = true,
				Position = new Vector3(-1f, 1.16f, 0.15f),
				Size = 0.675f,
				Count = 6
			},
			new TableItemSlot
			{
				Level = 3,
				Item = "Iron",
				Position = new Vector3(-0.26f, 1.02f, 0.32f),
				Size = 0.3f,
				Count = 8
			},
			new TableItemSlot
			{
				Level = 4,
				Item = "TrophyWolf",
				Position = new Vector3(0.55f, 1.05f, 0.3f),
				Rotation = new Vector3(10f, 75f, 1f),
				Size = 0.605f
			},
			new TableItemSlot
			{
				Level = 5,
				Item = "BlackMetal",
				Position = new Vector3(0.16f, 1.02f, 0.32f),
				Size = 0.3f,
				Count = 8
			},
			new TableItemSlot
			{
				Level = 6,
				Item = "Eitr",
				Position = new Vector3(-0.18f, 0.85f, -0.35f),
				Size = 0.2f,
				Count = 2
			},
			new TableItemSlot
			{
				Level = 7,
				Item = "FlametalNew",
				Position = new Vector3(-0.98f, 1.16f, -0.15f),
				Size = 0.3f,
				Count = 6
			}
		};

		private const float CheckInterval = 1f;

		private ZNetView nview;

		private GameObject holder;

		private int shownLevel = -1;

		private float timer;

		private void Awake()
		{
			nview = ((Component)this).GetComponent<ZNetView>();
		}

		private void Update()
		{
			timer -= Time.deltaTime;
			if (timer > 0f)
			{
				return;
			}
			timer = 1f;
			if ((Object)(object)nview == (Object)null || !nview.IsValid() || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return;
			}
			CraftingStation component = ((Component)this).GetComponent<CraftingStation>();
			if (!((Object)(object)component == (Object)null))
			{
				int num = StationLevel.Get(component);
				if (num != shownLevel)
				{
					Rebuild(num);
				}
			}
		}

		private void Rebuild(int level)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			shownLevel = level;
			if ((Object)(object)holder != (Object)null)
			{
				Object.Destroy((Object)(object)holder);
			}
			holder = new GameObject("nokep_upgrade_items");
			holder.transform.SetParent(((Component)this).transform, false);
			TableItemSlot[] items = Items;
			foreach (TableItemSlot tableItemSlot in items)
			{
				if (tableItemSlot.Level <= level)
				{
					AddItem(tableItemSlot.Source ?? tableItemSlot.Item, tableItemSlot.Position, Quaternion.Euler(tableItemSlot.Rotation), tableItemSlot.Size, tableItemSlot.Count, tableItemSlot.Bunch);
				}
			}
		}

		private void AddItem(string itemName, Vector3 point, Quaternion rotation, float size, int count, bool bunch)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//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_0144: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = ObjectDB.instance.GetItemPrefab(itemName);
			if ((Object)(object)val == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab(itemName);
			}
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)("Предмет для верстака не найден: " + itemName));
				return;
			}
			GameObject val2 = new GameObject(itemName);
			val2.transform.SetParent(holder.transform, false);
			int num = 0;
			foreach (Renderer item in ModelRenderers(val))
			{
				Mesh val3 = null;
				SkinnedMeshRenderer val4 = (SkinnedMeshRenderer)(object)((item is SkinnedMeshRenderer) ? item : null);
				if (val4 != null)
				{
					val3 = val4.sharedMesh;
				}
				else if (item is MeshRenderer)
				{
					MeshFilter component = ((Component)item).GetComponent<MeshFilter>();
					val3 = ((component != null) ? component.sharedMesh : null);
				}
				if (!((Object)(object)val3 == (Object)null))
				{
					Transform transform = val.transform;
					Transform transform2 = ((Component)item).transform;
					GameObject val5 = new GameObject(((Object)transform2).name)
					{
						layer = ((Component)this).gameObject.layer
					};
					val5.transform.SetParent(val2.transform, false);
					val5.transform.localPosition = transform.InverseTransformPoint(transform2.position);
					val5.transform.localRotation = Quaternion.Inverse(transform.rotation) * transform2.rotation;
					val5.transform.localScale = Divide(transform2.lossyScale, transform.lossyScale);
					val5.AddComponent<MeshFilter>().sharedMesh = val3;
					((Renderer)val5.AddComponent<MeshRenderer>()).sharedMaterials = item.sharedMaterials;
					num++;
				}
			}
			if (num == 0)
			{
				Logger.LogWarning((object)("У предмета " + itemName + " нет ни одной модели — на верстак не ставлю"));
				Object.Destroy((Object)(object)val2);
				return;
			}
			CopyEffects(val, val2);
			if (bunch)
			{
				PlaceBunch(val2, point, rotation, size, count);
			}
			else
			{
				PlaceStack(val2, point, rotation, size, count);
			}
		}

		private static void CopyEffects(GameObject prefab, GameObject model)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = prefab.transform;
			Transform[] componentsInChildren = ((Component)transform).GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				GameObject gameObject = ((Component)val).gameObject;
				if ((!((Object)(object)gameObject.GetComponent<ParticleSystem>() == (Object)null) || !((Object)(object)gameObject.GetComponent<Light>() == (Object)null)) && ActiveInPrefab(val, transform) && !((Object)(object)gameObject.GetComponentInChildren<ZNetView>(true) != (Object)null) && !((Object)(object)gameObject.GetComponentInChildren<Collider>(true) != (Object)null) && !((Object)(object)gameObject.GetComponentInChildren<Rigidbody>(true) != (Object)null))
				{
					GameObject obj = Object.Instantiate<GameObject>(gameObject, model.transform, false);
					((Object)obj).name = ((Object)val).name;
					obj.transform.localPosition = transform.InverseTransformPoint(val.position);
					obj.transform.localRotation = Quaternion.Inverse(transform.rotation) * val.rotation;
					obj.transform.localScale = Divide(val.lossyScale, transform.lossyScale);
					ParticleSystem[] componentsInChildren2 = obj.GetComponentsInChildren<ParticleSystem>(true);
					for (int j = 0; j < componentsInChildren2.Length; j++)
					{
						MainModule main = componentsInChildren2[j].main;
						((MainModule)(ref main)).scalingMode = (ParticleSystemScalingMode)0;
					}
				}
			}
		}

		private static void FixLights(GameObject piece, int index, float scale)
		{
			if (index > 0)
			{
				LightFlicker[] componentsInChildren = piece.GetComponentsInChildren<LightFlicker>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren[i]);
				}
				LightLod[] componentsInChildren2 = piece.GetComponentsInChildren<LightLod>(true);
				for (int i = 0; i < componentsInChildren2.Length; i++)
				{
					Object.Destroy((Object)(object)componentsInChildren2[i]);
				}
			}
			Light[] componentsInChildren3 = piece.GetComponentsInChildren<Light>(true);
			foreach (Light val in componentsInChildren3)
			{
				if (index > 0)
				{
					Object.Destroy((Object)(object)val);
				}
				else
				{
					val.range *= scale;
				}
			}
		}

		private void PlaceBunch(GameObject model, Vector3 point, Quaternion rotation, float size, int count)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = LocalBounds(model, rotation);
			float num = Mathf.Max(((Bounds)(ref val)).size.x, Mathf.Max(((Bounds)(ref val)).size.y, ((Bounds)(ref val)).size.z));
			float num2 = ((num > 0.001f) ? (size / num) : 1f);
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).min.y, ((Bounds)(ref val)).center.z);
			for (int i = 0; i < count; i++)
			{
				GameObject obj = ((i == 0) ? model : Object.Instantiate<GameObject>(model, holder.transform));
				float num3 = 360f * (float)i / (float)count;
				Vector3 val3 = Quaternion.Euler(0f, num3, 0f) * Vector3.forward;
				Quaternion val4 = ((count > 1) ? Quaternion.AngleAxis(12f, Vector3.Cross(Vector3.up, val3)) : Quaternion.identity) * Quaternion.Euler(0f, num3 * 1.7f, 0f);
				float num4 = num2 * (1f - 0.1f * (float)(i % 3));
				Vector3 val5 = ((count > 1) ? (val3 * (0.04f * size)) : Vector3.zero);
				obj.transform.localRotation = val4 * rotation;
				obj.transform.localScale = Vector3.one * num4;
				FixLights(obj, i, num4);
				obj.transform.localPosition = point + val5 - val4 * (val2 * num4);
			}
		}

		private void PlaceStack(GameObject model, Vector3 point, Quaternion rotation, float size, int count)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			Bounds val = LocalBounds(model, rotation);
			float num = Mathf.Max(((Bounds)(ref val)).size.x, Mathf.Max(((Bounds)(ref val)).size.y, ((Bounds)(ref val)).size.z));
			float num2 = ((num > 0.001f) ? (size / num) : 1f);
			Vector3 val2 = new Vector3(((Bounds)(ref val)).center.x, ((Bounds)(ref val)).min.y, ((Bounds)(ref val)).center.z) * num2;
			Vector3 val3 = ((Bounds)(ref val)).size * num2;
			bool flag = val3.x <= val3.z;
			float num3 = (flag ? val3.x : val3.z);
			for (int i = 0; i < count; i++)
			{
				GameObject obj = ((i == 0) ? model : Object.Instantiate<GameObject>(model, holder.transform));
				int num4 = i / 2;
				int num5 = Mathf.Min(2, count - num4 * 2);
				bool flag2 = num4 % 2 == 1;
				Quaternion val4 = (flag2 ? Quaternion.Euler(0f, 90f, 0f) : Quaternion.identity);
				Vector3 val5 = ((flag != flag2) ? Vector3.right : Vector3.forward);
				float num6 = ((num5 == 1) ? 0f : (((float)(i % 2) - 0.5f) * num3));
				obj.transform.localRotation = val4 * rotation;
				obj.transform.localScale = Vector3.one * num2;
				FixLights(obj, i, num2);
				obj.transform.localPosition = point + val5 * num6 + Vector3.up * ((float)num4 * val3.y) - val4 * val2;
			}
		}

		private static List<Renderer> ModelRenderers(GameObject prefab)
		{
			List<Renderer> list = new List<Renderer>();
			HashSet<Renderer> hashSet = new HashSet<Renderer>();
			LODGroup[] componentsInChildren = prefab.GetComponentsInChildren<LODGroup>(true);
			Renderer[] renderers;
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				LOD[] lODs = componentsInChildren[i].GetLODs();
				for (int j = 1; j < lODs.Length; j++)
				{
					renderers = lODs[j].renderers;
					foreach (Renderer val in renderers)
					{
						if ((Object)(object)val != (Object)null)
						{
							hashSet.Add(val);
						}
					}
				}
			}
			renderers = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in renderers)
			{
				if ((val2 is MeshRenderer || val2 is SkinnedMeshRenderer) && !hashSet.Contains(val2) && val2.enabled && ActiveInPrefab(((Component)val2).transform, prefab.transform))
				{
					list.Add(val2);
				}
			}
			return list;
		}

		private static bool ActiveInPrefab(Transform t, Transform root)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (!((Component)t).gameObject.activeSelf)
				{
					return false;
				}
				if ((Object)(object)t == (Object)(object)root)
				{
					break;
				}
				t = t.parent;
			}
			return true;
		}

		private static Bounds LocalBounds(GameObject model, Quaternion rotation)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			Bounds result = default(Bounds);
			bool flag = true;
			MeshFilter[] componentsInChildren = model.GetComponentsInChildren<MeshFilter>();
			foreach (MeshFilter obj in componentsInChildren)
			{
				Bounds bounds = obj.sharedMesh.bounds;
				Transform transform = ((Component)obj).transform;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3((float)(((j & 1) != 0) ? 1 : (-1)), (float)(((j & 2) != 0) ? 1 : (-1)), (float)(((j & 4) != 0) ? 1 : (-1))));
					Vector3 val2 = rotation * (transform.localPosition + transform.localRotation * Vector3.Scale(transform.localScale, val));
					if (flag)
					{
						((Bounds)(ref result))..ctor(val2, Vector3.zero);
						flag = false;
					}
					else
					{
						((Bounds)(ref result)).Encapsulate(val2);
					}
				}
			}
			return result;
		}

		private static Vector3 Divide(Vector3 a, Vector3 b)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			return new Vector3(a.x / b.x, a.y / b.y, a.z / b.z);
		}
	}
	internal class UnlockCommand : ConsoleCommand
	{
		public override string Name => "nokep_unlock";

		public override string Help => "Unlock all NokepArmorSets recipes for this character";

		public override bool IsCheat => true;

		public override void Run(string[] args)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				Console instance = Console.instance;
				if (instance != null)
				{
					instance.Print("nokep_unlock: no player or ObjectDB");
				}
				return;
			}
			int num = 0;
			foreach (Recipe recipe in ObjectDB.instance.m_recipes)
			{
				if (!((Object)(object)recipe == (Object)null) && !((Object)(object)recipe.m_item == (Object)null) && ((Object)((Component)recipe.m_item).gameObject).name.StartsWith("Nokep_") && localPlayer.m_knownRecipes.Add(recipe.m_item.m_itemData.m_shared.m_name))
				{
					num++;
				}
			}
			Console instance2 = Console.instance;
			if (instance2 != null)
			{
				instance2.Print($"nokep_unlock: recipes unlocked: {num}");
			}
			Logger.LogInfo((object)$"nokep_unlock: открыто рецептов: {num}");
		}
	}
	internal static class Upgrade
	{
		public static List<Requirement> Cost(int targetLevel)
		{
			List<Requirement> list = new List<Requirement>();
			if ((Object)(object)ObjectDB.instance == (Object)null || targetLevel < 2 || targetLevel > 7)
			{
				return list;
			}
			Recipes.AddItems(list, NokepUtils.ParseRecipe(ModConfig.UpgradeCost[targetLevel].Value));
			return list;
		}

		public static string CostText(Player player, int targetLevel)
		{
			StringBuilder stringBuilder = new StringBuilder();
			Inventory inventory = ((Humanoid)player).GetInventory();
			foreach (Requirement item in Cost(targetLevel))
			{
				string name = item.m_resItem.m_itemData.m_shared.m_name;
				int num = inventory.CountItems(name, -1, true);
				string arg = ((num >= item.m_amount) ? "white" : "red");
				if (stringBuilder.Length > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append($"<color={arg}>{Translations.Get(name)} {item.m_amount}</color> " + string.Format("({0} {1})", Translations.Get("$nokep_have"), num));
			}
			return stringBuilder.ToString();
		}

		public static void TryUpgrade(Player player, CraftingStation station)
		{
			int num = StationLevel.Get(station);
			if (num >= 7)
			{
				return;
			}
			int num2 = num + 1;
			string value = ModConfig.UpgradeCost[num2].Value;
			List<Requirement> list = Cost(num2);
			if (list.Count == 0 && NokepUtils.ParseRecipe(value).Count > 0)
			{
				Logger.LogWarning((object)$"Цена улучшения до {num2} не распознана: {value}");
				return;
			}
			if (!player.NoCostCheat())
			{
				Inventory inventory = ((Humanoid)player).GetInventory();
				foreach (Requirement item in list)
				{
					if (inventory.CountItems(item.m_resItem.m_itemData.m_shared.m_name, -1, true) < item.m_amount)
					{
						((Character)player).Message((MessageType)2, Translations.Get("$nokep_need") + ":\n" + CostText(player, num2), 0, (Sprite)null, false);
						return;
					}
				}
				player.ConsumeResources(list.ToArray(), 1, -1, 1);
			}
			ZNetView nview = station.m_nview;
			nview.ClaimOwnership();
			nview.GetZDO().Set("nokep_level", num2);
			player.AddKnownStation(station);
			((Character)player).Message((MessageType)2, Translations.Get("$nokep_upgraded") + ": " + BiomeFilter.NameForLevel(num2), 0, (Sprite)null, false);
			Logger.LogInfo((object)$"Верстак скорняка улучшен до уровня {num2}");
		}
	}
	internal class ArmorSet
	{
		public string Id;

		public string Bonus;

		public string VanillaHelmet;

		public string VanillaChest;

		public string VanillaLegs;

		public string IconFolder = "";

		public string IconPrefix = "";

		public string EffectName;

		public int EffectHash;

		public SE_Stats Effect;

		public ConfigEntry<float> CfgBonus;

		public ConfigEntry<float> CfgSpeed;

		public ConfigEntry<string> CfgExtra;

		public ConfigEntry<string> CfgHelmet;

		public ConfigEntry<string> CfgChest;

		public ConfigEntry<string> CfgLegs;

		public float HealthRegen;

		public float StaminaRegen;

		public float CarryWeight;

		public float JumpStamina;

		public float BlockStamina;

		public float SneakStamina;

		public float AttackStamina;

		public float DodgeStamina;

		public float RunStamina;

		public float EitrRegen;

		public SkillType? Skill1;

		public float Skill1Level;

		public SkillType? Skill2;

		public float Skill2Level;

		public SkillType? WeaponSkill;

		public float WeaponDamage;

		public DamageType? ResistType;

		public string HelmetPrefab => "Nokep_Helmet_" + Id;

		public string ChestPrefab => "Nokep_Chest_" + Id;

		public string LegsPrefab => "Nokep_Legs_" + Id;

		public string SetName => "Nokep_Set_" + Id;

		public string LineKey
		{
			get
			{
				if (!Id.Contains("_"))
				{
					return "leather";
				}
				return Id.Substring(0, Id.IndexOf('_')).ToLower();
			}
		}

		public string TypeKey => Bonus.ToLower();

		public string EffectDisplayName => "$nokep_set_" + TypeKey;

		public string ItemDescription => "$nokep_part_of_set $nokep_type_" + TypeKey + ".";

		public string ItemName(string part)
		{
			return "$nokep_" + LineKey + "_" + part + ": $nokep_type_" + TypeKey;
		}

		public string IconName(string part)
		{
			string text = (string.IsNullOrEmpty(IconPrefix) ? (Bonus + "_" + part) : (IconPrefix + "_" + Bonus + "_" + part));
			if (!string.IsNullOrEmpty(IconFolder))
			{
				return IconFolder + "/" + text;
			}
			return text;
		}
	}
	internal class Cape
	{
		public string Line;

		public string Role;

		public string Vanilla;

		public string IconFolder;

		public float Damage;

		public float Extra;

		public float MaxEitr;

		public float ItemEitrRegen;

		public bool FireInsteadOfFrost;

		public string ExtraResources;

		public ConfigEntry<float> CfgDamage;

		public ConfigEntry<float> CfgExtra;

		public ConfigEntry<float> CfgMaxEitr;

		public ConfigEntry<string> CfgResources;

		public ConfigEntry<string> CfgRecipe;

		public SE_Stats Effect;

		public string VanillaTooltip;

		public string Id => Line + "_" + Role;

		public string Prefab => "Nokep_Cape_" + Id;

		public string EffectName => "Nokep_CapeEffect_" + Id;

		public string ItemName => "$nokep_cape_" + Line.ToLower() + ": $nokep_role_" + Role.ToLower();

		public string IconName
		{
			get
			{
				if (!string.IsNullOrEmpty(IconFolder))
				{
					return IconFolder + "/Cape_" + Id;
				}
				return "Cape_" + Id;
			}
		}
	}
	internal static class ModConfig
	{
		public static ConfigEntry<string> TableName;

		public static ConfigEntry<string> TableRecipe;

		public static ConfigEntry<bool> RequireRoof;

		public static ConfigEntry<bool> RequireFire;

		public static ConfigEntry<KeyCode> NextBiomeKey;

		public static ConfigEntry<KeyCode> PrevBiomeKey;

		public static ConfigEntry<float> TableBrightness;

		public static ConfigEntry<bool> CraftFromVanilla;

		public static readonly ConfigEntry<string>[] UpgradeCost = new ConfigEntry<string>[8];

		private static ConfigFile file;

		public static void Bind(ConfigFile config)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Expected O, but got Unknown
			file = config;
			TableName = Server("0. Workbench", "Name", "", "Custom workbench name. Empty = name in the game language. Applied after restart.");
			TableRecipe = Server("0. Workbench", "Recipe", "Wood:10", "What the workbench is built from. Format: Item:Amount, comma separated.");
			RequireRoof = Server("0. Workbench", "Require roof", value: true, "Workbench needs a roof to work.");
			RequireFire = Server("0. Workbench", "Require fire", value: false, "Workbench needs a fire nearby to work.");
			CraftFromVanilla = Server("0. Workbench", "Craft from vanilla item", value: true, "Set items are made from the vanilla item plus extra resources (vanilla resources are then needed only for quality upgrades). Off = vanilla resources plus extra resources.");
			NextBiomeKey = config.Bind<KeyCode>("0. Workbench", "Next biome key", (KeyCode)275, "Key at the workbench: show items of the next biome. Personal, not synced.");
			PrevBiomeKey = config.Bind<KeyCode>("0. Workbench", "Previous biome key", (KeyCode)276, "Key at the workbench: show items of the previous biome. Personal, not synced.");
			TableBrightness = config.Bind<float>("0. Workbench", "Brightness", 0.6f, new ConfigDescription("Workbench color: 1 = like the vanilla workbench, less = darker. Personal, not synced.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>()));
			UpgradeCost[2] = Server("0. Workbench upgrades", "2. Black Forest", "Thistle:10, FineWood:20", "Cost of the workbench upgrade that opens this biome. Format: Item:Amount, comma separated. Empty = free.");
			UpgradeCost[3] = Server("0. Workbench upgrades", "3. Swamp", "ElderBark:20, Iron:10", "Cost of the workbench upgrade that opens this biome. Format: Item:Amount, comma separated. Empty = free.");
			UpgradeCost[4] = Server("0. Workbench upgrades", "4. Mountains", "WolfPelt:10, Obsidian:20", "Cost of the workbench upgrade that opens this biome. Format: Item:Amount, comma separated. Empty = free.");
			UpgradeCost[5] = Server("0. Workbench upgrades", "5. Plains", "LinenThread:20, BlackMetal:10", "Cost of the workbench upgrade that opens this biome. Format: Item:Amount, comma separated. Empty = free.");
			UpgradeCost[6] = Server("0. Workbench upgrades", "6. Mistlands", "Carapace:20, Eitr:10", "Cost of the workbench upgrade that opens this biome. Format: Item:Amount, comma separated. Empty = free.");
			UpgradeCost[7] = Server("0. Workbench upgrades", "7. Ashlands", "FlametalNew:10, AskHide:10", "Cost of the workbench upgrade that opens this biome. Format: Item:Amount, comma separated. Empty = free.");
			BindSet("Vitality", "1. Meadows", 15f, 0f, "BoneFragments:8, LeatherScraps:6");
			BindSet("Armored", "1. Meadows", 3f, 0f, "Flint:8, LeatherScraps:6");
			BindSet("Magic", "1. Meadows", 10f, 0f, "Feathers:10, Wood:10");
			BindSet("Stamina", "1. Meadows", 15f, 0f, "Resin:10, Wood:10");
			BindSet("Troll_Vitality", "2. Troll", 25f, 5f, "TrollHide:2, RoundLog:15, Resin:10");
			BindSet("Troll_Armored", "2. Troll", 5f, 0f, "TrollHide:5, FineWood:10");
			BindSet("Troll_Magic", "2. Troll", 25f, 0f, "TrollHide:2, GreydwarfEye:20, Resin:10");
			BindSet("Troll_Stamina", "2. Troll", 25f, -10f, "TrollHide:2, Thistle:10, FineWood:10");
			BindSet("Bronze_Vitality", "3. Bronze", 35f, 0f, "Bronze:2, Copper:5, RoundLog:15");
			BindSet("Bronze_Armored", "3. Bronze", 8f, -5f, "Bronze:6, Coal:10");
			BindSet("Bronze_Magic", "3. Bronze", 20f, 0f, "Bronze:2, SurtlingCore:5, Coal:10");
			BindSet("Bronze_Stamina", "3. Bronze", 25f, 0f, "Bronze:2, Tin:5, RoundLog:15");
			BindSet("Iron_Vitality", "4. Iron", 45f, 0f, "Iron:2, Bloodbag:5, Entrails:5");
			BindSet("Iron_Armored", "4. Iron", 10f, 0f, "Iron:6, Chain:2");
			BindSet("Iron_Magic", "4. Iron", 30f, 0f, "Iron:2, Guck:10, Ooze:5");
			BindSet("Iron_Stamina", "4. Iron", 35f, 0f, "Iron:2, ElderBark:10, WitheredBone:5");
			BindSet("Wolf_Vitality", "5. Wolf", 55f, 0f, "Silver:2, WolfPelt:5");
			BindSet("Wolf_Armored", "5. Wolf", 12f, 0f, "Silver:6, Obsidian:10");
			BindSet("Wolf_Magic", "5. Wolf", 40f, 0f, "Silver:2, Crystal:5, FreezeGland:5");
			BindSet("Wolf_Stamina", "5. Wolf", 45f, 0f, "Silver:2, WolfFang:10");
			BindSet("Fenris_Vitality", "6. Fenris", 50f, 10f, "WolfPelt:4, LeatherScraps:10");
			BindSet("Fenris_Armored", "6. Fenris", 8f, 0f, "WolfPelt:3, Obsidian:10");
			BindSet("Fenris_Magic", "6. Fenris", 50f, 0f, "WolfPelt:2, Crystal:5, FreezeGland:3");
			BindSet("Fenris_Stamina", "6. Fenris", 50f, -15f, "WolfPelt:2, WolfFang:10, Feathers:10");
			BindSet("Padded_Vitality", "7. Padded", 70f, 0f, "BlackMetal:2, LoxPelt:3");
			BindSet("Padded_Armored", "7. Padded", 15f, 0f, "BlackMetal:6, LinenThread:10");
			BindSet("Padded_Magic", "7. Padded", 50f, 0f, "BlackMetal:2, Tar:5");
			BindSet("Padded_Stamina", "7. Padded", 55f, 0f, "BlackMetal:2, Needle:10");
			BindSet("Root_Vitality", "8. Root", 40f, 0f, "Root:4, Bloodbag:5");
			BindSet("Root_Armored", "8. Root", 8f, 0f, "Root:6, ElderBark:10");
			BindSet("Root_Magic", "8. Root", 30f, 0f, "Root:4, Guck:10");
			BindSet("Root_Stamina", "8. Root", 40f, 0f, "Root:4, WitheredBone:5");
			BindSet("Rotbone_Vitality", "9. Rotbone", 60f, 0f, "BjornHide:3, Cloudberry:10");
			BindSet("Rotbone_Armored", "9. Rotbone", 12f, 0f, "BjornHide:4, BlackMetal:5");
			BindSet("Rotbone_Magic", "9. Rotbone", 45f, 0f, "BjornHide:2, GoblinTotem:2");
			BindSet("Rotbone_Stamina", "9. Rotbone", 55f, 0f, "BjornHide:2, Needle:10");
			BindSet("Eitrweave_Vitality", "A. Eitr-weave", 80f, 0f, "LinenThread:5, MushroomJotunPuffs:5");
			BindSet("Eitrweave_Armored", "A. Eitr-weave", 18f, 0f, "ScaleHide:4, Iron:5");
			BindSet("Eitrweave_Magic", "A. Eitr-weave", 70f, 0f, "Eitr:5, Sap:5");
			BindSet("Eitrweave_Stamina", "A. Eitr-weave", 65f, 0f, "ScaleHide:3, Feathers:10");
			BindSet("Carapace_Vitality", "B. Carapace", 85f, 0f, "Carapace:3, GiantBloodSack:3");
			BindSet("Carapace_Armored", "B. Carapace", 20f, 0f, "Carapace:6, BlackMarble:10");
			BindSet("Carapace_Magic", "B. Carapace", 60f, 0f, "Carapace:3, Eitr:5");
			BindSet("Carapace_Stamina", "B. Carapace", 65f, 0f, "Carapace:3, Mandible:2");
			BindSet("Ask_Vitality", "C. Ask", 95f, 0f, "AskHide:2, Vineberry:10");
			BindSet("Ask_Armored", "C. Ask", 22f, 0f, "AskHide:3, FlametalNew:3");
			BindSet("Ask_Magic", "C. Ask", 75f, 0f, "AskHide:2, Eitr:5");
			BindSet("Ask_Stamina", "C. Ask", 85f, 0f, "AskHide:2, CelestialFeather:3");
			BindSet("Embla_Vitality", "D. Embla", 90f, 0f, "LinenThread:5, Vineberry:10");
			BindSet("Embla_Armored", "D. Embla", 20f, 0f, "AskHide:3, Grausten:10");
			BindSet("Embla_Magic", "D. Embla", 90f, 0f, "Eitr:10, MoltenCore:1");
			BindSet("Embla_Stamina", "D. Embla", 75f, 0f, "AskHide:2, CelestialFeather:3");
			BindSet("Flametal_Vitality", "E. Flametal", 110f, 0f, "FlametalNew:2, Vineberry:10");
			BindSet("Flametal_Armored", "E. Flametal", 25f, 0f, "FlametalNew:6, CharredBone:10");
			BindSet("Flametal_Magic", "E. Flametal", 80f, 0f, "FlametalNew:2, MoltenCore:1");
			BindSet("Flametal_Stamina", "E. Flametal", 85f, 0f, "FlametalNew:2, Grausten:10");
			foreach (Cape cape in Plugin.Capes)
			{
				BindCape(cape);
			}
		}

		private static void BindCape(Cape cape)
		{
			string section = "F. Cape - " + cape.Line + " " + cape.Role;
			string role = cape.Role;
			string description = ((role == "Warrior") ? "Less stagger taken, in percent." : ((!(role == "Hunter")) ? "Eitr regeneration, in percent." : "Sneak skill bonus, in skill levels."));
			cape.CfgDamage = Server(section, "Damage bonus", cape.Damage, "Damage bonus for the cape's weapon group (melee / ranged / magic), in percent.");
			cape.CfgExtra = Server(section, "Extra bonus", cape.Extra, description);
			if (cape.Role == "Mage")
			{
				cape.CfgMaxEitr = Server(section, "Max eitr", cape.MaxEitr, "Max eitr given by the cape.");
			}
			cape.CfgResources = Server(section, "Extra resources", cape.ExtraResources, "Added to the vanilla cape. Format: Item:Amount, comma separated. Empty = add nothing.");
			cape.CfgRecipe = Server(section, "Recipe", "", "Own recipe instead of the vanilla one. Format: Item:Amount, comma separated.");
		}

		private static ConfigEntry<T> Server<T>(string section, string key, T value, string description)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			return file.Bind<T>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			} }));
		}

		private static void BindSet(string setId, string line, float bonus, float speed, string extraDefault)
		{
			ArmorSet armorSet = Plugin.Sets.Find((ArmorSet s) => s.Id == setId);
			if (armorSet == null)
			{
				Logger.LogError((object)("Нет комплекта " + setId + " — настройки не привязаны"));
				return;
			}
			string section = line + " - " + armorSet.Bonus;
			armorSet.CfgBonus = Server(section, "Bonus", bonus, BonusHint(armorSet.Bonus));
			armorSet.CfgSpeed = Server(section, "Extra bonus", speed, (armorSet.Bonus == "Stamina") ? "Change of stamina drain while running, in percent. Negative = less drain." : "Change of movement speed, in percent. 0 = no change.");
			armorSet.CfgExtra = Server(section, "Extra resources", extraDefault, "Added to the vanilla recipe of each item. Format: Item:Amount, comma separated. Empty = add nothing.");
			armorSet.CfgHelmet = Server(section, "Helmet recipe", "", "Own recipe instead of the vanilla one. Format: Item:Amount, comma separated. Empty = vanilla recipe plus extra resources.");
			armorSet.CfgChest = Server(section, "Chest recipe", "", "Own recipe instead of the vanilla one. Format: Item:Amount, comma separated. Empty = vanilla recipe plus extra resources.");
			armorSet.CfgLegs = Server(section, "Legs recipe", "", "Own recipe instead of the vanilla one. Format: Item:Amount, comma separated. Empty = vanilla recipe plus extra resources.");
		}

		private static string BonusHint(string bonus)
		{
			return bonus switch
			{
				"Vitality" => "Max health given by the full set.", 
				"Armored" => "Armor given by the full set.", 
				"Magic" => "Max eitr given by the full set.", 
				"Stamina" => "Max stamina given by the full set.", 
				_ => "", 
			};
		}
	}
	internal static class BiomeFilter
	{
		private static readonly string[] Folders = new string[8] { null, "", "BlackForest", "Swamp", "Mountains", "Plains", "Mistlands", "Ashlands" };

		private static readonly string[] Names = new string[8] { "$nokep_biome_all", "$nokep_biome_meadows", "$nokep_biome_blackforest", "$nokep_biome_swamp", "$nokep_biome_mountains", "$nokep_biome_plains", "$nokep_biome_mistlands", "$nokep_biome_ashlands" };

		public static int Current;

		private static Dictionary<string, string> folderByPrefab;

		public static string CurrentName => Translations.Get(Names[Current]);

		public static string PrevName => Translations.Get(Names[Step(-1)]);

		public static string NextName => Translations.Get(Names[Step(1)]);

		public static bool IsOurStation()
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return false;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation != (Object)null)
			{
				return currentCraftingStation.m_name == Table.StationName;
			}
			return false;
		}

		private static int Level()
		{
			CraftingStation station = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetCurrentCraftingStation() : null);
			if (!StationLevel.IsOurs(station))
			{
				return 7;
			}
			return StationLevel.Get(station);
		}

		private static bool IsOpen(int index, int level)
		{
			if (index != 0)
			{
				return index <= level;
			}
			return true;
		}

		private static int Step(int dir)
		{
			int level = Level();
			int num = Current;
			do
			{
				num = (num + dir + Names.Length) % Names.Length;
			}
			while (!IsOpen(num, level));
			return num;
		}

		public static void EnsureOpen()
		{
			if (!IsOpen(Current, Level()))
			{
				Current = 0;
			}
		}

		public static string NameForLevel(int level)
		{
			return Translations.Get(Names[level]);
		}

		public static void Next()
		{
			Current = Step(1);
		}

		public static void Prev()
		{
			Current = Step(-1);
		}

		public static bool Matches(Recipe recipe)
		{
			if (Current == 0)
			{
				return true;
			}
			if ((Object)(object)recipe == (Object)null || (Object)(object)recipe.m_item == (Object)null)
			{
				return false;
			}
			if (folderByPrefab == null)
			{
				BuildMap();
			}
			if (folderByPrefab.TryGetValue(((Object)((Component)recipe.m_item).gameObject).name, out var value))
			{
				return value == Folders[Current];
			}
			return false;
		}

		private static void BuildMap()
		{
			folderByPrefab = new Dictionary<string, string>();
			foreach (ArmorSet set in Plugin.Sets)
			{
				string value = set.IconFolder ?? "";
				folderByPrefab[set.HelmetPrefab] = value;
				folderByPrefab[set.ChestPrefab] = value;
				folderByPrefab[set.LegsPrefab] = value;
			}
			foreach (Cape cape in Plugin.Capes)
			{
				folderByPrefab[cape.Prefab] = cape.IconFolder ?? "";
			}
		}

		public unsafe static string KeyLabel(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Invalid comparison between Unknown and I4
			if ((int)key == 276)
			{
				return "←";
			}
			if ((int)key == 275)
			{
				return "→";
			}
			return ((object)(*(KeyCode*)(&key))/*cast due to .constrained prefix*/).ToString();
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")]
	internal static class BiomeFilter_RecipeList
	{
		private static void Prefix(InventoryGui __instance, List<Recipe> recipes)
		{
			if (!BiomeFilter.IsOurStation())
			{
				return;
			}
			int level = Player.m_localPlayer.GetCurrentCraftingStation().GetLevel(true);
			recipes.RemoveAll((Recipe r) => (Object)(object)r != (Object)null && r.m_minStationLevel > level);
			if (__instance.InCraftTab())
			{
				BiomeFilter.EnsureOpen();
				recipes.RemoveAll((Recipe r) => !BiomeFilter.Matches(r));
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
	internal static class BiomeFilter_Title
	{
		private static void Postfix(InventoryGui __instance)
		{
			if (BiomeFilter.IsOurStation() && __instance.InCraftTab())
			{
				BiomeFilter.EnsureOpen();
				TMP_Text craftingStationName = __instance.m_craftingStationName;
				craftingStationName.text = craftingStationName.text + " — " + BiomeFilter.CurrentName;
				BiomeFilter_Buttons.UpdateLabels();
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Awake")]
	internal static class BiomeFilter_Buttons
	{
		private const float Width = 130f;

		private const float UpgradeWidth = 120f;

		private const float UpgradeHeight = 48f;

		private const float Gap = 8f;

		public static GameObject Prev;

		public static GameObject Next;

		public static GameObject UpgradeButton;

		private static TMP_Text prevText;

		private static TMP_Text nextText;

		private static TMP_Text upgradeText;

		private static UITooltip upgradeTooltip;

		private static void Postfix(InventoryGui __instance)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00b1: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			RectTransform parent = (RectTransform)((Component)__instance.m_tabUpgrade).transform;
			InventoryGui gui = __instance;
			Prev = MakeButton(gui, parent, "NokepBiomePrev", (UnityAction)delegate
			{
				BiomeFilter.Prev();
				gui.UpdateCraftingPanel(true);
			});
			PlaceInTabRow(Prev, 8f);
			Next = MakeButton(gui, parent, "NokepBiomeNext", (UnityAction)delegate
			{
				BiomeFilter.Next();
				gui.UpdateCraftingPanel(true);
			});
			PlaceInTabRow(Next, 142f);
			UpgradeButton = MakeButton(gui, (RectTransform)((Component)gui.m_repairButton).transform, "NokepUpgrade", (UnityAction)delegate
			{
				Player localPlayer = Player.m_localPlayer;
				CraftingStation station = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetCurrentCraftingStation() : null);
				if (StationLevel.IsOurs(station))
				{
					Upgrade.TryUpgrade(localPlayer, station);
					gui.UpdateCraftingPanel(true);
				}
			});
			RectTransform val = (RectTransform)UpgradeButton.transform;
			val.anchorMin = new Vector2(1f, 1f);
			val.anchorMax = new Vector2(1f, 1f);
			val.pivot = new Vector2(1f, 0f);
			val.sizeDelta = new Vector2(120f, 48f);
			val.anchoredPosition = new Vector2(0f, 8f);
			prevText = Prev.GetComponentInChildren<TMP_Text>(true);
			nextText = Next.GetComponentInChildren<TMP_Text>(true);
			upgradeText = UpgradeButton.GetComponentInChildren<TMP_Text>(true);
			upgradeTooltip = AddTooltip(gui, UpgradeButton);
		}

		private static UITooltip AddTooltip(InventoryGui gui, GameObject go)
		{
			UITooltip val = go.GetComponent<UITooltip>();
			if ((Object)(object)val == (Object)null)
			{
				val = go.AddComponent<UITooltip>();
			}
			if ((Object)(object)val.m_tooltipPrefab == (Object)null)
			{
				UITooltip[] componentsInChildren = ((Component)gui).GetComponentsInChildren<UITooltip>(true);
				foreach (UITooltip val2 in componentsInChildren)
				{
					if ((Object)(object)val2 != (Object)(object)val && (Object)(object)val2.m_tooltipPrefab != (Object)null)
					{
						val.m_tooltipPrefab = val2.m_tooltipPrefab;
						break;
					}
				}
			}
			if ((Object)(object)val.m_tooltipPrefab == (Object)null)
			{
				Logger.LogWarning((object)"Не нашёл шаблон подсказки — цена улучшения будет только в сообщении");
			}
			return val;
		}

		public static void UpdateLabels()
		{
			if ((Object)(object)prevText != (Object)null)
			{
				prevText.text = "← " + BiomeFilter.PrevName;
			}
			if ((Object)(object)nextText != (Object)null)
			{
				nextText.text = BiomeFilter.NextName + " →";
			}
			Player localPlayer = Player.m_localPlayer;
			CraftingStation station = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetCurrentCraftingStation() : null);
			if (!StationLevel.IsOurs(station))
			{
				return;
			}
			int num = StationLevel.Get(station) + 1;
			if (num <= 7)
			{
				string text = BiomeFilter.NameForLevel(num);
				if ((Object)(object)upgradeText != (Object)null)
				{
					upgradeText.text = Translations.Get("$nokep_upgrade") + "\n→ " + text;
				}
				if ((Object)(object)upgradeTooltip != (Object)null)
				{
					upgradeTooltip.m_topic = Translations.Get("$nokep_upgrade_title") + ": " + text;
					upgradeTooltip.m_text = Upgrade.CostText(localPlayer, num);
				}
			}
		}

		private static void PlaceInTabRow(GameObject go, float offset)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = (RectTransform)go.transform;
			val.anchorMin = new Vector2(1f, 0f);
			val.anchorMax = new Vector2(1f, 1f);
			val.pivot = new Vector2(0f, 0.5f);
			val.sizeDelta = new Vector2(130f, 0f);
			val.anchoredPosition = new Vector2(offset, 0f);
		}

		private static GameObject MakeButton(InventoryGui gui, RectTransform parent, string name, UnityAction onClick)
		{
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			GameObject val = Object.Instantiate<GameObject>(((Component)gui.m_tabCraft).gameObject, (Transform)(object)parent);
			((Object)val).name = name;
			UIGamePad[] componentsInChildren = val.GetComponentsInChildren<UIGamePad>(true);
			foreach (UIGamePad val2 in componentsInChildren)
			{
				if ((Object)(object)val2.m_hint != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)val2.m_hint);
				}
				Object.DestroyImmediate((Object)(object)val2);
			}
			MonoBehaviour[] componentsInChildren2 = val.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val3 in componentsInChildren2)
			{
				if (((object)val3).GetType().Name == "Localize")
				{
					Object.DestroyImmediate((Object)(object)val3);
				}
			}
			TMP_Text componentInChildren = val.GetComponentInChildren<TMP_Text>(true);
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.fontSizeMax = componentInChildren.fontSize;
				componentInChildren.fontSizeMin = 10f;
				componentInChildren.enableAutoSizing = true;
			}
			val.transform.localScale = Vector3.one;
			Button component = val.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			((Selectable)component).interactable = true;
			((UnityEvent)component.onClick).AddListener(onClick);
			val.SetActive(false);
			return val;
		}

		public static void SetVisible(bool visible)
		{
			Show(Prev, visible);
			Show(Next, visible);
			bool visible2 = false;
			if (visible)
			{
				visible2 = StationLevel.Get(Player.m_localPlayer.GetCurrentCraftingStation()) < 7;
			}
			Show(UpgradeButton, visible2);
		}

		private static void Show(GameObject go, bool visible)
		{
			if ((Object)(object)go != (Object)null && go.activeSelf != visible)
			{
				go.SetActive(visible);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "Update")]
	internal static class BiomeFilter_Keys
	{
		private static void Postfix(InventoryGui __instance)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			bool num = InventoryGui.IsVisible() && BiomeFilter.IsOurStation() && __instance.InCraftTab();
			BiomeFilter_Buttons.SetVisible(num);
			if (num && !__instance.m_splitDialog.IsActive)
			{
				bool flag = false;
				if (ZInput.GetKeyDown(ModConfig.NextBiomeKey.Value, true))
				{
					BiomeFilter.Next();
					flag = true;
				}
				else if (ZInput.GetKeyDown(ModConfig.PrevBiomeKey.Value, true))
				{
					BiomeFilter.Prev();
					flag = true;
				}
				if (flag)
				{
					__instance.UpdateCraftingPanel(true);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "GetTotalFoodValue")]
	internal static class FoodValuePatch
	{
		private static void Postfix(Player __instance, ref float hp, ref float stamina, ref float eitr)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			SEMan sEMan = ((Character)__instance).GetSEMan();
			if (sEMan == null)
			{
				return;
			}
			foreach (ArmorSet set in Plugin.Sets)
			{
				if (!((Object)(object)set.Effect == (Object)null) && sEMan.HaveStatusEffect(set.EffectHash))
				{
					float value = set.CfgBonus.Value;
					switch (set.Bonus)
					{
					case "Vitality":
						hp += value;
						break;
					case "Stamina":
						stamina += value;
						break;
					case "Magic":
						eitr += value;
						break;
					}
				}
			}
			foreach (Cape cape in Plugin.Capes)
			{
				if (!((Object)(object)cape.Effect == (Object)null) && cape.CfgMaxEitr != null && sEMan.HaveStatusEffect(((StatusEffect)cape.Effect).NameHash()))
				{
					eitr += cape.CfgMaxEitr.Value;
				}
			}
		}
	}
	internal static class StationLevel
	{
		public const string ZdoKey = "nokep_level";

		public const int MaxLevel = 7;

		public static bool IsOurs(CraftingStation station)
		{
			if ((Object)(object)station != (Object)null)
			{
				return station.m_name == Table.StationName;
			}
			return false;
		}

		public static int Get(CraftingStation station)
		{
			ZNetView nview = station.m_nview;
			if ((Object)(object)nview == (Object)null || !nview.IsValid())
			{
				return 1;
			}
			return Mathf.Clamp(nview.GetZDO().GetInt("nokep_level", 1), 1, 7);
		}

		public static int ForSet(ArmorSet set)
		{
			return ForFolder(set.IconFolder);
		}

		public static int ForFolder(string folder)
		{
			return folder switch
			{
				"BlackForest" => 2, 
				"Swamp" => 3, 
				"Mountains" => 4, 
				"Plains" => 5, 
				"Mistlands" => 6, 
				"Ashlands" => 7, 
				_ => 1, 
			};
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "GetLevel")]
	internal static class StationLevel_Get
	{
		private static void Postfix(CraftingStation __instance, ref int __result)
		{
			if (StationLevel.IsOurs(__instance))
			{
				__result = StationLevel.Get(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Piece), "DropResources")]
	internal static class StationLevel_Refund
	{
		private static void Postfix(Piece __instance)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			CraftingStation component = ((Component)__instance).GetComponent<CraftingStation>();
			if (!StationLevel.IsOurs(component))
			{
				return;
			}
			int num = StationLevel.Get(component);
			if (num <= 1)
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position + Vector3.up * __instance.m_returnResourceHeightOffset;
			for (int i = 2; i <= num; i++)
			{
				foreach (Requirement item in Upgrade.Cost(i))
				{
					Drop(item.m_resItem, item.m_amount, position);
				}
			}
			Logger.LogInfo((object)$"Возвращены ресурсы за улучшения верстака: уровень {num}");
		}

		private static void Drop(ItemDrop item, int amount, Vector3 position)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.Max(1, item.m_itemData.m_shared.m_maxStackSize);
			while (amount > 0)
			{
				int num2 = Mathf.Min(amount, num);
				amount -= num2;
				ItemDrop component = Object.Instantiate<GameObject>(((Component)item).gameObject, position, Quaternion.identity).GetComponent<ItemDrop>();
				component.SetStack(num2);
				ItemDrop.OnCreateNew(component, false);
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "CanRepair")]
	internal static class StationLevel_Repair
	{
		private static void Postfix(ItemData item, ref bool __result)
		{
			if (__result || item == null || !item.m_shared.m_canBeReparied)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			CraftingStation station = (((Object)(object)localPlayer != (Object)null) ? localPlayer.GetCurrentCraftingStation() : null);
			if (StationLevel.IsOurs(station))
			{
				Recipe val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetRecipe(item) : null);
				if (!((Object)(object)val == (Object)null) && StationLevel.IsOurs(val.m_craftingStation) && StationLevel.Get(station) >= val.m_minStationLevel)
				{
					__result = true;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Recipe), "GetRequiredStationLevel")]
	internal static class StationLevel_Quality
	{
		private static void Postfix(Recipe __instance, ref int __result)
		{
			if (StationLevel.IsOurs(__instance.m_craftingStation))
			{
				__result = Mathf.Max(1, __instance.m_minStationLevel);
			}
		}
	}
	internal static class VanillaArmor
	{
		public static bool Fits(ItemData item, string name, int quality, bool matchWorldLevel)
		{
			if (item.m_shared.m_name == name && !item.m_equipped && (quality < 0 || item.m_quality == quality))
			{
				if (matchWorldLevel)
				{
					return item.m_worldLevel >= Game.m_worldLevel;
				}
				return true;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "CountItems", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(bool)
	})]
	internal static class VanillaArmor_Count
	{
		private static bool Prefix(Inventory __instance, string name, int quality, bool matchWorldLevel, ref int __result)
		{
			if (name == null || !Recipes.VanillaArmorNames.Contains(name))
			{
				return true;
			}
			int num = 0;
			foreach (ItemData item in __instance.m_inventory)
			{
				if (VanillaArmor.Fits(item, name, quality, matchWorldLevel))
				{
					num += item.m_stack;
				}
			}
			__result = num;
			return false;
		}
	}
	[HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(int),
		typeof(bool)
	})]
	internal static class VanillaArmor_Remove
	{
		private static bool Prefix(Inventory __instance, string name, int amount, int itemQuality, bool worldLevelBased)
		{
			if (name == null || !Recipes.VanillaArmorNames.Contains(name))
			{
				return true;
			}
			List<ItemData> list = new List<ItemData>();
			foreach (ItemData item in __instance.m_inventory)
			{
				if (VanillaArmor.Fits(item, name, itemQuality, worldLevelBased))
				{
					list.Add(item);
				}
			}
			list.Sort((ItemData a, ItemData b) => a.m_quality.CompareTo(b.m_quality));
			foreach (ItemData item2 in list)
			{
				if (amount <= 0)
				{
					break;
				}
				int num = ((item2.m_stack < amount) ? item2.m_stack : amount);
				item2.m_stack -= num;
				amount -= num;
				if (item2.m_stack <= 0)
				{
					__instance.m_inventory.Remove(item2);
				}
			}
			__instance.Changed(false, false);
			return false;
		}
	}
	[BepInPlugin("nokep.valheim.armorsets", "NokepArmorSets", "1.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	internal class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "nokep.valheim.armorsets";

		public const string PluginName = "NokepArmorSets";

		public const string PluginVersion = "1.5.0";

		public static readonly List<ArmorSet> Sets = new List<ArmorSet>();

		public static readonly List<Cape> Capes = new List<Cape>();

		private Harmony harmony;

		private bool configDirty;

		private void Awake()
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			Sets.AddRange(Meadows.GetSets());
			Sets.AddRange(BlackForest.GetSets());
			Sets.AddRange(Swamp.GetSets());
			Sets.AddRange(Mountains.GetSets());
			Sets.AddRange(Plains.GetSets());
			Sets.AddRange(Mistlands.GetSets());
			Sets.AddRange(Ashlands.GetSets());
			foreach (ArmorSet set in Sets)
			{
				TypeBuffs.ApplyToAll(set);
			}
			Capes.AddRange(JotunnModStub.Capes.GetCapes());
			ModConfig.Bind(((BaseUnityPlugin)this).Config);
			Translations.Load();
			harmony = new Harmony("nokep.valheim.armorsets");
			harmony.PatchAll();
			CommandManager.Instance.AddConsoleCommand((ConsoleCommand)(object)new UnlockCommand());
			PrefabManager.OnVanillaPrefabsAvailable += AddContent;
			ItemManager.OnItemsRegistered += ApplyConfig;
			SynchronizationManager.OnConfigurationSynchronized += delegate
			{
				configDirty =