Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of EnemyMutations v1.0.0
EnemyMutations.dll
Decompiled 3 weeks agousing 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 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("EnemyMutations")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EnemyMutations")] [assembly: AssemblyTitle("EnemyMutations")] [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 EnemyMutations { [BepInPlugin("dileppy.enemymutations", "EnemyMutations", "1.0.0")] public class EnemyMutationsPlugin : BaseUnityPlugin { public enum MutationType { None, Giant, Tiny, Frenzied, Volatile, Treasure } public class MutationMarker : MonoBehaviour { public MutationType type; public float rewardMult = 1f; } private class SizeMarker : MonoBehaviour { public Vector3 baseScale; } public const string PluginGUID = "dileppy.enemymutations"; public const string PluginName = "EnemyMutations"; public const string PluginVersion = "1.0.0"; public static ConfigEntry<float> BaseMutationChance; public static ConfigEntry<float> ChanceScalingPerStage; public static ConfigEntry<bool> AllowBossMutations; public static ConfigEntry<bool> AllowEliteMutations; public static ConfigEntry<bool> EnableGiant; public static ConfigEntry<bool> EnableTiny; public static ConfigEntry<bool> EnableFrenzied; public static ConfigEntry<bool> EnableVolatile; public static ConfigEntry<bool> EnableTreasure; public static ConfigEntry<float> TreasureChance; public static ConfigEntry<bool> AnnounceTreasure; public static ConfigEntry<float> VolatileBlastDamage; public static ConfigEntry<float> VolatileBlastRadius; 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_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Expected O, but got Unknown //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Expected O, but got Unknown //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Expected O, but got Unknown //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Expected O, but got Unknown BaseMutationChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BaseMutationChance", 12f, new ConfigDescription("Percent chance an enemy spawns mutated on stage 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); ChanceScalingPerStage = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ChanceScalingPerStage", 2f, new ConfigDescription("Percent added to the mutation chance per stage cleared.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), Array.Empty<object>())); AllowBossMutations = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowBossMutations", false, "Whether teleporter and world bosses can roll mutations."); AllowEliteMutations = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AllowEliteMutations", true, "Whether elite enemies can roll mutations on top of their elite affix."); EnableGiant = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableGiant", true, "Larger, slower, tankier, more rewarding. Mini-boss moments."); EnableTiny = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableTiny", true, "Smaller, faster, harder to hit, less health, small reward bonus."); EnableFrenzied = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableFrenzied", true, "Much faster movement and attacks, reduced health. Kill it quickly."); EnableVolatile = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableVolatile", true, "Explodes on death. Watch your positioning and kill timing."); EnableTreasure = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "EnableTreasure", true, "Rare: tanky, dangerous, drops massively increased gold."); TreasureChance = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "TreasureChance", 10f, new ConfigDescription("When a mutation rolls, percent chance it upgrades to the rare Treasure mutation.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); AnnounceTreasure = ((BaseUnityPlugin)this).Config.Bind<bool>("Mutations", "AnnounceTreasure", true, "Post a chat message when a Treasure enemy spawns."); VolatileBlastDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "VolatileBlastDamage", 15f, new ConfigDescription("Volatile death explosion damage as a multiple of the enemy's base damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>())); VolatileBlastRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Mutations", "VolatileBlastRadius", 12f, new ConfigDescription("Volatile death explosion radius in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 40f), Array.Empty<object>())); DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Advanced", "DebugLogging", false, "Log every mutation roll to the console."); CharacterBody.Start += new hook_Start(CharacterBody_Start); CharacterBody.RecalculateStats += new hook_RecalculateStats(CharacterBody_RecalculateStats); DeathRewards.OnKilledServer += new hook_OnKilledServer(DeathRewards_OnKilledServer); GlobalEventManager.onCharacterDeathGlobal += OnCharacterDeath; ((BaseUnityPlugin)this).Logger.LogInfo((object)"EnemyMutations 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); GlobalEventManager.onCharacterDeathGlobal -= OnCharacterDeath; } private static bool IsHostileEnemy(CharacterBody body) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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) //IL_0025: Invalid comparison between Unknown and I4 //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Invalid comparison between Unknown and I4 if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.teamComponent)) { return false; } TeamIndex teamIndex = body.teamComponent.teamIndex; if ((int)teamIndex != 2 && (int)teamIndex != 3) { return (int)teamIndex == 4; } return true; } 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 void CharacterBody_Start(orig_Start orig, CharacterBody self) { orig.Invoke(self); if (!NetworkServer.active || !IsHostileEnemy(self) || Object.op_Implicit((Object)(object)((Component)self).GetComponent<MutationMarker>()) || (self.isBoss && !AllowBossMutations.Value) || (self.isElite && !AllowEliteMutations.Value)) { return; } try { int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : 0); float num2 = BaseMutationChance.Value + ChanceScalingPerStage.Value * (float)num; if (rng.NextDouble() * 100.0 > (double)num2) { return; } List<MutationType> list = new List<MutationType>(); if (EnableGiant.Value) { list.Add(MutationType.Giant); } if (EnableTiny.Value) { list.Add(MutationType.Tiny); } if (EnableFrenzied.Value) { list.Add(MutationType.Frenzied); } if (EnableVolatile.Value) { list.Add(MutationType.Volatile); } if (list.Count == 0 && !EnableTreasure.Value) { return; } MutationType mutationType; if (EnableTreasure.Value && rng.NextDouble() * 100.0 < (double)TreasureChance.Value) { mutationType = MutationType.Treasure; } else { if (list.Count <= 0) { return; } mutationType = list[rng.Next(list.Count)]; } MutationMarker mutationMarker = ((Component)self).gameObject.AddComponent<MutationMarker>(); mutationMarker.type = mutationType; switch (mutationType) { case MutationType.Giant: ApplyModelScale(self, 1.75f); mutationMarker.rewardMult = 2f; break; case MutationType.Tiny: ApplyModelScale(self, 0.5f); mutationMarker.rewardMult = 1.3f; break; case MutationType.Frenzied: ApplyModelScale(self, 0.9f); mutationMarker.rewardMult = 1.4f; break; case MutationType.Volatile: ApplyModelScale(self, 1.1f); mutationMarker.rewardMult = 1.5f; break; case MutationType.Treasure: ApplyModelScale(self, 1.2f); mutationMarker.rewardMult = 4f; if (AnnounceTreasure.Value) { Chat.AddMessage("<color=#ffd700>A Treasure " + self.GetDisplayName() + " has appeared!</color>"); } break; } self.RecalculateStats(); if (DebugLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0}: {1} rolled {2} (chance was {3:F0}%)", "EnemyMutations", self.GetDisplayName(), mutationType, num2)); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0}: mutation roll failed: {1}", "EnemyMutations", arg)); } } 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_RecalculateStats(orig_RecalculateStats orig, CharacterBody self) { orig.Invoke(self); MutationMarker mutationMarker = (Object.op_Implicit((Object)(object)self) ? ((Component)self).GetComponent<MutationMarker>() : null); if (!((Object)(object)mutationMarker == (Object)null)) { switch (mutationMarker.type) { case MutationType.Giant: self.maxHealth *= 2f; self.damage *= 1.3f; self.moveSpeed *= 0.8f; break; case MutationType.Tiny: self.maxHealth *= 0.6f; self.moveSpeed *= 1.5f; self.attackSpeed *= 1.25f; break; case MutationType.Frenzied: self.maxHealth *= 0.75f; self.moveSpeed *= 1.5f; self.attackSpeed *= 1.5f; self.damage *= 1.1f; break; case MutationType.Volatile: self.maxHealth *= 0.9f; break; case MutationType.Treasure: self.maxHealth *= 2f; self.damage *= 1.25f; break; } } } private void OnCharacterDeath(DamageReport report) { //IL_003c: 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_0052: 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_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Expected O, but got Unknown if (!NetworkServer.active || (Object)(object)report?.victimBody == (Object)null) { return; } MutationMarker component = ((Component)report.victimBody).GetComponent<MutationMarker>(); if ((Object)(object)component == (Object)null || component.type != MutationType.Volatile) { return; } try { new BlastAttack { attacker = ((Component)report.victimBody).gameObject, inflictor = ((Component)report.victimBody).gameObject, teamIndex = (TeamIndex)((!Object.op_Implicit((Object)(object)report.victimBody.teamComponent)) ? 2 : ((int)report.victimBody.teamComponent.teamIndex)), baseDamage = report.victimBody.baseDamage * VolatileBlastDamage.Value, baseForce = 800f, position = report.victimBody.corePosition, radius = VolatileBlastRadius.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 = report.victimBody.corePosition, scale = VolatileBlastRadius.Value }, true); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)string.Format("{0}: volatile blast failed: {1}", "EnemyMutations", arg)); } } private void DeathRewards_OnKilledServer(orig_OnKilledServer orig, DeathRewards self, DamageReport damageReport) { MutationMarker mutationMarker = (Object.op_Implicit((Object)(object)damageReport?.victimBody) ? ((Component)damageReport.victimBody).GetComponent<MutationMarker>() : null); if ((Object)(object)mutationMarker != (Object)null && mutationMarker.rewardMult != 1f) { self.goldReward = (uint)((float)self.goldReward * mutationMarker.rewardMult); self.expReward = (uint)((float)self.expReward * mutationMarker.rewardMult); } orig.Invoke(self, damageReport); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "EnemyMutations"; public const string PLUGIN_NAME = "EnemyMutations"; public const string PLUGIN_VERSION = "1.0.0"; } }