Decompiled source of WiresForgeOfPotentialRework v1.1.1

WiresForgeOfPotentialRework.dll

Decompiled 3 weeks ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("WiresForgeOfPotentialRework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("WiresForgeOfPotentialRework")]
[assembly: AssemblyTitle("WiresForgeOfPotentialRework")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace WiresForgeOfPotentialRework
{
	[BepInPlugin("wire.valheim.forgeofpotentialrework", "Wire's Forge of Potential Rework", "1.1.1")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "wire.valheim.forgeofpotentialrework";

		public const string Name = "Wire's Forge of Potential Rework";

		public const string Version = "1.1.1";

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			_harmony = new Harmony("wire.valheim.forgeofpotentialrework");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Wire's Forge of Potential Rework 1.1.1 loaded.");
		}

		private void OnDestroy()
		{
			ForgeContext.Clear();
			if (_harmony != null)
			{
				_harmony.UnpatchSelf();
			}
		}
	}
	internal enum ForgeOutcome
	{
		None,
		Success,
		Jackpot,
		Ignore,
		Loss,
		Break
	}
	internal static class ForgeRules
	{
		internal static float GetWinChance(int potential)
		{
			return Mathf.Max(0.65f, 0.9f - 0.05f * (float)Mathf.Max(0, potential));
		}

		internal static bool LossRiskActive(int potential)
		{
			return potential >= 2;
		}

		internal static bool MultiLossRiskActive(int potential)
		{
			return potential >= 4;
		}

		internal static bool BreakRiskActive(int potential)
		{
			return potential >= 5;
		}

		internal static int RollLossLevels(int potential)
		{
			int num = Mathf.Max(1, potential);
			int i = 1;
			if (!MultiLossRiskActive(potential))
			{
				return i;
			}
			float num2 = 1f - GetWinChance(potential);
			for (; i < num; i++)
			{
				if (!(Random.value < num2))
				{
					break;
				}
			}
			return i;
		}

		internal static float GetConditionalBreakChance(int potential)
		{
			if (!BreakRiskActive(potential))
			{
				return 0f;
			}
			float num = 1f - GetWinChance(potential);
			if (!(num > 0f))
			{
				return 0f;
			}
			return Mathf.Clamp01(0.1f / num);
		}
	}
	internal static class ForgeContext
	{
		internal static bool Active;

		internal static Player Player;

		internal static ItemData OriginalItem;

		internal static ItemData UpgraderResource;

		internal static Recipe Recipe;

		internal static Vector2i OriginalPosition;

		internal static string CraftedPrefabName;

		internal static string SharedItemName;

		internal static int OriginalQuality;

		internal static int AttemptedQuality;

		internal static int TargetQuality;

		internal static int Delta;

		internal static ForgeOutcome Outcome;

		internal static float OldUpgradeChance;

		internal static float OldBreakChance;

		internal static CraftingStation Station;

		internal static EffectList OldFailEffects;

		internal static void Clear()
		{
			Active = false;
			Player = null;
			OriginalItem = null;
			UpgraderResource = null;
			Recipe = null;
			CraftedPrefabName = null;
			SharedItemName = null;
			OriginalQuality = 0;
			AttemptedQuality = 0;
			TargetQuality = 0;
			Delta = 0;
			Outcome = ForgeOutcome.None;
			Station = null;
			OldFailEffects = null;
		}

		internal static void RestoreChanceFields()
		{
			if (UpgraderResource != null && UpgraderResource.m_shared != null)
			{
				UpgraderResource.m_shared.m_upgradeChance = OldUpgradeChance;
				UpgraderResource.m_shared.m_breakChance = OldBreakChance;
				if ((Object)(object)Station != (Object)null && OldFailEffects != null)
				{
					Station.m_craftItemDoneFailEffects = OldFailEffects;
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "DoCrafting")]
	internal static class ForgeCraftPatch
	{
		[HarmonyPrefix]
		private static void Prefix(Recipe ___m_craftRecipe, ItemData ___m_craftUpgradeItem)
		{
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Expected O, but got Unknown
			ForgeContext.Clear();
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)___m_craftRecipe == (Object)null || ___m_craftUpgradeItem == null)
			{
				return;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if ((Object)(object)currentCraftingStation == (Object)null || !currentCraftingStation.m_upgrader)
			{
				return;
			}
			ItemData val = null;
			Requirement[] resources = ___m_craftRecipe.m_resources;
			foreach (Requirement val2 in resources)
			{
				if (val2 != null && val2.m_upgraderResource && (Object)(object)val2.m_resItem != (Object)null)
				{
					val = val2.m_resItem.m_itemData;
					break;
				}
			}
			if (val == null || val.m_shared == null)
			{
				return;
			}
			int num = Mathf.Max(1, ___m_craftRecipe.m_item.m_itemData.m_shared.m_maxQuality);
			int quality = ___m_craftUpgradeItem.m_quality;
			int potential = Mathf.Max(0, quality - num);
			float winChance = ForgeRules.GetWinChance(potential);
			int num2;
			int delta;
			ForgeOutcome forgeOutcome;
			if (Random.value < winChance)
			{
				int j = 1;
				if (Random.value < 0.2f)
				{
					for (j = 2; j < 5; j++)
					{
						if (!(Random.value < 0.2f))
						{
							break;
						}
					}
				}
				num2 = quality + j;
				delta = j;
				forgeOutcome = ((j == 1) ? ForgeOutcome.Success : ForgeOutcome.Jackpot);
			}
			else if (!ForgeRules.LossRiskActive(potential))
			{
				num2 = quality;
				delta = 0;
				forgeOutcome = ForgeOutcome.Ignore;
			}
			else if (ForgeRules.BreakRiskActive(potential) && Random.value < ForgeRules.GetConditionalBreakChance(potential))
			{
				num2 = 0;
				delta = 0;
				forgeOutcome = ForgeOutcome.Break;
			}
			else
			{
				int num3 = ForgeRules.RollLossLevels(potential);
				num2 = Mathf.Max(num, quality - num3);
				delta = num2 - quality;
				forgeOutcome = ForgeOutcome.Loss;
			}
			ForgeContext.Active = true;
			ForgeContext.Player = localPlayer;
			ForgeContext.OriginalItem = ___m_craftUpgradeItem;
			ForgeContext.UpgraderResource = val;
			ForgeContext.Recipe = ___m_craftRecipe;
			ForgeContext.OriginalPosition = ___m_craftUpgradeItem.m_gridPos;
			ForgeContext.CraftedPrefabName = ((Object)((Component)___m_craftRecipe.m_item).gameObject).name;
			ForgeContext.SharedItemName = ___m_craftUpgradeItem.m_shared.m_name;
			ForgeContext.OriginalQuality = quality;
			ForgeContext.AttemptedQuality = quality + 1;
			ForgeContext.TargetQuality = num2;
			ForgeContext.Delta = delta;
			ForgeContext.Outcome = forgeOutcome;
			ForgeContext.OldUpgradeChance = val.m_shared.m_upgradeChance;
			ForgeContext.OldBreakChance = val.m_shared.m_breakChance;
			ForgeContext.Station = currentCraftingStation;
			if (forgeOutcome == ForgeOutcome.Success || forgeOutcome == ForgeOutcome.Jackpot)
			{
				val.m_shared.m_upgradeChance = 2f;
				val.m_shared.m_breakChance = -1f;
				return;
			}
			ForgeContext.OldFailEffects = currentCraftingStation.m_craftItemDoneFailEffects;
			currentCraftingStation.m_craftItemDoneFailEffects = new EffectList();
			val.m_shared.m_upgradeChance = -1f;
			val.m_shared.m_breakChance = ((forgeOutcome == ForgeOutcome.Break) ? 2f : (-1f));
		}

		[HarmonyPostfix]
		private static void Postfix(EffectList ___m_craftBonusEffect)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0086: Unknown result type (might be due to invalid IL or missing references)
			if (!ForgeContext.Active)
			{
				return;
			}
			try
			{
				Player player = ForgeContext.Player;
				if (!((Object)(object)player == (Object)null) && ForgeContext.OriginalItem != null && !((Humanoid)player).GetInventory().ContainsItem(ForgeContext.OriginalItem))
				{
					if (ForgeContext.Outcome == ForgeOutcome.Ignore || ForgeContext.Outcome == ForgeOutcome.Loss || ForgeContext.Outcome == ForgeOutcome.Break)
					{
						PlaySafeFailureEffect(player);
					}
					if (ForgeContext.Outcome == ForgeOutcome.Jackpot && ___m_craftBonusEffect != null)
					{
						___m_craftBonusEffect.Create(((Component)player).transform.position + Vector3.up, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
					}
					ShowResult(player);
				}
			}
			finally
			{
				ForgeContext.RestoreChanceFields();
				ForgeContext.Clear();
			}
		}

		[HarmonyFinalizer]
		private static Exception Finalizer(Exception __exception)
		{
			if (__exception != null && ForgeContext.Active)
			{
				ForgeContext.RestoreChanceFields();
				ForgeContext.Clear();
			}
			return __exception;
		}

		private static void PlaySafeFailureEffect(Player player)
		{
			//IL_001c: 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_002f: 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)
			if ((Object)(object)player == (Object)null || ForgeContext.OldFailEffects == null)
			{
				return;
			}
			GameObject[] array = ForgeContext.OldFailEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			foreach (GameObject val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
				foreach (MonoBehaviour val2 in componentsInChildren)
				{
					if (val2 is IProjectile)
					{
						((Behaviour)val2).enabled = false;
						Object.Destroy((Object)(object)val2);
					}
				}
			}
		}

		private static void ShowResult(Player player)
		{
			string text = ((Localization.instance != null) ? Localization.instance.Localize(ForgeContext.SharedItemName) : ForgeContext.SharedItemName);
			switch (ForgeContext.Outcome)
			{
			case ForgeOutcome.Jackpot:
				((Character)player).Message((MessageType)2, "JACKPOT! " + text + " gained +" + ForgeContext.Delta + " quality (Q" + ForgeContext.TargetQuality + ").", 0, (Sprite)null, true);
				break;
			case ForgeOutcome.Ignore:
				((Character)player).Message((MessageType)2, "Refinement had no effect on " + text + " (Q" + ForgeContext.OriginalQuality + ").", 0, (Sprite)null, true);
				break;
			case ForgeOutcome.Loss:
			{
				int num = -ForgeContext.Delta;
				((Character)player).Message((MessageType)2, text + " lost " + num + " Potential level" + ((num == 1) ? "" : "s") + " (Q" + ForgeContext.TargetQuality + ").", 0, (Sprite)null, true);
				break;
			}
			}
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(string),
		typeof(int),
		typeof(int),
		typeof(int),
		typeof(long),
		typeof(string),
		typeof(Vector2i),
		typeof(bool),
		typeof(bool),
		typeof(bool)
	})]
	internal static class ForgeReturnedItemQualityPatch
	{
		[HarmonyPrefix]
		private static void Prefix(string name, ref int quality, Vector2i position)
		{
			//IL_0014: 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)
			if (ForgeContext.Active && !(name != ForgeContext.CraftedPrefabName) && position.x == ForgeContext.OriginalPosition.x && position.y == ForgeContext.OriginalPosition.y)
			{
				quality = ForgeContext.TargetQuality;
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")]
	internal static class ForgeStatusTextPatch
	{
		private static readonly FieldInfo SelectedRecipeField = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe");

		private static readonly PropertyInfo SelectedItemProperty = ((SelectedRecipeField != null) ? SelectedRecipeField.FieldType.GetProperty("ItemData", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) : null);

		[HarmonyPostfix]
		private static void Postfix(InventoryGui __instance)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)__instance == (Object)null || (Object)(object)localPlayer == (Object)null || (Object)(object)__instance.m_itemCraftType == (Object)null)
			{
				return;
			}
			CraftingStation currentCraftingStation = localPlayer.GetCurrentCraftingStation();
			if (!((Object)(object)currentCraftingStation == (Object)null) && currentCraftingStation.m_upgrader && !(SelectedRecipeField == null) && !(SelectedItemProperty == null))
			{
				object value = SelectedRecipeField.GetValue(__instance);
				object? value2 = SelectedItemProperty.GetValue(value, null);
				ItemData val = (ItemData)((value2 is ItemData) ? value2 : null);
				if (val != null && val.m_shared != null)
				{
					int num = Mathf.Max(1, val.m_shared.m_maxQuality);
					int potential = Mathf.Max(0, val.m_quality - num);
					string text = ((!ForgeRules.LossRiskActive(potential)) ? "The item can withstand further forging." : ((!ForgeRules.MultiLossRiskActive(potential)) ? "Further forging may weaken the item." : (ForgeRules.BreakRiskActive(potential) ? "Further forging may destroy the item." : "Further forging may greatly weaken the item.")));
					((Component)__instance.m_itemCraftType).gameObject.SetActive(true);
					__instance.m_itemCraftType.text = text;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Message")]
	internal static class ForgeVanillaMessagePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(MessageType type, string msg)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if (!ForgeContext.Active || (int)type != 2 || Localization.instance == null)
			{
				return true;
			}
			string text = Localization.instance.Localize("$msg_upgrader_success", new string[2]
			{
				ForgeContext.SharedItemName,
				ForgeContext.AttemptedQuality.ToString()
			});
			string text2 = Localization.instance.Localize("$msg_upgrader_failed", new string[2]
			{
				ForgeContext.SharedItemName,
				(ForgeContext.AttemptedQuality - 2).ToString()
			});
			string text3 = Localization.instance.Localize("$msg_upgrader_broke", new string[2]
			{
				ForgeContext.SharedItemName,
				(ForgeContext.AttemptedQuality - 1).ToString()
			});
			if (msg == text)
			{
				return ForgeContext.Outcome == ForgeOutcome.Success;
			}
			if (msg == text3)
			{
				return ForgeContext.Outcome == ForgeOutcome.Break;
			}
			if (msg == text2)
			{
				return false;
			}
			return true;
		}
	}
}