Decompiled source of BossMutations v1.0.0

BossMutations.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using On.RoR2;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

[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("BossMutations")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BossMutations")]
[assembly: AssemblyTitle("BossMutations")]
[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 BossMutations
{
	[BepInPlugin("dileppy.bossmutations", "BossMutations", "1.0.0")]
	public class BossMutationsPlugin : BaseUnityPlugin
	{
		public enum BossMutationType
		{
			None,
			Colossal,
			Frenzied,
			Shielded,
			Volatile,
			Splitting
		}

		public class BossMutationMarker : MonoBehaviour
		{
			public BossMutationType type;

			public float rewardMult = 1f;

			public bool burst75;

			public bool burst50;

			public bool burst25;

			public bool split66;

			public bool split33;

			public float nextShieldTime;
		}

		public class SplitChildMarker : MonoBehaviour
		{
		}

		private class SizeMarker : MonoBehaviour
		{
			public Vector3 baseScale;
		}

		public const string PluginGUID = "dileppy.bossmutations";

		public const string PluginName = "BossMutations";

		public const string PluginVersion = "1.0.0";

		public static ConfigEntry<float> BossMutationChance;

		public static ConfigEntry<float> ChancePerLoop;

		public static ConfigEntry<bool> EnableColossal;

		public static ConfigEntry<bool> EnableFrenzied;

		public static ConfigEntry<bool> EnableShielded;

		public static ConfigEntry<bool> EnableVolatile;

		public static ConfigEntry<bool> EnableSplitting;

		public static ConfigEntry<bool> AnnounceMutation;

		public static ConfigEntry<int> SplitCount;

		public static ConfigEntry<float> ShieldPulseInterval;

		public static ConfigEntry<float> ShieldPulseFraction;

		public static ConfigEntry<float> VolatileBurstDamage;

		public static ConfigEntry<float> VolatileBurstRadius;

		public static ConfigEntry<bool> DebugLogging;

		private static readonly Random rng = new Random();

		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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0166: Expected O, but got Unknown
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Expected O, but got Unknown
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Expected O, but got Unknown
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021d: Expected O, but got Unknown
			//IL_0250: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Expected O, but got Unknown
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Expected O, but got Unknown
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a1: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Expected O, but got Unknown
			BossMutationChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BossMutationChance", 25f, new ConfigDescription("Percent chance a boss spawns mutated.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
			ChancePerLoop = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChancePerLoop", 10f, new ConfigDescription("Percent added to the chance per completed loop.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			AnnounceMutation = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AnnounceMutation", true, "Post a chat message naming the boss mutation when one spawns.");
			EnableColossal = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableColossal", true, "180% size, double HP, +30% damage, slower attacks. A monument.");
			EnableFrenzied = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableFrenzied", true, "+40% speed and attack speed, -25% HP. A blur.");
			EnableShielded = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableShielded", true, "Periodically gains a barrier. Burst it down in the windows.");
			EnableVolatile = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableVolatile", true, "Explosion bursts at 75/50/25% health. Respect the space.");
			EnableSplitting = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableSplitting", true, "Spawns smaller copies of itself at 66% and 33% health.");
			SplitCount = ((BaseUnityPlugin)this).Config.Bind<int>("Mutations", "SplitCount", 2, new ConfigDescription("How many smaller copies each split spawns.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 4), Array.Empty<object>()));
			ShieldPulseInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "ShieldPulseInterval", 12f, new ConfigDescription("Seconds between Shielded barrier pulses.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 60f), Array.Empty<object>()));
			ShieldPulseFraction = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "ShieldPulseFraction", 0.25f, new ConfigDescription("Barrier gained per pulse as a fraction of max HP.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 1f), Array.Empty<object>()));
			VolatileBurstDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "VolatileBurstDamage", 10f, new ConfigDescription("Volatile burst damage as a multiple of the boss's base damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), Array.Empty<object>()));
			VolatileBurstRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "VolatileBurstRadius", 18f, new ConfigDescription("Volatile burst radius in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 50f), Array.Empty<object>()));
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "DebugLogging", false, "Log rolls and threshold triggers.");
			CharacterBody.Start += new hook_Start(CharacterBody_Start);
			CharacterBody.RecalculateStats += new hook_RecalculateStats(CharacterBody_RecalculateStats);
			DeathRewards.OnKilledServer += new hook_OnKilledServer(DeathRewards_OnKilledServer);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"BossMutations v1.0.0 loaded. Part of The Petrichor Protocol.");
		}

		private void OnDestroy()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			CharacterBody.Start -= new hook_Start(CharacterBody_Start);
			CharacterBody.RecalculateStats -= new hook_RecalculateStats(CharacterBody_RecalculateStats);
			DeathRewards.OnKilledServer -= new hook_OnKilledServer(DeathRewards_OnKilledServer);
		}

		private static void ApplyAbsoluteScale(GameObject go, float factor)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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)
			if (!Object.op_Implicit((Object)(object)go))
			{
				return;
			}
			Scene scene = go.scene;
			if (((Scene)(ref scene)).IsValid())
			{
				SizeMarker sizeMarker = go.GetComponent<SizeMarker>();
				if (!Object.op_Implicit((Object)(object)sizeMarker))
				{
					sizeMarker = go.AddComponent<SizeMarker>();
					sizeMarker.baseScale = go.transform.localScale;
				}
				go.transform.localScale = sizeMarker.baseScale * factor;
			}
		}

		private static void ApplyModelScale(CharacterBody body, float factor)
		{
			ModelLocator modelLocator = body.modelLocator;
			if (Object.op_Implicit((Object)(object)modelLocator) && Object.op_Implicit((Object)(object)modelLocator.modelTransform))
			{
				ApplyAbsoluteScale(((Component)modelLocator.modelTransform).gameObject, factor);
			}
		}

		private void CharacterBody_Start(orig_Start orig, CharacterBody self)
		{
			orig.Invoke(self);
			if (!NetworkServer.active || !self.isBoss || Object.op_Implicit((Object)(object)((Component)self).GetComponent<BossMutationMarker>()))
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)self.master) && Object.op_Implicit((Object)(object)((Component)self.master).GetComponent<SplitChildMarker>()))
			{
				ApplyModelScale(self, 0.5f);
				BossMutationMarker bossMutationMarker = ((Component)self).gameObject.AddComponent<BossMutationMarker>();
				bossMutationMarker.type = BossMutationType.None;
				bossMutationMarker.rewardMult = 0.25f;
				self.RecalculateStats();
				return;
			}
			try
			{
				int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.loopClearCount : 0);
				float num2 = BossMutationChance.Value + ChancePerLoop.Value * (float)num;
				if (rng.NextDouble() * 100.0 > (double)num2)
				{
					return;
				}
				List<BossMutationType> list = new List<BossMutationType>();
				if (EnableColossal.Value)
				{
					list.Add(BossMutationType.Colossal);
				}
				if (EnableFrenzied.Value)
				{
					list.Add(BossMutationType.Frenzied);
				}
				if (EnableShielded.Value)
				{
					list.Add(BossMutationType.Shielded);
				}
				if (EnableVolatile.Value)
				{
					list.Add(BossMutationType.Volatile);
				}
				if (EnableSplitting.Value)
				{
					list.Add(BossMutationType.Splitting);
				}
				if (list.Count != 0)
				{
					BossMutationType bossMutationType = list[rng.Next(list.Count)];
					BossMutationMarker bossMutationMarker2 = ((Component)self).gameObject.AddComponent<BossMutationMarker>();
					bossMutationMarker2.type = bossMutationType;
					switch (bossMutationType)
					{
					case BossMutationType.Colossal:
						ApplyModelScale(self, 1.8f);
						bossMutationMarker2.rewardMult = 2f;
						break;
					case BossMutationType.Frenzied:
						ApplyModelScale(self, 0.95f);
						bossMutationMarker2.rewardMult = 1.6f;
						break;
					case BossMutationType.Shielded:
						bossMutationMarker2.rewardMult = 1.5f;
						bossMutationMarker2.nextShieldTime = Time.time + ShieldPulseInterval.Value;
						break;
					case BossMutationType.Volatile:
						ApplyModelScale(self, 1.1f);
						bossMutationMarker2.rewardMult = 1.6f;
						break;
					case BossMutationType.Splitting:
						ApplyModelScale(self, 1.15f);
						bossMutationMarker2.rewardMult = 1.8f;
						break;
					}
					((Component)self).gameObject.AddComponent<BossMutationWatcher>().Init(self, bossMutationMarker2, ((BaseUnityPlugin)this).Logger);
					self.RecalculateStats();
					if (AnnounceMutation.Value)
					{
						Chat.AddMessage($"<color=#ff6a4d>A {bossMutationType} {self.GetDisplayName()} emerges!</color>");
					}
					if (DebugLogging.Value)
					{
						((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0}: {1} rolled {2} ({3:F0}%)", "BossMutations", self.GetDisplayName(), bossMutationType, num2));
					}
				}
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0}: boss roll failed: {1}", "BossMutations", arg));
			}
		}

		private void CharacterBody_RecalculateStats(orig_RecalculateStats orig, CharacterBody self)
		{
			orig.Invoke(self);
			BossMutationMarker bossMutationMarker = (Object.op_Implicit((Object)(object)self) ? ((Component)self).GetComponent<BossMutationMarker>() : null);
			if ((Object)(object)bossMutationMarker == (Object)null)
			{
				return;
			}
			if (Object.op_Implicit((Object)(object)self.master) && Object.op_Implicit((Object)(object)((Component)self.master).GetComponent<SplitChildMarker>()))
			{
				self.maxHealth *= 0.25f;
				self.damage *= 0.5f;
				return;
			}
			switch (bossMutationMarker.type)
			{
			case BossMutationType.Colossal:
				self.maxHealth *= 2f;
				self.damage *= 1.3f;
				self.attackSpeed *= 0.8f;
				self.moveSpeed *= 0.85f;
				break;
			case BossMutationType.Frenzied:
				self.maxHealth *= 0.75f;
				self.moveSpeed *= 1.4f;
				self.attackSpeed *= 1.4f;
				break;
			case BossMutationType.Splitting:
				self.maxHealth *= 0.85f;
				break;
			case BossMutationType.Shielded:
			case BossMutationType.Volatile:
				break;
			}
		}

		private void DeathRewards_OnKilledServer(orig_OnKilledServer orig, DeathRewards self, DamageReport damageReport)
		{
			BossMutationMarker bossMutationMarker = (Object.op_Implicit((Object)(object)damageReport?.victimBody) ? ((Component)damageReport.victimBody).GetComponent<BossMutationMarker>() : null);
			if ((Object)(object)bossMutationMarker != (Object)null && bossMutationMarker.rewardMult != 1f)
			{
				self.goldReward = (uint)((float)self.goldReward * bossMutationMarker.rewardMult);
				self.expReward = (uint)((float)self.expReward * bossMutationMarker.rewardMult);
			}
			orig.Invoke(self, damageReport);
		}
	}
	public class BossMutationWatcher : MonoBehaviour
	{
		private CharacterBody body;

		private BossMutationsPlugin.BossMutationMarker marker;

		private ManualLogSource log;

		public void Init(CharacterBody b, BossMutationsPlugin.BossMutationMarker m, ManualLogSource l)
		{
			body = b;
			marker = m;
			log = l;
		}

		private void FixedUpdate()
		{
			if (!NetworkServer.active || !Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.healthComponent) || !body.healthComponent.alive || (Object)(object)marker == (Object)null)
			{
				return;
			}
			float combinedHealthFraction = body.healthComponent.combinedHealthFraction;
			if (marker.type == BossMutationsPlugin.BossMutationType.Volatile)
			{
				if (!marker.burst75 && combinedHealthFraction <= 0.75f)
				{
					marker.burst75 = true;
					Burst();
				}
				if (!marker.burst50 && combinedHealthFraction <= 0.5f)
				{
					marker.burst50 = true;
					Burst();
				}
				if (!marker.burst25 && combinedHealthFraction <= 0.25f)
				{
					marker.burst25 = true;
					Burst();
				}
			}
			else if (marker.type == BossMutationsPlugin.BossMutationType.Splitting)
			{
				if (!marker.split66 && combinedHealthFraction <= 0.66f)
				{
					marker.split66 = true;
					Split();
				}
				if (!marker.split33 && combinedHealthFraction <= 0.33f)
				{
					marker.split33 = true;
					Split();
				}
			}
			else if (marker.type == BossMutationsPlugin.BossMutationType.Shielded && Time.time >= marker.nextShieldTime)
			{
				marker.nextShieldTime = Time.time + BossMutationsPlugin.ShieldPulseInterval.Value;
				body.healthComponent.AddBarrier(body.maxHealth * BossMutationsPlugin.ShieldPulseFraction.Value);
			}
		}

		private void Burst()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00ee: Expected O, but got Unknown
			try
			{
				new BlastAttack
				{
					attacker = ((Component)body).gameObject,
					inflictor = ((Component)body).gameObject,
					teamIndex = (TeamIndex)((!Object.op_Implicit((Object)(object)body.teamComponent)) ? 2 : ((int)body.teamComponent.teamIndex)),
					baseDamage = body.baseDamage * BossMutationsPlugin.VolatileBurstDamage.Value,
					baseForce = 1200f,
					position = body.corePosition,
					radius = BossMutationsPlugin.VolatileBurstRadius.Value,
					falloffModel = (FalloffModel)1,
					attackerFiltering = (AttackerFiltering)2
				}.Fire();
				GameObject val = LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/OmniEffect/OmniExplosionVFX");
				if (Object.op_Implicit((Object)(object)val))
				{
					EffectManager.SpawnEffect(val, new EffectData
					{
						origin = body.corePosition,
						scale = BossMutationsPlugin.VolatileBurstRadius.Value
					}, true);
				}
			}
			catch (Exception arg)
			{
				log.LogError((object)$"BossMutations: burst failed: {arg}");
			}
		}

		private void Split()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//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_0073: 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)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!Object.op_Implicit((Object)(object)body.master))
				{
					return;
				}
				GameObject masterPrefab = MasterCatalog.GetMasterPrefab(body.master.masterIndex);
				if (!Object.op_Implicit((Object)(object)masterPrefab))
				{
					return;
				}
				for (int i = 0; i < BossMutationsPlugin.SplitCount.Value; i++)
				{
					CharacterMaster val = new MasterSummon
					{
						masterPrefab = masterPrefab,
						position = body.corePosition + Random.insideUnitSphere * 4f,
						rotation = Quaternion.identity,
						teamIndexOverride = (TeamIndex)((!Object.op_Implicit((Object)(object)body.teamComponent)) ? 2 : ((int)body.teamComponent.teamIndex)),
						ignoreTeamMemberLimit = true
					}.Perform();
					if (Object.op_Implicit((Object)(object)val))
					{
						((Component)val).gameObject.AddComponent<BossMutationsPlugin.SplitChildMarker>();
					}
				}
			}
			catch (Exception arg)
			{
				log.LogError((object)$"BossMutations: split failed: {arg}");
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "BossMutations";

		public const string PLUGIN_NAME = "BossMutations";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}