Decompiled source of Multiplier v1.0.0

plugins/Multiplier.dll

Decompiled 2 hours 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 System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LootClicker;
using LootClicker.Entities.Monsters;
using LootClicker.Items;
using LootClicker.Maps;
using LootClicker.Professions;
using LootClicker.Services;
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("Multiplier")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0640f1ef899280163b0db8182202a4b4f9061b82")]
[assembly: AssemblyProduct("Multiplier")]
[assembly: AssemblyTitle("Multiplier")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 LootunMultiplier
{
	[BepInPlugin("nemonline.lootun.multiplier", "Multiplier", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		internal static ManualLogSource Logger;

		internal static Harmony Harmony;

		internal static ConfigEntry<float> ScrapMultiplier;

		internal static ConfigEntry<float> HarvestMultiplier;

		internal static ConfigEntry<bool> FixDoubleResources;

		internal static ConfigEntry<float> MissionMaterialMultiplier;

		internal static ConfigEntry<bool> MultiplyMissionPreviews;

		internal static ConfigEntry<bool> LogRewards;

		private void Awake()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Expected O, but got Unknown
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			AcceptableValueRange<float> val = new AcceptableValueRange<float>(0f, 100f);
			ScrapMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Scrap", "ScrapMultiplier", 2f, new ConfigDescription("Multiplies every material you get from scrapping (manual, auto-scrap, scrapped rewards). Stacks with the Community passive Double Scrap: a successful double roll gives 2x on top. Fractions are rounded randomly so the average is exact (1.5 on 1 core = 1 or 2, 50/50).", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			HarvestMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Professions", "HarvestMultiplier", 2f, new ConfigDescription("Multiplies the materials gathered by every profession, online and offline harvests alike (normal, rare and soul materials). Stacks with Double Resource Chance (tools) and the Community passive Double Resources. Gold from harvesting is not changed.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			FixDoubleResources = ((BaseUnityPlugin)this).Config.Bind<bool>("Professions", "EnableCommunityDoubleResources", true, "Vanilla bug: the Community passive Double Resources is computed but never used, so it does nothing. true = its chance is added to every worker's double-harvest roll (same as a tool's Double Resource Chance). false = vanilla behaviour.");
			MissionMaterialMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Missions", "MaterialRewardMultiplier", 2f, new ConfigDescription("Multiplies material rewards of all mission types: campaign boss materials, bounty rewards, Agony, faction dungeons, Faction Frenzy, raids, boss chests and mission-difficulty boss bonuses. Applied to the final amounts, so Infamy, bounty passives, infusion and faction bonuses all still count. Items, XP, gold, Fame/Favour and regular monster drops are unchanged.", (AcceptableValueBase)(object)val, Array.Empty<object>()));
			MultiplyMissionPreviews = ((BaseUnityPlugin)this).Config.Bind<bool>("Missions", "ShowMultipliedPreviews", true, "Show the multiplied amounts in the bounty, faction dungeon, Faction Frenzy and raid reward previews.");
			LogRewards = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogRewards", false, "Write every multiplied reward to BepInEx/LogOutput.log (source, material, before -> after). For checking that a multiplier works; leave off for normal play.");
			Harmony = new Harmony("nemonline.lootun.multiplier");
			Harmony.CreateClassProcessor(typeof(Locale_SetupLocale_Hook)).Patch();
			Logger.LogInfo((object)(string.Format("{0} loaded: scrap x{1}, harvest x{2}, ", "Multiplier", ScrapMultiplier.Value, HarvestMultiplier.Value) + $"mission materials x{MissionMaterialMultiplier.Value}"));
		}

		internal static void ApplyPatches()
		{
			int num = 0;
			int num2 = 0;
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(typeof(Plugin).Assembly);
			foreach (Type type in typesFromAssembly)
			{
				if (!(type == typeof(Locale_SetupLocale_Hook)) && type.GetCustomAttributes(typeof(HarmonyPatch), inherit: false).Any())
				{
					try
					{
						Harmony.CreateClassProcessor(type).Patch();
						num++;
					}
					catch (Exception arg)
					{
						num2++;
						Logger.LogError((object)$"Patch {type.Name} failed: {arg}");
					}
				}
			}
			Logger.LogInfo((object)$"Patching done: {num} patch classes applied, {num2} failed");
		}
	}
	[HarmonyPatch(typeof(Locale), "SetupLocale")]
	internal static class Locale_SetupLocale_Hook
	{
		private static bool done;

		private static void Postfix()
		{
			if (!done)
			{
				done = true;
				Plugin.ApplyPatches();
			}
		}
	}
	internal static class RewardLog
	{
		[ThreadStatic]
		public static string Source;

		public static bool On => Plugin.LogRewards.Value;

		public static void Write(string source, IEnumerable<(MaterialID ID, int Before, int After)> entries)
		{
			List<string> list = (from e in entries
				where e.Before > 0 || e.After > 0
				select $"{e.ID} {e.Before} -> {e.After}").ToList();
			if (list.Count > 0)
			{
				Plugin.Logger.LogInfo((object)((source ?? "?") + ": " + string.Join(", ", list)));
			}
		}

		public static void Write(string source, MaterialID id, int before, int after)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Write(source, new(MaterialID, int, int)[1] { (id, before, after) });
		}
	}
	internal static class Mult
	{
		private static readonly Random Rng = new Random();

		public static int Apply(int count, float mult)
		{
			if (count <= 0 || mult == 1f)
			{
				return count;
			}
			double num = (double)count * (double)Math.Max(0f, mult);
			double num2 = Math.Floor(num);
			if (num - num2 > 0.0 && Rng.NextDouble() < num - num2)
			{
				num2 += 1.0;
			}
			if (!(num2 >= 2147483647.0))
			{
				return (int)num2;
			}
			return int.MaxValue;
		}

		public static int Preview(int count, float mult)
		{
			if (count <= 0 || mult == 1f)
			{
				return count;
			}
			double num = Math.Round((double)count * (double)Math.Max(0f, mult), MidpointRounding.AwayFromZero);
			if (!(num >= 2147483647.0))
			{
				return (int)num;
			}
			return int.MaxValue;
		}

		public static List<CodeInstruction> RedirectCalls(IEnumerable<CodeInstruction> instructions, Type declaring, string name, Type wrappers, out int hits)
		{
			List<CodeInstruction> list = instructions.ToList();
			hits = 0;
			foreach (CodeInstruction item in list)
			{
				if ((item.opcode != OpCodes.Callvirt && item.opcode != OpCodes.Call) || !(item.operand is MethodInfo methodInfo) || methodInfo.DeclaringType != declaring || methodInfo.Name != name || methodInfo.IsStatic)
				{
					continue;
				}
				Type[] array = new Type[1] { declaring }.Concat(from p in methodInfo.GetParameters()
					select p.ParameterType).ToArray();
				MethodInfo methodInfo2 = AccessTools.Method(wrappers, name, array, (Type[])null);
				if (methodInfo2 == null)
				{
					Plugin.Logger.LogWarning((object)("No wrapper " + wrappers.Name + "." + name + "(" + string.Join(", ", array.Select((Type a) => a.Name)) + ")"));
				}
				else
				{
					item.opcode = OpCodes.Call;
					item.operand = methodInfo2;
					hits++;
				}
			}
			return list;
		}

		public static void LogHits(string where, int hits, int expected)
		{
			if (hits == expected)
			{
				Plugin.Logger.LogInfo((object)$"{where}: {hits} call(s) hooked");
			}
			else
			{
				Plugin.Logger.LogWarning((object)$"{where}: expected {expected} call(s), hooked {hits} (game update?)");
			}
		}
	}
	internal static class Scrap
	{
		private sealed class Done
		{
			public int Count;
		}

		private static readonly ConditionalWeakTable<List<(MaterialID ID, int Count)>, Done> Multiplied = new ConditionalWeakTable<List<(MaterialID, int)>, Done>();

		public static void MultiplyNew(List<(MaterialID ID, int Count)> list)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if (list == null)
			{
				return;
			}
			Done value = Multiplied.GetValue(list, (List<(MaterialID ID, int Count)> _) => new Done());
			float value2 = Plugin.ScrapMultiplier.Value;
			List<(MaterialID, int, int)> list2 = (RewardLog.On ? new List<(MaterialID, int, int)>() : null);
			if (value2 != 1f)
			{
				for (int num = value.Count; num < list.Count; num++)
				{
					(MaterialID, int) value3 = list[num];
					int item = value3.Item2;
					value3.Item2 = Mult.Apply(value3.Item2, value2);
					list[num] = value3;
					list2?.Add((value3.Item1, item, value3.Item2));
				}
			}
			value.Count = Math.Max(value.Count, list.Count);
			if (list2 != null)
			{
				RewardLog.Write("Scrap", list2);
			}
		}

		public static void AddMaterial(MaterialInventory inv, List<(MaterialID ID, int Count)> list)
		{
			MultiplyNew(list);
			inv.AddMaterial(list);
		}
	}
	[HarmonyPatch(typeof(MaterialInventory), "ApplyDoubleScrap")]
	internal static class Scrap_ApplyDoubleScrap
	{
		private static void Postfix(List<(MaterialID ID, int Count)> __result)
		{
			Scrap.MultiplyNew(__result);
		}
	}
	[HarmonyPatch(typeof(MaterialInventory), "GetScrap", new Type[]
	{
		typeof(ToolID),
		typeof(Rarity),
		typeof(int)
	})]
	internal static class Scrap_GetScrapTool
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.Method(typeof(MaterialInventory), "AddMaterial", new Type[1] { typeof(List<(MaterialID, int)>) }, (Type[])null);
			MethodInfo operand = AccessTools.Method(typeof(Scrap), "AddMaterial", (Type[])null, (Type[])null);
			int num = 0;
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.Calls(item, methodInfo))
				{
					item.opcode = OpCodes.Call;
					item.operand = operand;
					num++;
				}
			}
			Mult.LogHits("MaterialInventory.GetScrap(Tool)", num, 1);
			return list;
		}
	}
	internal static class Harvest
	{
		private static readonly Dictionary<MaterialID, (int Before, int After)> Pending = new Dictionary<MaterialID, (int, int)>();

		public static void Track(MaterialID id, int before, int after)
		{
			//IL_0005: 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)
			Pending.TryGetValue(id, out (int, int) value);
			Pending[id] = (value.Item1 + before, value.Item2 + after);
		}

		public static void Flush(string label)
		{
			if (Pending.Count != 0)
			{
				RewardLog.Write(label, Pending.Select((KeyValuePair<MaterialID, (int Before, int After)> kv) => (Key: kv.Key, Before: kv.Value.Before, After: kv.Value.After)).ToList());
				Pending.Clear();
			}
		}

		public static int DoubleChance(Profession p)
		{
			return p.DoubleChance + (Plugin.FixDoubleResources.Value ? Math.Max(0, DonationPassives.DoubleGathering) : 0);
		}
	}
	[HarmonyPatch(typeof(Profession), "Harvest")]
	internal static class Profession_Harvest
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(Profession), "DoubleChance");
			MethodInfo operand = AccessTools.Method(typeof(Harvest), "DoubleChance", (Type[])null, (Type[])null);
			int num = 0;
			foreach (CodeInstruction item in list)
			{
				if (CodeInstructionExtensions.Calls(item, methodInfo))
				{
					item.opcode = OpCodes.Call;
					item.operand = operand;
					num++;
				}
			}
			Mult.LogHits("Profession.Harvest (Community Double Resources)", num, 2);
			return list;
		}

		private static void Prefix(ref Dictionary<MaterialID, int> materials, out Dictionary<MaterialID, int> __state)
		{
			__state = ((Plugin.HarvestMultiplier.Value == 1f || materials == null) ? null : new Dictionary<MaterialID, int>(materials));
		}

		private static void Postfix(ref Dictionary<MaterialID, int> materials, Dictionary<MaterialID, int> __state)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			if (__state == null || materials == null)
			{
				return;
			}
			float value = Plugin.HarvestMultiplier.Value;
			foreach (MaterialID item in materials.Keys.ToList())
			{
				__state.TryGetValue(item, out var value2);
				int num = materials[item] - value2;
				if (num > 0)
				{
					int num2 = Mult.Apply(num, value);
					long num3 = (long)value2 + (long)num2;
					materials[item] = (int)((num3 >= int.MaxValue) ? int.MaxValue : num3);
					if (RewardLog.On)
					{
						Harvest.Track(item, num, num2);
					}
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class Professions_HarvestLog
	{
		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in AccessTools.GetDeclaredMethods(typeof(Professions))
				where m.Name == "HarvestProfessions"
				select m;
		}

		private static void Postfix(MethodBase __originalMethod)
		{
			Harvest.Flush((__originalMethod.GetParameters().Length == 0) ? "Harvest" : "Harvest (offline)");
		}
	}
	internal static class MissionRewards
	{
		private static float M => Plugin.MissionMaterialMultiplier.Value;

		private static int Scale(MaterialID id, int count, List<(MaterialID, int, int)> log)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			int num = Mult.Apply(count, M);
			log?.Add((id, count, num));
			return num;
		}

		private static List<(MaterialID, int, int)> NewLog()
		{
			if (!RewardLog.On)
			{
				return null;
			}
			return new List<(MaterialID, int, int)>();
		}

		private static void Flush(List<(MaterialID, int, int)> log)
		{
			if (log != null)
			{
				RewardLog.Write(RewardLog.Source, log);
			}
		}

		public static void AddMaterial(MaterialInventory inv, MaterialID id, int count)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			List<(MaterialID, int, int)> log = NewLog();
			inv.AddMaterial(id, Scale(id, count, log));
			Flush(log);
		}

		public static void AddMaterial(MaterialInventory inv, (MaterialID ID, int Count) material, bool updateCount)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			AddMaterial(inv, material.ID, material.Count);
		}

		public static void AddMaterial(MaterialInventory inv, (MaterialID ID, int Count)[] materials)
		{
			//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)
			if (materials != null)
			{
				List<(MaterialID, int, int)> log = NewLog();
				for (int i = 0; i < materials.Length; i++)
				{
					(MaterialID, int) tuple = materials[i];
					inv.AddMaterial(tuple.Item1, Scale(tuple.Item1, tuple.Item2, log));
				}
				Flush(log);
			}
		}

		public static void AddMaterial(MaterialInventory inv, List<(MaterialID ID, int Count)> materials)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			if (materials == null)
			{
				return;
			}
			List<(MaterialID, int, int)> log = NewLog();
			foreach (var material in materials)
			{
				inv.AddMaterial(material.ID, Scale(material.ID, material.Count, log));
			}
			Flush(log);
		}

		public static void AddMaterial(MaterialInventory inv, Dictionary<MaterialID, int> materials)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (materials == null)
			{
				return;
			}
			List<(MaterialID, int, int)> log = NewLog();
			foreach (KeyValuePair<MaterialID, int> material in materials)
			{
				inv.AddMaterial(material.Key, Scale(material.Key, material.Value, log));
			}
			Flush(log);
		}

		public static void AddMaterial(MaterialInventory inv, List<CraftingMaterial> materials)
		{
			//IL_0020: 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 (materials == null)
			{
				return;
			}
			List<(MaterialID, int, int)> log = NewLog();
			foreach (CraftingMaterial material in materials)
			{
				if (material != null)
				{
					inv.AddMaterial(material.ID, Scale(material.ID, ((StackableItem)material).StackCount, log));
				}
			}
			Flush(log);
		}
	}
	[HarmonyPatch]
	internal static class Missions_MaterialRewards
	{
		private static readonly (Type Type, string Method, int Expected)[] Targets = new(Type, string, int)[8]
		{
			(typeof(Bounty), "ClaimReward", 5),
			(typeof(AgonyMission), "ClearStage", 5),
			(typeof(FactionFrenzy), "ClearStage", 5),
			(typeof(Raid), "ClearStage", 4),
			(typeof(EndlessMap), "ClearStage", 1),
			(typeof(BossChest), "OpenChest", 8),
			(typeof(Monster), "DropBossLoot", 3),
			(typeof(MapPassiveGroup), "ApplyDifficultyDropBonus", 8)
		};

		private static MethodBase Find(Type type, string method)
		{
			if (!(type == typeof(BossChest)))
			{
				return AccessTools.DeclaredMethod(type, method, (Type[])null, (Type[])null);
			}
			return AccessTools.GetDeclaredMethods(type).FirstOrDefault((MethodInfo m) => m.Name == method && m.IsStatic);
		}

		private static IEnumerable<MethodBase> TargetMethods()
		{
			(Type Type, string Method, int Expected)[] targets = Targets;
			for (int i = 0; i < targets.Length; i++)
			{
				(Type, string, int) tuple = targets[i];
				MethodBase methodBase = Find(tuple.Item1, tuple.Item2);
				if (methodBase == null)
				{
					Plugin.Logger.LogWarning((object)("Missions: " + tuple.Item1.Name + "." + tuple.Item2 + " not found (game update?)"));
				}
				else
				{
					yield return methodBase;
				}
			}
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			int hits;
			List<CodeInstruction> result = Mult.RedirectCalls(instructions, typeof(MaterialInventory), "AddMaterial", typeof(MissionRewards), out hits);
			(Type, string, int) tuple = Targets.First(((Type Type, string Method, int Expected) x) => x.Type == original.DeclaringType && x.Method == original.Name);
			Mult.LogHits("Missions: " + tuple.Item1.Name + "." + tuple.Item2, hits, tuple.Item3);
			return result;
		}

		private static void Prefix(MethodBase __originalMethod, out string __state)
		{
			__state = RewardLog.Source;
			RewardLog.Source = __originalMethod.DeclaringType?.Name + "." + __originalMethod.Name;
		}

		private static void Finalizer(string __state)
		{
			RewardLog.Source = __state;
		}
	}
	internal static class Previews
	{
		public static void LoadMaterial(MaterialPreviewSlotController slot, MaterialID id, int amount)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			slot.LoadMaterial(id, Plugin.MultiplyMissionPreviews.Value ? Mult.Preview(amount, Plugin.MissionMaterialMultiplier.Value) : amount);
		}
	}
	[HarmonyPatch]
	internal static class Missions_RewardPreviews
	{
		private static readonly (Type Type, string Method, int Expected)[] Targets = new(Type, string, int)[6]
		{
			(typeof(BountyMenuController), "LoadMission", 1),
			(typeof(BountyMenuController), "LoadRandomMission", 5),
			(typeof(BountyMenuController), "LoadRandomMythicMission", 6),
			(typeof(FactionMenuController), "LoadFactionDungeon", 1),
			(typeof(FactionMenuController), "LoadMythicFactionFrenzy", 1),
			(typeof(RaidMenuController), "LoadRaid", 1)
		};

		private static IEnumerable<MethodBase> TargetMethods()
		{
			return from m in ((IEnumerable<(Type, string, int)>)Targets).Select((Func<(Type, string, int), MethodBase>)(((Type Type, string Method, int Expected) t) => AccessTools.DeclaredMethod(t.Type, t.Method, (Type[])null, (Type[])null)))
				where m != null
				select m;
		}

		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original)
		{
			int hits;
			List<CodeInstruction> result = Mult.RedirectCalls(instructions, typeof(MaterialPreviewSlotController), "LoadMaterial", typeof(Previews), out hits);
			(Type, string, int) tuple = Targets.First(((Type Type, string Method, int Expected) x) => x.Type == original.DeclaringType && x.Method == original.Name);
			Mult.LogHits("Preview: " + tuple.Item1.Name + "." + tuple.Item2, hits, tuple.Item3);
			return result;
		}
	}
	internal static class AgonyPreview
	{
		private static int P(int amount)
		{
			if (!Plugin.MultiplyMissionPreviews.Value)
			{
				return amount;
			}
			return Mult.Preview(amount, Plugin.MissionMaterialMultiplier.Value);
		}

		public static int GetUpgradeKitAmount(int agonyLevel)
		{
			return P(AgonyMissions.GetUpgradeKitAmount(agonyLevel));
		}

		public static int GetPristineMaterialAmount(int agonyLevel, bool applyPartial)
		{
			return P(AgonyMissions.GetPristineMaterialAmount(agonyLevel, applyPartial));
		}
	}
	[HarmonyPatch(typeof(AgonyMissions), "GetRewardsText")]
	internal static class Agony_RewardsText
	{
		private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
		{
			List<CodeInstruction> list = instructions.ToList();
			int num = 0;
			foreach (CodeInstruction item in list)
			{
				if (!(item.opcode != OpCodes.Call) && item.operand is MethodInfo methodInfo && !(methodInfo.DeclaringType != typeof(AgonyMissions)) && (!(methodInfo.Name != "GetUpgradeKitAmount") || !(methodInfo.Name != "GetPristineMaterialAmount")))
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(AgonyPreview), methodInfo.Name, (from p in methodInfo.GetParameters()
						select p.ParameterType).ToArray(), (Type[])null);
					if (!(methodInfo2 == null))
					{
						item.operand = methodInfo2;
						num++;
					}
				}
			}
			Mult.LogHits("Preview: AgonyMissions.GetRewardsText", num, 2);
			return list;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "nemonline.lootun.multiplier";

		public const string PLUGIN_NAME = "Multiplier";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}