Decompiled source of MoreMonsterCredits v1.1.0

plugins/MoreMonsterCredits/MoreMonsterCredits.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
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 LocalTweaks;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[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("MoreMonsterCredits")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+1bf901674ad3666c35166e5369bf7c177afbdfa2")]
[assembly: AssemblyProduct("MoreMonsterCredits")]
[assembly: AssemblyTitle("MoreMonsterCredits")]
[assembly: AssemblyVersion("1.1.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 MoreMonsterCredits
{
	[BepInPlugin("com.youssef.MoreMonsterCredits", "More Monster Credits", "1.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.youssef.MoreMonsterCredits";

		public const string Name = "More Monster Credits";

		private static readonly ConfigEntry<int>[] bonuses = new ConfigEntry<int>[8];

		private static readonly ConfigEntry<float>[] monsterCounts = new ConfigEntry<float>[8];

		private static FieldInfo singleBossSpawn;

		private readonly Harmony harmony = new Harmony("com.youssef.MoreMonsterCredits");

		private void Awake()
		{
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Expected O, but got Unknown
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Expected O, but got Unknown
			//IL_01d6: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Set separate monster budgets and monster-count multipliers for stages 3 through 10.", "com.youssef.MoreMonsterCredits", "More Monster Credits");
			Sprite val = SettingsIcon.Load("MoreMonsterCredits.SettingsIcon.png");
			if (Object.op_Implicit((Object)(object)val))
			{
				ModSettingsManager.SetModIcon(val, "com.youssef.MoreMonsterCredits", "More Monster Credits");
			}
			for (int i = 3; i <= 10; i++)
			{
				bonuses[i - 3] = TweakSettings.Slider(((BaseUnityPlugin)this).Config, "Monster credits", $"Stage {i} bonus percent", 0, 0, 200, "Extra monster budget: 0 leaves it alone, 100 doubles it, 200 triples it. Ongoing income changes immediately; starting spawns change on the next stage entry. Hidden realms do not count.", "com.youssef.MoreMonsterCredits", "More Monster Credits");
				monsterCounts[i - 3] = TweakSettings.StepSlider(((BaseUnityPlugin)this).Config, "Monster count", $"Stage {i} multiplier", 1f, 1f, 3f, 0.5f, "Makes the director spend less credit per successful monster spawn, producing roughly this many monsters from the same budget. Does not affect chests or other interactables.", "com.youssef.MoreMonsterCredits", "More Monster Credits");
			}
			try
			{
				harmony.Patch((MethodBase)AccessTools.Method(typeof(CombatDirector), "FixedUpdate", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(Plugin), "ChangeIncome", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null);
				harmony.Patch((MethodBase)AccessTools.Method(typeof(SceneDirector), "PopulateScene", (Type[])null, (Type[])null), new HarmonyMethod(typeof(Plugin), "ChangeStartingCredits", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				MethodInfo methodInfo = AccessTools.Method(typeof(CombatDirector), "AttemptSpawnOnTarget", (Type[])null, (Type[])null);
				singleBossSpawn = AccessTools.Field(typeof(CombatDirector), "_bossOverrideSpawnSingleBoss");
				if (methodInfo == null || singleBossSpawn == null)
				{
					throw new MissingMemberException("CombatDirector's spawn accounting no longer matches.");
				}
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "RememberCredits", (Type[])null), new HarmonyMethod(typeof(Plugin), "RefundSpawnCost", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Monster credit and count tweaks loaded.");
			}
			catch (Exception arg)
			{
				harmony.UnpatchSelf();
				((BaseUnityPlugin)this).Logger.LogError((object)$"Monster credit tweaks were not applied.\n{arg}");
			}
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}

		private static int StageIndex()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			Run instance = Run.instance;
			SceneDef mostRecentSceneDef = SceneCatalog.mostRecentSceneDef;
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)mostRecentSceneDef) || (int)mostRecentSceneDef.sceneType != 1 || mostRecentSceneDef.isFinalStage || !mostRecentSceneDef.validForRandomSelection)
			{
				return -1;
			}
			int num = instance.stageClearCount - 2;
			if (num < 0 || num >= bonuses.Length)
			{
				return -1;
			}
			return num;
		}

		private static float CreditMultiplier()
		{
			int num = StageIndex();
			if (num < 0)
			{
				return 1f;
			}
			return 1f + (float)bonuses[num].Value / 100f;
		}

		private static float MonsterMultiplier()
		{
			int num = StageIndex();
			if (num < 0)
			{
				return 1f;
			}
			return monsterCounts[num].Value;
		}

		private static void ChangeStartingCredits(ref int ___monsterCredit)
		{
			___monsterCredit = (int)Math.Min(2147483647.0, Math.Round((double)___monsterCredit * (double)CreditMultiplier()));
		}

		private static float ScaleIncome(float credits, CombatDirector director)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)director.teamIndex != 2)
			{
				return credits;
			}
			return credits * CreditMultiplier();
		}

		private static void RememberCredits(CombatDirector __instance, out float __state)
		{
			__state = __instance.monsterCredit;
		}

		private static void RefundSpawnCost(CombatDirector __instance, bool __result, float __state)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			float num = MonsterMultiplier();
			if (__result && !(num <= 1f) && (int)__instance.teamIndex != 1 && !(bool)singleBossSpawn.GetValue(__instance))
			{
				float num2 = __state - __instance.monsterCredit;
				if (num2 > 0f)
				{
					__instance.monsterCredit += num2 * (1f - 1f / num);
				}
			}
		}

		private static IEnumerable<CodeInstruction> ChangeIncome(IEnumerable<CodeInstruction> instructions)
		{
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Expected O, but got Unknown
			List<CodeInstruction> list = instructions.ToList();
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].operand is MethodInfo methodInfo && !(methodInfo.Name != "Update") && !(methodInfo.DeclaringType?.Name != "DirectorMoneyWave") && !(methodInfo.ReturnType != typeof(float)))
				{
					list.InsertRange(i + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
					{
						new CodeInstruction(OpCodes.Ldarg_0, (object)null),
						new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Plugin), "ScaleIncome", (Type[])null, (Type[])null))
					});
					i += 2;
					num++;
				}
			}
			if (num != 1)
			{
				throw new InvalidOperationException($"Expected one director income update, found {num}.");
			}
			return list;
		}
	}
	internal static class SettingsIcon
	{
		internal static Sprite Load(string resourceName)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num == 0)
				{
					throw new EndOfStreamException(resourceName);
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				return null;
			}
			((Object)val).name = "MoreMonsterCredits settings icon";
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
	}
}
namespace LocalTweaks
{
	internal static class PatchTools
	{
		internal static MethodInfo Method(string type, string name)
		{
			Type type2 = AccessTools.TypeByName(type);
			if (!(type2 == null))
			{
				return AccessTools.DeclaredMethod(type2, name, (Type[])null, (Type[])null) ?? throw new MissingMethodException(type, name);
			}
			throw new TypeLoadException(type);
		}

		internal static IEnumerable<CodeInstruction> ReplaceFloat(IEnumerable<CodeInstruction> source, float value, MethodInfo replacement)
		{
			List<CodeInstruction> list = source.ToList();
			List<CodeInstruction> list2 = list.Where((CodeInstruction x) => x.opcode == OpCodes.Ldc_R4 && x.operand is float num && Math.Abs(num - value) < 1E-06f).ToList();
			if (list2.Count != 1)
			{
				throw new InvalidOperationException($"Expected one {value} constant, found {list2.Count}.");
			}
			list2[0].opcode = OpCodes.Call;
			list2[0].operand = replacement;
			return list;
		}
	}
	internal static class TweakSettings
	{
		internal static ConfigEntry<int> Slider(ConfigFile file, string section, string name, int value, int min, int max, string description, string guid, string modName)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			ConfigEntry<int> obj = file.Bind<int>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(min, max), Array.Empty<object>()));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(obj, new IntSliderConfig
			{
				min = min,
				max = max
			}), guid, modName);
			return obj;
		}

		internal static ConfigEntry<bool> Checkbox(ConfigFile file, string section, string name, bool value, string description, string guid, string modName)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			ConfigEntry<bool> obj = file.Bind<bool>(section, name, value, description);
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(obj), guid, modName);
			return obj;
		}

		internal static ConfigEntry<float> StepSlider(ConfigFile file, string section, string name, float value, float min, float max, float increment, string description, string guid, string modName)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0041: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			ConfigEntry<float> obj = file.Bind<float>(section, name, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(obj, new StepSliderConfig
			{
				min = min,
				max = max,
				increment = increment
			}), guid, modName);
			return obj;
		}
	}
}