Decompiled source of MonsoonPlus v1.0.20

plugins/MonsoonPlus.dll

Decompiled 6 hours ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RoR2;
using UnityEngine;

[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("MonsoonPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MonsoonPlus")]
[assembly: AssemblyTitle("MonsoonPlus")]
[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 MonsoonPlus
{
	[BepInPlugin("com.monsoonplus", "MonsoonPlus", "1.0.20")]
	public class MonsoonPlusPlugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(RuleDef), "FromDifficulty")]
		private static class RuleDefFromDifficultyPatch
		{
			private static void Postfix(RuleDef __result)
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: 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_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				if (!EnableMod || __result == null)
				{
					return;
				}
				try
				{
					RuleChoiceDef val = __result.AddChoice("MonsoonPlus", (object)DifficultyIndex, false);
					if (val != null)
					{
						val.difficultyIndex = (DifficultyIndex)2;
						val.extraData = DifficultyIndex;
						val.tooltipNameToken = "MONSOON_PLUS_NAME";
						val.tooltipBodyToken = "MONSOON_PLUS_DESCRIPTION";
						val.tooltipNameColor = new Color(0.85f, 0.2f, 1f, 1f);
						val.tooltipBodyColor = Color.white;
						if ((Object)(object)CachedDifficultyIcon != (Object)null)
						{
							val.sprite = CachedDifficultyIcon;
						}
						val.availableInSinglePlayer = true;
						val.availableInMultiPlayer = true;
						val.onlyShowInGameBrowserIfNonDefault = false;
						val.serverTag = "MonsoonPlus";
					}
				}
				catch (Exception ex)
				{
					if (Log != null)
					{
						Log.LogError((object)ex);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Run), "BeginStage")]
		private static class RunBeginStagePatch
		{
			private static void Postfix(Run __instance)
			{
				if (EnableMod && IsMonsoonPlusRun(__instance))
				{
					if (RunAmbientLevelCapField != null)
					{
						RunAmbientLevelCapField.SetValue(null, EnemyLevelCap);
					}
					ApplyHardDifficultyIcon(enable: true);
				}
			}
		}

		[HarmonyPatch(typeof(Run), "OnDestroy")]
		private static class RunOnDestroyPatch
		{
			private static void Postfix(Run __instance)
			{
				if (EnableMod && IsMonsoonPlusRun(__instance))
				{
					ApplyHardDifficultyIcon(enable: false);
				}
			}
		}

		[HarmonyPatch(typeof(DeathRewards), "get_goldReward")]
		private static class DeathRewardsGoldRewardPatch
		{
			private static void Postfix(ref uint __result)
			{
				if (!EnableMod || !EnableGoldCleanup)
				{
					return;
				}
				Run instance = Run.instance;
				if ((Object)(object)instance == (Object)null || !IsMonsoonPlusRun(instance))
				{
					return;
				}
				int num = instance.stageClearCount + 1;
				if (num >= 4)
				{
					float num2 = GoldMultiplierForStage(num);
					if (!Mathf.Approximately(num2, 1f))
					{
						__result = (uint)Mathf.RoundToInt((float)__result * num2);
					}
				}
			}
		}

		public const string PluginGUID = "com.monsoonplus";

		public const string PluginName = "MonsoonPlus";

		public const string PluginVersion = "1.0.20";

		internal static ManualLogSource Log;

		public static DifficultyDef Difficulty;

		public static DifficultyIndex DifficultyIndex;

		public static bool EnableMod = true;

		public static bool EnableGoldCleanup = true;

		public static float ScalingValue = 3.45f;

		public static int EnemyLevelCap = 125;

		public static float GoldStage4Multiplier = 0.55f;

		public static float GoldRampStep = 0.1f;

		public static float GoldMinMultiplier = 0.25f;

		public static Sprite CachedDifficultyIcon;

		private static Sprite OriginalHardDifficultyIcon;

		private static bool HardDifficultyIconOverridden;

		private static readonly FieldInfo DifficultyIconSpriteField = typeof(DifficultyDef).GetField("iconSprite", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo DifficultyFoundIconSpriteField = typeof(DifficultyDef).GetField("foundIconSprite", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly FieldInfo RunAmbientLevelCapField = typeof(Run).GetField("ambientLevelCap", BindingFlags.Static | BindingFlags.NonPublic);

		private static RuleDef DifficultyRuleDefCache;

		private readonly Harmony _harmony = new Harmony("com.monsoonplus");

		private static bool IsMonsoonPlusRun(Run run)
		{
			if ((Object)(object)run == (Object)null || !EnableMod)
			{
				return false;
			}
			if (DifficultyRuleDefCache == null)
			{
				DifficultyRuleDefCache = RuleCatalog.FindRuleDef("Difficulty");
			}
			if (DifficultyRuleDefCache == null)
			{
				try
				{
					DifficultyRuleDefCache = RuleDef.FromDifficulty();
				}
				catch
				{
					DifficultyRuleDefCache = null;
				}
			}
			if (DifficultyRuleDefCache == null || run.ruleBook == null)
			{
				return false;
			}
			try
			{
				RuleChoiceDef ruleChoice = run.ruleBook.GetRuleChoice(DifficultyRuleDefCache);
				return ruleChoice != null && string.Equals(ruleChoice.localName, "MonsoonPlus", StringComparison.Ordinal);
			}
			catch
			{
				return false;
			}
		}

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			if (EnableMod)
			{
				RegisterDifficulty();
			}
			_harmony.PatchAll();
			Log.LogInfo((object)"MonsoonPlus loaded");
		}

		private static void RegisterDifficulty()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			Difficulty = new DifficultyDef(ScalingValue, "MONSOON_PLUS_DESCRIPTION", "MONSOON_PLUS_NAME", "Textures/DifficultyIcons/texDifficultyHardIcon", new Color(0.85f, 0.2f, 1f, 1f), "MonsoonPlus", true);
			CachedDifficultyIcon = CreatePurpleGradientIcon();
			ExportGeneratedIcon(CachedDifficultyIcon);
			if ((Object)(object)CachedDifficultyIcon != (Object)null && DifficultyIconSpriteField != null)
			{
				DifficultyIconSpriteField.SetValue(Difficulty, CachedDifficultyIcon);
				DifficultyFoundIconSpriteField?.SetValue(Difficulty, true);
			}
			FieldInfo? field = typeof(DifficultyCatalog).GetField("difficultyDefs", BindingFlags.Static | BindingFlags.NonPublic);
			typeof(DifficultyCatalog).GetField("standardDifficultyCount", BindingFlags.Static | BindingFlags.NonPublic);
			DifficultyDef[] array = ((DifficultyDef[])field.GetValue(null)) ?? Array.Empty<DifficultyDef>();
			int num = array.Length;
			DifficultyDef[] array2 = (DifficultyDef[])(object)new DifficultyDef[array.Length + 1];
			Array.Copy(array, array2, array.Length);
			array2[num] = Difficulty;
			field.SetValue(null, array2);
			DifficultyIndex = (DifficultyIndex)num;
			RegisterLanguageTokens();
			Language.onCurrentLanguageChanged += RegisterLanguageTokens;
		}

		private static void ApplyHardDifficultyIcon(bool enable)
		{
			try
			{
				DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef((DifficultyIndex)2);
				if (difficultyDef == null || DifficultyIconSpriteField == null)
				{
					return;
				}
				if (enable)
				{
					if (!HardDifficultyIconOverridden)
					{
						object? value = DifficultyIconSpriteField.GetValue(difficultyDef);
						OriginalHardDifficultyIcon = (Sprite)((value is Sprite) ? value : null);
						HardDifficultyIconOverridden = true;
					}
					if ((Object)(object)CachedDifficultyIcon != (Object)null)
					{
						DifficultyIconSpriteField.SetValue(difficultyDef, CachedDifficultyIcon);
						DifficultyFoundIconSpriteField?.SetValue(difficultyDef, true);
					}
				}
				else if (HardDifficultyIconOverridden)
				{
					DifficultyIconSpriteField.SetValue(difficultyDef, OriginalHardDifficultyIcon);
					DifficultyFoundIconSpriteField?.SetValue(difficultyDef, (Object)(object)OriginalHardDifficultyIcon != (Object)null);
					HardDifficultyIconOverridden = false;
				}
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogError((object)("Monsoon+ difficulty icon override failed: " + ex));
				}
			}
		}

		private static Sprite CreatePurpleGradientIcon()
		{
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Sprite val = Resources.Load<Sprite>("Textures/DifficultyIcons/texDifficultyHardIcon");
				if ((Object)(object)val == (Object)null || (Object)(object)val.texture == (Object)null)
				{
					return null;
				}
				Texture2D texture = val.texture;
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)texture).width, ((Texture)texture).height, 0, (RenderTextureFormat)0);
				Graphics.Blit((Texture)(object)texture, temporary);
				RenderTexture.active = temporary;
				Texture2D val2 = new Texture2D(((Texture)texture).width, ((Texture)texture).height, (TextureFormat)4, false);
				val2.ReadPixels(new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), 0, 0);
				val2.Apply();
				RenderTexture.active = null;
				RenderTexture.ReleaseTemporary(temporary);
				Color32[] pixels = val2.GetPixels32();
				int width = ((Texture)val2).width;
				int height = ((Texture)val2).height;
				Color val5 = default(Color);
				Color val6 = default(Color);
				for (int i = 0; i < height; i++)
				{
					for (int j = 0; j < width; j++)
					{
						int num = i * width + j;
						Color32 val3 = pixels[num];
						if (val3.a != 0)
						{
							float num2 = ((float)j * 1.35f + (float)i * 0.65f) / ((float)width * 1.35f + (float)height * 0.65f);
							float num3 = Mathf.Repeat(num2 * 1.15f + 0.08f, 1f);
							float num4 = 0.92f + 0.08f * Mathf.Sin(num2 * MathF.PI * 6f);
							float num5 = 0.95f + 0.05f * Mathf.Cos(num2 * MathF.PI * 4f);
							Color val4 = Color.HSVToRGB(num3, num4, num5);
							((Color)(ref val5))..ctor((float)(int)val3.r / 255f, (float)(int)val3.g / 255f, (float)(int)val3.b / 255f, (float)(int)val3.a / 255f);
							((Color)(ref val6))..ctor(val4.r, val4.g, val4.b, 0.55f);
							Color val7 = Color.Lerp(val5, val6, val6.a);
							val7.a = val5.a;
							pixels[num] = Color32.op_Implicit(val7);
						}
					}
				}
				val2.SetPixels32(pixels);
				val2.Apply();
				return Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f));
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogError((object)("Monsoon+ icon generation failed: " + ex));
				}
				return null;
			}
		}

		private static void ExportGeneratedIcon(Sprite sprite)
		{
			if ((Object)(object)sprite == (Object)null || (Object)(object)sprite.texture == (Object)null)
			{
				return;
			}
			try
			{
				byte[] bytes = ImageConversion.EncodeToPNG(sprite.texture);
				File.WriteAllBytes(Path.Combine(Paths.BepInExRootPath, "monsoon_plus_generated_icon.png"), bytes);
			}
			catch (Exception ex)
			{
				if (Log != null)
				{
					Log.LogError((object)("Monsoon+ icon export failed: " + ex));
				}
			}
		}

		private static void RegisterLanguageTokens()
		{
			if (Language.english != null)
			{
				Language.english.SetStringByToken("MONSOON_PLUS_NAME", "Monsoon+");
				Language.english.SetStringByToken("MONSOON_PLUS_DESCRIPTION", "A nastier Monsoon for veteran players.<style=cStack>\n\n>Player Health Regeneration: <style=cIsHealth>-40%</style> \n>Difficulty Scaling: <style=cIsHealth>+65%</style> \n>Enemy Level Cap: <style=cIsHealth>125</style> \n>Late-Game Gold: <style=cIsHealth>Reduced from Stage 4</style></style>");
			}
		}

		internal static float GoldMultiplierForStage(int stage)
		{
			if (stage < 4)
			{
				return 1f;
			}
			float num = GoldStage4Multiplier - GoldRampStep * (float)(stage - 4);
			return Mathf.Max(GoldMinMultiplier, num);
		}
	}
}