Decompiled source of PotentialReforged v1.0.4

PotentialReforged.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PotentialReforged")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.4.0")]
[assembly: AssemblyInformationalVersion("1.0.4")]
[assembly: AssemblyProduct("PotentialReforged")]
[assembly: AssemblyTitle("PotentialReforged")]
[assembly: AssemblyVersion("1.0.4.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 PotentialReforged
{
	[BepInPlugin("Dyls123.PotentialReforged", "Potential Reforged", "1.0.4")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "Dyls123.PotentialReforged";

		internal static ConfigEntry<float> SuccessChance;

		internal static ConfigEntry<bool> BreakOnFailure;

		internal static ConfigEntry<bool> ReduceLevelOnFailure;

		internal static ConfigEntry<int> LevelsLostOnFailure;

		private Harmony harmony;

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			SuccessChance = ((BaseUnityPlugin)this).Config.Bind<float>("Chances", "SuccessChance", 65f, new ConfigDescription("Success percentage. Failure chance is 100 minus this value. 0 always fails; 100 always succeeds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			BreakOnFailure = ((BaseUnityPlugin)this).Config.Bind<bool>("Failure", "BreakOnFailure", false, "True: EVERY failed refinement destroys the item using the normal break/refund behavior. False: failed refinement never destroys the item. Overrides ReduceLevelOnFailure.");
			ReduceLevelOnFailure = ((BaseUnityPlugin)this).Config.Bind<bool>("Failure", "ReduceLevelOnFailure", true, "When BreakOnFailure is false: true reduces quality by LevelsLostOnFailure (minimum quality 1); false keeps the current level. Normal idol/material costs still apply.");
			LevelsLostOnFailure = ((BaseUnityPlugin)this).Config.Bind<int>("Failure", "LevelsLostOnFailure", 1, new ConfigDescription("Number of quality levels lost on failure, from 1 to 10. Only applies when ReduceLevelOnFailure is true and BreakOnFailure is false. Item quality cannot fall below 1.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), Array.Empty<object>()));
			harmony = new Harmony("Dyls123.PotentialReforged");
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "DoCrafting", new Type[1] { typeof(Player) }, (Type[])null);
				if (methodInfo == null)
				{
					throw new MissingMethodException("InventoryGui.DoCrafting(Player)");
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(ForgePatch), "Transpiler", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Potential Reforged 1.0.4: all Forge patches installed. Client-only; no server installation needed.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Success={SuccessChance.Value}%, failure={100f - SuccessChance.Value}%, break={BreakOnFailure.Value}, reduce level={ReduceLevelOnFailure.Value}.");
			}
			catch (Exception ex)
			{
				harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogError((object)("Potential Reforged could not patch this game build. No changes applied; vanilla rules remain active. " + ex));
			}
		}

		private void OnDestroy()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		public static float GetSuccessThreshold(float original)
		{
			return RefinementRules.SuccessThreshold(SuccessChance.Value);
		}

		public static float GetBreakThreshold(float original)
		{
			return RefinementRules.BreakThreshold(BreakOnFailure.Value);
		}

		public static int GetFailureQuality(int targetQuality, int vanillaReduction)
		{
			return RefinementRules.FailureQuality(targetQuality, ReduceLevelOnFailure.Value, LevelsLostOnFailure.Value);
		}

		public static string GetFailureMessage()
		{
			if (!ReduceLevelOnFailure.Value)
			{
				return "Refinement failed. Your item keeps its current level.";
			}
			return "$msg_upgrader_failed";
		}
	}
	public static class ForgePatch
	{
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.Select((Func<CodeInstruction, CodeInstruction>)((CodeInstruction i) => new CodeInstruction(i))).ToList();
			Type typeFromHandle = typeof(SharedData);
			FieldInfo successField = typeFromHandle.GetField("m_upgradeChance");
			FieldInfo breakField = typeFromHandle.GetField("m_breakChance");
			List<CodeInstruction> list2 = list.FindAll((CodeInstruction i) => CodeInstructionExtensions.LoadsField(i, successField, false));
			List<CodeInstruction> list3 = list.FindAll((CodeInstruction i) => CodeInstructionExtensions.LoadsField(i, breakField, false));
			List<CodeInstruction> list4 = list.FindAll((CodeInstruction i) => i.opcode == OpCodes.Ldstr && object.Equals(i.operand, "$msg_upgrader_failed"));
			List<CodeInstruction> list5 = list.FindAll((CodeInstruction i) => i.opcode == OpCodes.Ldstr && i.operand is string text && text.StartsWith("Upgrader <color=orange>FAILED"));
			Require(list2.Count == 1 && list3.Count == 1 && list4.Count == 1 && list5.Count == 1, "Expected exactly one success, break, failure message and failure log site.");
			int num = list.IndexOf(list4[0]);
			int num2 = list.FindIndex(num, (CodeInstruction i) => i.operand is MethodInfo methodInfo && methodInfo.DeclaringType == typeof(Inventory) && methodInfo.Name == "AddItem");
			Require(num2 > num, "Could not locate the failure item creation.");
			List<CodeInstruction> list6 = new List<CodeInstruction>();
			for (int num3 = num + 2; num3 < num2; num3++)
			{
				if (list[num3].opcode == OpCodes.Sub && CodeInstructionExtensions.LoadsConstant(list[num3 - 1], 2L) && IsLoadLocal(list[num3 - 2].opcode))
				{
					list6.Add(list[num3]);
				}
			}
			Require(list6.Count == 2, "Expected two failure quality calculations (message and item).");
			foreach (CodeInstruction item in list6)
			{
				item.opcode = OpCodes.Call;
				item.operand = typeof(Plugin).GetMethod("GetFailureQuality");
			}
			list4[0].opcode = OpCodes.Call;
			list4[0].operand = typeof(Plugin).GetMethod("GetFailureMessage");
			list5[0].operand = "Upgrader <color=orange>FAILED</color> {0} at level {1}; Potential Reforged failure settings applied.";
			list.Insert(list.IndexOf(list2[0]) + 1, new CodeInstruction(OpCodes.Call, (object)typeof(Plugin).GetMethod("GetSuccessThreshold")));
			list.Insert(list.IndexOf(list3[0]) + 1, new CodeInstruction(OpCodes.Call, (object)typeof(Plugin).GetMethod("GetBreakThreshold")));
			return list;
		}

		private static void Require(bool condition, string reason)
		{
			if (!condition)
			{
				throw new InvalidOperationException("Unsupported or conflicting Forge crafting code: " + reason);
			}
		}

		private static bool IsLoadLocal(OpCode op)
		{
			if (!(op == OpCodes.Ldloc) && !(op == OpCodes.Ldloc_S) && !(op == OpCodes.Ldloc_0) && !(op == OpCodes.Ldloc_1) && !(op == OpCodes.Ldloc_2))
			{
				return op == OpCodes.Ldloc_3;
			}
			return true;
		}
	}
	public static class RefinementRules
	{
		public static float SuccessThreshold(float percent)
		{
			if (float.IsNaN(percent) || float.IsInfinity(percent))
			{
				percent = 65f;
			}
			if (percent <= 0f)
			{
				return -1f;
			}
			return Math.Min(100f, percent) / 100f;
		}

		public static float BreakThreshold(bool breakOnFailure)
		{
			if (!breakOnFailure)
			{
				return -1f;
			}
			return 1f;
		}

		public static int FailureQuality(int targetQuality, bool reduceLevel, int levelsLost = 1)
		{
			return Math.Max(1, targetQuality - 1 - (reduceLevel ? Math.Max(1, Math.Min(10, levelsLost)) : 0));
		}
	}
}