Decompiled source of WeaponCrafting v0.1.0

plugins/JotunnModStub.dll

Decompiled 2 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using HarmonyLib;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WeaponCraftingMod")]
[assembly: AssemblyDescription("Valheim mod adding SES/Perk Tiers with Smithing skill")]
[assembly: AssemblyCompany("proflupin")]
[assembly: AssemblyProduct("WeaponCraftingMod")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[BepInPlugin("proflupin.weaponcrafting", "WeaponCrafting", "1.0.0")]
public class WeaponCraftingMod : BaseUnityPlugin
{
	private const string DataFileName = "weaponcrafting_smithing.json";

	private SmithingDataStore _store;

	private string DataFilePath => Path.Combine(Paths.ConfigPath, "weaponcrafting_smithing.json");

	private void Awake()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Harmony val = new Harmony("proflupin.weaponcrafting");
		val.PatchAll();
		LoadData();
		try
		{
			Type typeFromHandle = typeof(ZRoutedRpc);
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null)
			{
				MethodInfo[] methods = typeFromHandle.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name != "Register")
					{
						continue;
					}
					ParameterInfo[] parameters = methodInfo.GetParameters();
					if (parameters.Length == 2 && !(parameters[0].ParameterType != typeof(string)))
					{
						Type parameterType = parameters[1].ParameterType;
						bool flag = false;
						try
						{
							MethodInfo method = ((object)this).GetType().GetMethod("OnMasterForgeRpc_Long", BindingFlags.Instance | BindingFlags.NonPublic);
							Delegate @delegate = Delegate.CreateDelegate(parameterType, this, method);
							methodInfo.Invoke(instance, new object[2] { "WeaponCrafting_MasterForge", @delegate });
							flag = true;
						}
						catch
						{
						}
						if (flag)
						{
							break;
						}
						try
						{
							MethodInfo method2 = ((object)this).GetType().GetMethod("OnMasterForgeRpc_ZRpc", BindingFlags.Instance | BindingFlags.NonPublic);
							Delegate delegate2 = Delegate.CreateDelegate(parameterType, this, method2);
							methodInfo.Invoke(instance, new object[2] { "WeaponCrafting_MasterForge", delegate2 });
							flag = true;
						}
						catch
						{
						}
						if (flag)
						{
							break;
						}
					}
				}
			}
		}
		catch
		{
		}
		try
		{
			SetupUpgradePatches(val);
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to setup upgrade patches: {arg}");
		}
	}

	private void OnDestroy()
	{
		SaveData();
	}

	private void LoadData()
	{
		try
		{
			if (File.Exists(DataFilePath))
			{
				string text = File.ReadAllText(DataFilePath);
				_store = JsonConvert.DeserializeObject<SmithingDataStore>(text) ?? new SmithingDataStore();
			}
			else
			{
				_store = new SmithingDataStore();
			}
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to load data: {arg}");
			_store = new SmithingDataStore();
		}
	}

	private void SaveData()
	{
		try
		{
			string directoryName = Path.GetDirectoryName(DataFilePath);
			if (!Directory.Exists(directoryName))
			{
				Directory.CreateDirectory(directoryName);
			}
			string contents = JsonConvert.SerializeObject((object)_store, (Formatting)1);
			File.WriteAllText(DataFilePath, contents);
		}
		catch (Exception arg)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to save data: {arg}");
		}
	}

	private void OnMasterForgeRpc_Long(long sender, ZPackage pkg)
	{
		try
		{
			if (pkg != null)
			{
				string text = pkg.ReadString();
				string text2 = pkg.ReadString();
				string text3 = pkg.ReadString();
				string text4 = ((Random.Range(0, 100) >= 50) ? ("The " + text2 + " of " + text + " shall be revered throughout the ages") : ("Odin smiles upon " + text + "'s " + text2 + ", bestowing his great power upon it"));
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, text4, 0, (Sprite)null, false);
				}
				Debug.Log((object)("[WeaponCrafting] Master-forge broadcast: " + text + " -> " + text2 + " (boon: " + text3 + ")"));
			}
		}
		catch
		{
		}
	}

	private void OnMasterForgeRpc_ZRpc(ZRpc rpc, ZPackage pkg)
	{
		try
		{
			if (pkg != null)
			{
				string text = pkg.ReadString();
				string text2 = pkg.ReadString();
				string text3 = pkg.ReadString();
				string text4 = ((Random.Range(0, 100) >= 50) ? ("The " + text2 + " of " + text + " shall be revered throughout the ages") : ("Odin smiles upon " + text + "'s " + text2 + ", bestowing his great power upon it"));
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)2, text4, 0, (Sprite)null, false);
				}
				Debug.Log((object)("[WeaponCrafting] Master-forge broadcast: " + text + " -> " + text2 + " (boon: " + text3 + ")"));
			}
		}
		catch
		{
		}
	}

	public void AddSmithingXP(string playerName, int xp)
	{
		if (!string.IsNullOrEmpty(playerName) && xp > 0)
		{
			SmithingEntry orCreate = _store.GetOrCreate(playerName);
			orCreate.XP += xp;
			orCreate.Level = ComputeLevelFromXP(orCreate.XP);
			SaveData();
		}
	}

	private int ComputeLevelFromXP(int xp)
	{
		int i = 1;
		int num = xp;
		for (; i < 100; i++)
		{
			int num2 = (int)Math.Floor(80.0 * Math.Pow(1.05, i - 1));
			if (num < num2)
			{
				break;
			}
			num -= num2;
		}
		if (i < 1)
		{
			i = 1;
		}
		if (i > 100)
		{
			i = 100;
		}
		return i;
	}

	public SmithingEntry GetSmithingFor(string playerName)
	{
		return _store.GetOrCreate(playerName);
	}

	private void SetupUpgradePatches(Harmony harmony)
	{
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Expected O, but got Unknown
		try
		{
			Assembly assembly = typeof(Player).Assembly;
			List<MethodInfo> list = new List<MethodInfo>();
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.IsGenericType || type.IsInterface)
				{
					continue;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					string text = methodInfo.Name.ToLower();
					if ((text.Contains("upgrade") || text.Contains("upgradeitem") || text.Contains("do_upgrade") || text.Contains("upgrade_piece") || text.Contains("upgradepiece")) && methodInfo.ReturnType == typeof(void))
					{
						list.Add(methodInfo);
					}
				}
			}
			MethodInfo method = typeof(WeaponCraftingMod).GetMethod("Upgrade_Postfix", BindingFlags.Static | BindingFlags.NonPublic);
			int num = 0;
			foreach (MethodInfo item in list)
			{
				try
				{
					HarmonyMethod val = new HarmonyMethod(method);
					harmony.Patch((MethodBase)item, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					((BaseUnityPlugin)this).Logger.LogInfo((object)("WeaponCrafting: patched upgrade method " + item.DeclaringType.FullName + "." + item.Name));
					num++;
				}
				catch (Exception arg)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: failed to patch {item.DeclaringType.FullName}.{item.Name}: {arg}");
				}
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"WeaponCrafting: patched {num} upgrade methods");
		}
		catch (Exception arg2)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)$"WeaponCrafting: SetupUpgradePatches error: {arg2}");
		}
	}

	private static int GetPieceLevel(Piece piece)
	{
		if ((Object)(object)piece == (Object)null)
		{
			return 1;
		}
		try
		{
			FieldInfo field = typeof(Piece).GetField("m_level", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				object value = field.GetValue(piece);
				if (value is int)
				{
					int num = (int)value;
					return (num <= 0) ? 1 : num;
				}
			}
		}
		catch
		{
		}
		return 1;
	}

	private static void Upgrade_Postfix(object __instance, object[] __args)
	{
		//IL_00b0: 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)
		try
		{
			Player val = null;
			Player val2 = (Player)((__instance is Player) ? __instance : null);
			if (val2 != null)
			{
				val = val2;
			}
			if ((Object)(object)val == (Object)null && __args != null)
			{
				foreach (object obj in __args)
				{
					Player val3 = (Player)((obj is Player) ? obj : null);
					if (val3 != null)
					{
						val = val3;
						break;
					}
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				val = Player.m_localPlayer;
			}
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Piece val4 = null;
			Piece val5 = null;
			try
			{
				Piece[] array = Object.FindObjectsOfType<Piece>();
				float num = 999f;
				float num2 = 999f;
				Piece[] array2 = array;
				foreach (Piece val6 in array2)
				{
					if ((Object)(object)val6 == (Object)null || (Object)(object)((Component)val6).gameObject == (Object)null)
					{
						continue;
					}
					float num3 = Vector3.Distance(((Component)val6).transform.position, ((Component)val).transform.position);
					if (!(num3 > 3f))
					{
						string text = ((Object)((Component)val6).gameObject).name.ToLower();
						if ((text.Contains("blackforge") || text.Contains("forge_black")) && num3 < num2)
						{
							val5 = val6;
							num2 = num3;
						}
						if (text.Contains("forge") && !text.Contains("black") && num3 < num)
						{
							val4 = val6;
							num = num3;
						}
					}
				}
			}
			catch
			{
			}
			WeaponCraftingMod component = Chainloader.ManagerObject.GetComponent<WeaponCraftingMod>();
			if (!((Object)(object)component == (Object)null))
			{
				if ((Object)(object)val5 != (Object)null)
				{
					int pieceLevel = GetPieceLevel(val5);
					int num4 = 13 + 2 * pieceLevel;
					component.AddSmithingXP(val.GetPlayerName(), num4);
					Debug.Log((object)$"[WeaponCrafting] Upgrade near black forge level {pieceLevel}: +{num4} XP to {val.GetPlayerName()}");
				}
				else if ((Object)(object)val4 != (Object)null)
				{
					int pieceLevel2 = GetPieceLevel(val4);
					int num5 = 8 + 2 * pieceLevel2;
					component.AddSmithingXP(val.GetPlayerName(), num5);
					Debug.Log((object)$"[WeaponCrafting] Upgrade near forge level {pieceLevel2}: +{num5} XP to {val.GetPlayerName()}");
				}
			}
		}
		catch
		{
		}
	}

	private void BroadcastMasterForgeRpc(string playerName, string itemName, string boon)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		try
		{
			ZPackage val = new ZPackage();
			val.Write(playerName);
			val.Write(itemName);
			val.Write(boon ?? string.Empty);
			ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "WeaponCrafting_MasterForge", new object[1] { val });
			Debug.Log((object)("[WeaponCrafting] Broadcast master-forge RPC: " + playerName + " -> " + itemName));
		}
		catch (Exception arg)
		{
			Debug.LogWarning((object)$"[WeaponCrafting] BroadcastMasterForgeRpc error: {arg}");
		}
	}

	private static bool InventoryBelongsTo(Inventory inv, params string[] keywords)
	{
		try
		{
			if (inv == null)
			{
				return false;
			}
			Type type = ((object)inv).GetType();
			FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				try
				{
					object value = fieldInfo.GetValue(inv);
					if (value == null)
					{
						continue;
					}
					GameObject val = (GameObject)((value is GameObject) ? value : null);
					string[] array;
					if (val != null)
					{
						string text = ((Object)val).name.ToLower();
						array = keywords;
						foreach (string text2 in array)
						{
							if (text.Contains(text2.ToLower()))
							{
								return true;
							}
						}
						continue;
					}
					Component val2 = (Component)((value is Component) ? value : null);
					if (val2 != null)
					{
						string text3 = ((Object)val2.gameObject).name.ToLower();
						array = keywords;
						foreach (string text4 in array)
						{
							if (text3.Contains(text4.ToLower()))
							{
								return true;
							}
						}
						continue;
					}
					string text5 = value.ToString();
					if (string.IsNullOrEmpty(text5))
					{
						continue;
					}
					string text6 = text5.ToLower();
					array = keywords;
					foreach (string text7 in array)
					{
						if (text6.Contains(text7.ToLower()))
						{
							return true;
						}
					}
				}
				catch
				{
				}
			}
			PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				try
				{
					object value2 = propertyInfo.GetValue(inv);
					if (value2 == null)
					{
						continue;
					}
					GameObject val3 = (GameObject)((value2 is GameObject) ? value2 : null);
					string[] array;
					if (val3 != null)
					{
						string text8 = ((Object)val3).name.ToLower();
						array = keywords;
						foreach (string text9 in array)
						{
							if (text8.Contains(text9.ToLower()))
							{
								return true;
							}
						}
						continue;
					}
					Component val4 = (Component)((value2 is Component) ? value2 : null);
					if (val4 != null)
					{
						string text10 = ((Object)val4.gameObject).name.ToLower();
						array = keywords;
						foreach (string text11 in array)
						{
							if (text10.Contains(text11.ToLower()))
							{
								return true;
							}
						}
						continue;
					}
					string text12 = value2.ToString();
					if (string.IsNullOrEmpty(text12))
					{
						continue;
					}
					string text13 = text12.ToLower();
					array = keywords;
					foreach (string text14 in array)
					{
						if (text13.Contains(text14.ToLower()))
						{
							return true;
						}
					}
				}
				catch
				{
				}
			}
		}
		catch
		{
		}
		return false;
	}

	public void ApplySmithingOnCreate(Player player, ItemData item)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: 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_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_034f: Unknown result type (might be due to invalid IL or missing references)
		//IL_036d: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0422: Unknown result type (might be due to invalid IL or missing references)
		//IL_040a: Unknown result type (might be due to invalid IL or missing references)
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0432: Unknown result type (might be due to invalid IL or missing references)
		//IL_0472: Unknown result type (might be due to invalid IL or missing references)
		//IL_045a: Unknown result type (might be due to invalid IL or missing references)
		//IL_049a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0482: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0512: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0525: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)player == (Object)null || item == null)
		{
			return;
		}
		int level = GetSmithingFor(player.GetPlayerName()).Level;
		_ = item.m_shared.m_damages;
		bool flag = item.m_shared.m_damages.m_slash > 0f || item.m_shared.m_damages.m_blunt > 0f || item.m_shared.m_damages.m_pierce > 0f;
		bool flag2 = item.m_shared.m_armor > 0f || item.m_shared.m_blockPower > 0f;
		int num = Random.Range(5, 9) + Mathf.FloorToInt((float)level / 3f) + 2;
		if (item.m_durability > 0f)
		{
			item.m_durability += (float)num;
		}
		if (item.m_shared.m_maxDurability > 0f)
		{
			SharedData shared = item.m_shared;
			shared.m_maxDurability += (float)num;
		}
		if (flag)
		{
			int num2 = Random.Range(3, 6) + Mathf.Max(2, Mathf.FloorToInt((float)level / 5f));
			DamageTypes damages = item.m_shared.m_damages;
			if (damages.m_slash > 0f)
			{
				damages.m_slash += num2;
			}
			if (damages.m_blunt > 0f)
			{
				damages.m_blunt += num2;
			}
			if (damages.m_pierce > 0f)
			{
				damages.m_pierce += num2;
			}
			if (damages.m_fire > 0f)
			{
				damages.m_fire += num2;
			}
			if (damages.m_frost > 0f)
			{
				damages.m_frost += num2;
			}
			if (damages.m_poison > 0f)
			{
				damages.m_poison += num2;
			}
			if (damages.m_lightning > 0f)
			{
				damages.m_lightning += num2;
			}
			if (damages.m_spirit > 0f)
			{
				damages.m_spirit += num2;
			}
		}
		if (flag2)
		{
			int num3 = Random.Range(4, 7) + Mathf.Max(2, Mathf.FloorToInt((float)level / 4f));
			SharedData shared2 = item.m_shared;
			shared2.m_armor += (float)num3;
			SharedData shared3 = item.m_shared;
			shared3.m_blockPower += (float)num3;
		}
		int num4 = Mathf.Clamp(level, 1, 100);
		int num5 = ((num4 <= 40) ? 40 : ((num4 <= 75) ? 50 : 60));
		if (Random.Range(0, 100) >= num5)
		{
			return;
		}
		if (item.m_shared.m_maxDurability > 0f)
		{
			SharedData shared4 = item.m_shared;
			shared4.m_maxDurability += 20f;
		}
		DamageTypes damages2 = item.m_shared.m_damages;
		if (damages2.m_slash > 0f)
		{
			damages2.m_slash += 5f;
		}
		if (damages2.m_blunt > 0f)
		{
			damages2.m_blunt += 5f;
		}
		if (damages2.m_pierce > 0f)
		{
			damages2.m_pierce += 5f;
		}
		if (damages2.m_fire > 0f)
		{
			damages2.m_fire += 5f;
		}
		if (damages2.m_frost > 0f)
		{
			damages2.m_frost += 5f;
		}
		if (damages2.m_poison > 0f)
		{
			damages2.m_poison += 5f;
		}
		if (damages2.m_lightning > 0f)
		{
			damages2.m_lightning += 5f;
		}
		if (damages2.m_spirit > 0f)
		{
			damages2.m_spirit += 5f;
		}
		int num6 = 40 + Mathf.FloorToInt((float)level / 3f);
		int num7 = Random.Range(0, 100);
		string text = null;
		if (num7 < num6)
		{
			if (flag)
			{
				int num8 = Random.Range(0, 100);
				if (num8 < 40)
				{
					text = "Razor";
					DamageTypes damages3 = item.m_shared.m_damages;
					if (damages3.m_slash > 0f)
					{
						damages3.m_slash = Mathf.FloorToInt(damages3.m_slash * 1.25f);
					}
					if (damages3.m_blunt > 0f)
					{
						damages3.m_blunt = Mathf.FloorToInt(damages3.m_blunt * 1.25f);
					}
					if (damages3.m_pierce > 0f)
					{
						damages3.m_pierce = Mathf.FloorToInt(damages3.m_pierce * 1.25f);
					}
					if (damages3.m_fire > 0f)
					{
						damages3.m_fire = Mathf.FloorToInt(damages3.m_fire * 1.25f);
					}
					if (damages3.m_frost > 0f)
					{
						damages3.m_frost = Mathf.FloorToInt(damages3.m_frost * 1.25f);
					}
					if (damages3.m_poison > 0f)
					{
						damages3.m_poison = Mathf.FloorToInt(damages3.m_poison * 1.25f);
					}
					if (damages3.m_lightning > 0f)
					{
						damages3.m_lightning = Mathf.FloorToInt(damages3.m_lightning * 1.25f);
					}
					if (damages3.m_spirit > 0f)
					{
						damages3.m_spirit = Mathf.FloorToInt(damages3.m_spirit * 1.25f);
					}
				}
				else if (num8 < 80)
				{
					text = "Ogre";
					item.m_shared.m_attackForce = Mathf.FloorToInt(item.m_shared.m_attackForce * 1.75f);
				}
				else
				{
					text = "Goblin";
					if (item.m_customData == null)
					{
						item.m_customData = new Dictionary<string, string>();
					}
					item.m_customData["GOBLIN_BOON"] = "1";
				}
			}
			else if (flag2)
			{
				if (item.m_shared.m_blockPower > 0f)
				{
					if (Random.Range(0, 100) < 50)
					{
						text = "Stalwart";
						item.m_shared.m_blockPower = Mathf.FloorToInt(item.m_shared.m_blockPower * 1.6f);
					}
					else
					{
						text = "Sealed";
						item.m_shared.m_armor = Mathf.FloorToInt(item.m_shared.m_armor * 1.35f);
					}
				}
				else if (Random.Range(0, 100) < 60)
				{
					text = "Reinforced";
					item.m_shared.m_armor = Mathf.FloorToInt(item.m_shared.m_armor * 1.25f);
				}
				else
				{
					text = "Feather";
					if (item.m_customData == null)
					{
						item.m_customData = new Dictionary<string, string>();
					}
					item.m_customData["FEATHER_BOON"] = "1";
				}
			}
		}
		string playerName = player.GetPlayerName();
		string name = item.m_shared.m_name;
		string text2 = "Odin smiles upon " + playerName + "'s " + name + ", bestowing his great power upon it";
		if ((Object)(object)MessageHud.instance != (Object)null)
		{
			MessageHud.instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false);
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("[WeaponCrafting] Master-forged: " + playerName + " -> " + name + " (boon: " + (text ?? "None") + ")"));
		BroadcastMasterForgeRpc(playerName, name, text ?? string.Empty);
	}
}
public class SmithingDataStore
{
	public List<SmithingEntry> Players = new List<SmithingEntry>();

	public SmithingEntry GetOrCreate(string name)
	{
		SmithingEntry smithingEntry = Players.Find((SmithingEntry x) => x.Name == name);
		if (smithingEntry == null)
		{
			smithingEntry = new SmithingEntry
			{
				Name = name,
				XP = 0,
				Level = 1
			};
			Players.Add(smithingEntry);
		}
		return smithingEntry;
	}
}
public class SmithingEntry
{
	public string Name;

	public int XP;

	public int Level;
}
public static class CharacterExtensions
{
	private static readonly FieldInfo RightItemField = typeof(Humanoid).GetField("m_rightItem", BindingFlags.Instance | BindingFlags.NonPublic);

	public static ItemData GetRightHandItem(this Character character)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001b: Expected O, but got Unknown
		Humanoid val = (Humanoid)(object)((character is Humanoid) ? character : null);
		if (val != null)
		{
			return (ItemData)RightItemField.GetValue(val);
		}
		return null;
	}
}
[HarmonyPatch(typeof(Inventory), "AddItem")]
public class Inventory_AddItem_Smithing_Patch
{
	private static void Postfix(ItemData item, Inventory __instance)
	{
		//IL_0375: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_029d: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (item == null || __instance == null)
			{
				return;
			}
			WeaponCraftingMod component = Chainloader.ManagerObject.GetComponent<WeaponCraftingMod>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			object obj = ((object)component).GetType().GetMethod("InventoryBelongsTo", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[2]
			{
				__instance,
				new string[1] { "kiln" }
			});
			bool flag = default(bool);
			int num;
			if (obj is bool)
			{
				flag = (bool)obj;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0 && item.m_shared.m_name.ToLower().Contains("wood") && (Object)(object)localPlayer != (Object)null)
			{
				component.AddSmithingXP(localPlayer.GetPlayerName(), 5);
				Debug.Log((object)("[WeaponCrafting] Kiln fed by " + localPlayer.GetPlayerName() + ": +5 XP"));
			}
			obj = ((object)component).GetType().GetMethod("InventoryBelongsTo", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[2]
			{
				__instance,
				new string[1] { "smelter" }
			});
			bool flag2 = default(bool);
			int num2;
			if (obj is bool)
			{
				flag2 = (bool)obj;
				num2 = 1;
			}
			else
			{
				num2 = 0;
			}
			if (((uint)num2 & (flag2 ? 1u : 0u)) != 0)
			{
				string text = item.m_shared.m_name.ToLower();
				if ((text.Contains("coal") || text.Contains("ore") || text.Contains("iron") || text.Contains("copper") || text.Contains("silver")) && (Object)(object)localPlayer != (Object)null)
				{
					component.AddSmithingXP(localPlayer.GetPlayerName(), 10);
					Debug.Log((object)("[WeaponCrafting] Smelter fed by " + localPlayer.GetPlayerName() + ": +10 XP"));
				}
			}
			obj = ((object)component).GetType().GetMethod("InventoryBelongsTo", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[2]
			{
				__instance,
				new string[1] { "blast" }
			});
			bool flag3 = default(bool);
			int num3;
			if (obj is bool)
			{
				flag3 = (bool)obj;
				num3 = 1;
			}
			else
			{
				num3 = 0;
			}
			if (((uint)num3 & (flag3 ? 1u : 0u)) != 0)
			{
				string text2 = item.m_shared.m_name.ToLower();
				if ((text2.Contains("coal") || text2.Contains("ore") || text2.Contains("iron") || text2.Contains("copper") || text2.Contains("silver")) && (Object)(object)localPlayer != (Object)null)
				{
					component.AddSmithingXP(localPlayer.GetPlayerName(), 15);
					Debug.Log((object)("[WeaponCrafting] Blast furnace fed by " + localPlayer.GetPlayerName() + ": +15 XP"));
				}
			}
			if (!((Object)(object)localPlayer != (Object)null) || __instance != ((Humanoid)localPlayer).GetInventory())
			{
				return;
			}
			Vector3 position = ((Component)localPlayer).transform.position;
			Piece val = null;
			Piece val2 = null;
			float num4 = 999f;
			float num5 = 999f;
			try
			{
				IEnumerable<Piece> enumerable = null;
				MethodInfo method = typeof(Object).GetMethod("FindObjectsByType", BindingFlags.Static | BindingFlags.Public);
				if (method != null)
				{
					try
					{
						MethodInfo methodInfo = (method.IsGenericMethod ? method.MakeGenericMethod(typeof(Piece)) : null);
						if (methodInfo != null)
						{
							enumerable = (IEnumerable<Piece>)methodInfo.Invoke(null, new object[1] { 0 });
						}
					}
					catch
					{
					}
				}
				if (enumerable == null)
				{
					enumerable = Object.FindObjectsOfType<Piece>();
				}
				foreach (Piece item2 in enumerable)
				{
					if ((Object)(object)item2 == (Object)null || (Object)(object)((Component)item2).gameObject == (Object)null)
					{
						continue;
					}
					float num6 = Vector3.Distance(((Component)item2).transform.position, position);
					if (!(num6 > 3f))
					{
						string text3 = ((Object)((Component)item2).gameObject).name.ToLower();
						if ((text3.Contains("blackforge") || text3.Contains("forge_black")) && num6 < num5)
						{
							val2 = item2;
							num5 = num6;
						}
						if (text3.Contains("forge") && !text3.Contains("black") && num6 < num4)
						{
							val = item2;
							num4 = num6;
						}
					}
				}
			}
			catch
			{
			}
			if ((Object)(object)val2 != (Object)null)
			{
				int num8 = ((!(((object)component).GetType().GetMethod("GetPieceLevel", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[1] { val2 }) is int num7)) ? 1 : num7);
				int num9 = 26 + 4 * num8;
				component.AddSmithingXP(localPlayer.GetPlayerName(), num9);
				component.ApplySmithingOnCreate(localPlayer, item);
				Debug.Log((object)$"[WeaponCrafting] Craft on black forge level {num8}: +{num9} XP to {localPlayer.GetPlayerName()}");
			}
			else if ((Object)(object)val != (Object)null)
			{
				int num11 = ((!(((object)component).GetType().GetMethod("GetPieceLevel", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[1] { val }) is int num10)) ? 1 : num10);
				int num12 = 13 + 2 * num11;
				component.AddSmithingXP(localPlayer.GetPlayerName(), num12);
				component.ApplySmithingOnCreate(localPlayer, item);
				Debug.Log((object)$"[WeaponCrafting] Craft on forge level {num11}: +{num12} XP to {localPlayer.GetPlayerName()}");
			}
		}
		catch (Exception arg)
		{
			Debug.LogWarning((object)$"WeaponCrafting: Inventory.AddItem patch error: {arg}");
		}
	}
}
[HarmonyPatch(typeof(Humanoid), "UpdateEquipment")]
public class Humanoid_Equip_Boons_Patch
{
	private static readonly Dictionary<int, float> OrigAttackSpeed = new Dictionary<int, float>();

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

	private static void Postfix(Humanoid __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		try
		{
			ItemData rightHandItem = ((Character)(object)__instance).GetRightHandItem();
			int instanceID = ((Object)__instance).GetInstanceID();
			FieldInfo fieldInfo = typeof(Humanoid).GetField("m_attackSpeed", BindingFlags.Instance | BindingFlags.NonPublic) ?? typeof(Humanoid).GetField("m_attackSpeedMultiplier", BindingFlags.Instance | BindingFlags.NonPublic);
			if (fieldInfo != null)
			{
				float value = ((fieldInfo.GetValue(__instance) is float num) ? num : 1f);
				if (!OrigAttackSpeed.ContainsKey(instanceID))
				{
					OrigAttackSpeed[instanceID] = value;
				}
				float num2 = OrigAttackSpeed[instanceID];
				if (rightHandItem != null && rightHandItem.m_customData != null && rightHandItem.m_customData.ContainsKey("GOBLIN_BOON"))
				{
					fieldInfo.SetValue(__instance, num2 * 0.85f);
				}
				else
				{
					fieldInfo.SetValue(__instance, num2);
				}
			}
			string[] obj = new string[4] { "m_runSpeed", "m_moveSpeed", "m_walkSpeed", "m_speed" };
			FieldInfo fieldInfo2 = null;
			string[] array = obj;
			foreach (string name in array)
			{
				fieldInfo2 = typeof(Humanoid).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic);
				if (fieldInfo2 != null)
				{
					break;
				}
			}
			if (fieldInfo2 != null)
			{
				float value2 = ((fieldInfo2.GetValue(__instance) is float num3) ? num3 : 1f);
				if (!OrigMoveSpeed.ContainsKey(instanceID))
				{
					OrigMoveSpeed[instanceID] = value2;
				}
				float num4 = OrigMoveSpeed[instanceID];
				if (rightHandItem != null && rightHandItem.m_customData != null && rightHandItem.m_customData.ContainsKey("FEATHER_BOON"))
				{
					fieldInfo2.SetValue(__instance, num4 * 1.03f);
				}
				else
				{
					fieldInfo2.SetValue(__instance, num4);
				}
			}
		}
		catch
		{
		}
	}
}