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 EnemyVariety v0.3.3
EnemyVariety.dll
Decompiled 6 months agousing System; using System.Collections; 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.Permissions; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Microsoft.CodeAnalysis; using Mono.Cecil.Cil; using MonoMod.Cil; using RoR2; using UnityEngine; using UnityEngine.AddressableAssets; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 Local.Enemy.Variety { internal class Override : MonoBehaviour { internal Type value; internal static void Set(CombatDirector director, Type value) { Override @override = ((Component)director).GetComponent<Override>(); if (value == Type.None) { if (!Object.op_Implicit((Object)(object)@override)) { return; } Object.Destroy((Object)(object)@override); } else if (@override == null) { @override = ((Component)director).gameObject.AddComponent<Override>(); } Console.WriteLine($"Set override to '{value}' for \"{((Object)director).name}\"."); @override.value = value; } internal static Type Get(CombatDirector director) { Override @override = default(Override); if (!((Component)director).TryGetComponent<Override>(ref @override)) { return Type.None; } return @override.value; } public static void Clear(CombatDirector director) { ref bool hasStartedWave = ref director.hasStartedWave; if (hasStartedWave) { Set(director, Type.None); } hasStartedWave = false; } } internal enum Type { None, Scene, Boss, Shrine, Card } internal class Hook { [CompilerGenerated] private sealed class <TriggerWaveStart>d__0 : IEnumerable<CodeInstruction>, IEnumerable, IEnumerator<CodeInstruction>, IEnumerator, IDisposable { private int <>1__state; private CodeInstruction <>2__current; private int <>l__initialThreadId; private IEnumerable<CodeInstruction> IL; public IEnumerable<CodeInstruction> <>3__IL; private FieldInfo <indicator>5__2; private FieldInfo <configuration>5__3; private IEnumerator<CodeInstruction> <>7__wrap3; private CodeInstruction <instruction>5__5; CodeInstruction IEnumerator<CodeInstruction>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TriggerWaveStart>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 7u) { try { } finally { <>m__Finally1(); } } <indicator>5__2 = null; <configuration>5__3 = null; <>7__wrap3 = null; <instruction>5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Expected O, but got Unknown //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Expected O, but got Unknown //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Expected O, but got Unknown //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Expected O, but got Unknown try { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; System.Type typeFromHandle = typeof(CombatDirector); <indicator>5__2 = typeFromHandle.GetField("hasStartedWave", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); <configuration>5__3 = typeFromHandle.GetField("shouldSpawnOneWave"); <>7__wrap3 = IL.GetEnumerator(); <>1__state = -3; break; } case 1: <>1__state = -3; if (CodeInstructionExtensions.LoadsField(<instruction>5__5, <configuration>5__3, false)) { <>2__current = new CodeInstruction(OpCodes.Pop, (object)null); <>1__state = 2; return true; } if (CodeInstructionExtensions.LoadsField(<instruction>5__5, <indicator>5__2, false)) { <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 4; return true; } goto IL_0212; case 2: <>1__state = -3; <>2__current = new CodeInstruction(OpCodes.Ldc_I4_1, (object)null); <>1__state = 3; return true; case 3: <>1__state = -3; goto IL_0212; case 4: <>1__state = -3; <>2__current = new CodeInstruction(OpCodes.Ldfld, (object)<configuration>5__3); <>1__state = 5; return true; case 5: <>1__state = -3; <>2__current = new CodeInstruction(OpCodes.And, (object)null); <>1__state = 6; return true; case 6: <>1__state = -3; <>2__current = new CodeInstruction(OpCodes.Ldarg_0, (object)null); <>1__state = 7; return true; case 7: <>1__state = -3; <>2__current = new CodeInstruction(OpCodes.Call, (object)typeof(Override).GetMethod("Clear")); <>1__state = 8; return true; case 8: { <>1__state = -3; goto IL_0212; } IL_0212: <instruction>5__5 = null; break; } if (<>7__wrap3.MoveNext()) { <instruction>5__5 = <>7__wrap3.Current; <>2__current = <instruction>5__5; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap3 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>7__wrap3 != null) { <>7__wrap3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<CodeInstruction> IEnumerable<CodeInstruction>.GetEnumerator() { <TriggerWaveStart>d__0 <TriggerWaveStart>d__; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; <TriggerWaveStart>d__ = this; } else { <TriggerWaveStart>d__ = new <TriggerWaveStart>d__0(0); } <TriggerWaveStart>d__.IL = <>3__IL; return <TriggerWaveStart>d__; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<CodeInstruction>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TriggerWaveStart>d__0))] [HarmonyPatch(typeof(CombatDirector), "Simulate")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> TriggerWaveStart(IEnumerable<CodeInstruction> IL) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TriggerWaveStart>d__0(-2) { <>3__IL = IL }; } [HarmonyPatch(typeof(CombatDirector), "SpendAllCreditsOnMapSpawns", new System.Type[] { typeof(Transform) })] [HarmonyPrefix] private static void PopulateScene(CombatDirector __instance) { __instance.hasStartedWave = true; Override.Set(__instance, Type.Scene); } [HarmonyPatch(typeof(CombatDirector), "SpendAllCreditsOnMapSpawns", new System.Type[] { typeof(Transform) })] [HarmonyPostfix] private static void EndScene(CombatDirector __instance) { Override.Clear(__instance); } [HarmonyPatch(typeof(CombatDirector), "SetNextSpawnAsBoss")] [HarmonyPrefix] private static void SetBoss(CombatDirector __instance) { Override.Set(__instance, Type.Boss); } [HarmonyPatch(typeof(CombatDirector), "CombatShrineActivation")] [HarmonyPostfix] private static void CombatShrine(CombatDirector __instance) { Override.Set(__instance, Type.Shrine); } [HarmonyPatch(typeof(CombatDirector), "OverrideCurrentMonsterCard")] [HarmonyPrefix] private static void OverrideMonsterCard(CombatDirector __instance) { Override.Set(__instance, Type.Card); } } [BepInPlugin("local.enemy.variety", "EnemyVariety", "0.3.3")] internal class Plugin : BaseUnityPlugin { public const string version = "0.3.3"; public const string identifier = "local.enemy.variety"; private static ConfigEntry<bool> scene; private static ConfigEntry<bool> boss; private static ConfigEntry<bool> combat; private static ConfigEntry<float> horde; private static ConfigEntry<float> debt; protected async void Awake() { boss = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Apply to Teleporter Boss", true, "If enabled, multiple types of bosses may appear for the teleporter event."); horde = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Horde of Many", 5f, new ConfigDescription("Percent chance for a different type of monster to be chosen instead.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); scene = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Scene Director", true, "This determines if expensive enemies are favored during initialization."); combat = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Shrine of Combat", true, "Whether those summoned by this interactable should be affected."); debt = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Credit Lending", 12.5f, new ConfigDescription("Allow the director to borrow extra credit, to be repaid in the future.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>())); Harmony.CreateAndPatchAll(typeof(Plugin), (string)null); Harmony.CreateAndPatchAll(typeof(Hook), (string)null); GameObject val = await Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC2/ShrineHalcyonite.prefab").Task; if (Object.op_Implicit((Object)(object)val)) { CombatDirector[] componentsInChildren = val.GetComponentsInChildren<CombatDirector>(); for (int i = 0; i < componentsInChildren.Length; i++) { ((Behaviour)componentsInChildren[i]).enabled = false; } } } [HarmonyPatch(typeof(CombatDirector), "AttemptSpawnOnTarget")] [HarmonyPrefix] private static void ResetMonsterCard(CombatDirector __instance) { //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0156: 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) WeightedSelection<DirectorCard> finalMonsterCardsSelection = __instance.finalMonsterCardsSelection; if (finalMonsterCardsSelection == null || !__instance.resetMonsterCardIfFailed) { return; } DirectorCard currentMonsterCard = __instance.currentMonsterCard; Xoroshiro128Plus rng = __instance.rng; bool? flag = null; switch (Override.Get(__instance)) { case Type.Scene: { SceneDef currentSceneDef = SceneCatalog.currentSceneDef; if (!scene.Value || currentSceneDef == null || currentSceneDef.stageOrder > 5) { return; } break; } case Type.Boss: if (!boss.Value) { return; } if (__instance.hasStartedWave) { flag = false; if (currentMonsterCard == null || !currentMonsterCard.IsBoss()) { return; } } else { flag = rng.nextNormalizedFloat < horde.Value / 100f; if (currentMonsterCard != null && currentMonsterCard.IsBoss() != flag) { return; } } break; case Type.Shrine: if (!combat.Value) { return; } break; case Type.Card: return; } int spawnCountInCurrentWave = __instance.spawnCountInCurrentWave; int num = 0; if (currentMonsterCard != null) { num = currentMonsterCard.cost; } else if (!flag.HasValue) { return; } WeightedSelection<DirectorCard> val = new WeightedSelection<DirectorCard>(finalMonsterCardsSelection.Count); float monsterCredit = __instance.monsterCredit; float val2 = Math.Min(800f, monsterCredit); monsterCredit *= 1f + debt.Value / 100f; for (int i = 0; i < finalMonsterCardsSelection.Count; i++) { ChoiceInfo<DirectorCard> choice = finalMonsterCardsSelection.GetChoice(i); currentMonsterCard = choice.value; if ((currentMonsterCard.cost <= num || !((float)currentMonsterCard.cost > monsterCredit)) && currentMonsterCard.IsAvailable()) { if (!flag.HasValue) { choice.weight *= Math.Min(currentMonsterCard.cost, val2); } else if (currentMonsterCard.IsBoss() == flag) { continue; } val.AddChoice(choice); } } if (val.totalWeight > 0f) { currentMonsterCard = val.Evaluate(rng.nextNormalizedFloat); __instance.PrepareNewMonsterWave(currentMonsterCard); __instance.spawnCountInCurrentWave = spawnCountInCurrentWave; } } [HarmonyPrefix] [HarmonyPatch(typeof(Chat), "SendBroadcastChat", new System.Type[] { typeof(ChatMessageBase) })] private static void ChangeMessage(ChatMessageBase message) { SubjectFormatChatMessage val = (SubjectFormatChatMessage)(object)((message is SubjectFormatChatMessage) ? message : null); if (val != null) { bool? flag = val.paramTokens?.Any(); if (flag.HasValue && flag.GetValueOrDefault() && combat.Value && ((SubjectChatMessage)val).baseToken == "SHRINE_COMBAT_USE_MESSAGE") { val.paramTokens[0] = Language.GetString("LOGBOOK_CATEGORY_MONSTER").ToLower(); } } } [HarmonyPatch(typeof(BossGroup), "UpdateBossMemories")] [HarmonyPostfix] private static void UpdateTitle(BossGroup __instance) { if (!boss.Value) { return; } Dictionary<(string, string), float> dictionary = new Dictionary<(string, string), float>(); float num = 0f; for (int i = 0; i < __instance.bossMemoryCount; i++) { CharacterBody cachedBody = __instance.bossMemories[i].cachedBody; if (!Object.op_Implicit((Object)(object)cachedBody)) { continue; } HealthComponent healthComponent = cachedBody.healthComponent; if (!(((healthComponent != null) ? new bool?(healthComponent.alive) : null) ?? true)) { continue; } string bestBodyName = Util.GetBestBodyName(((Component)cachedBody).gameObject); string text = cachedBody.GetSubtitle(); (string, string) key = (bestBodyName, text); if (!dictionary.ContainsKey(key)) { dictionary[key] = 0f; } dictionary[key] += healthComponent.combinedHealth + healthComponent.missingCombinedHealth * 4f; if (dictionary[key] > num) { num = dictionary[key]; if (string.IsNullOrEmpty(text)) { text = Language.GetString("NULL_SUBTITLE"); } __instance.bestObservedName = bestBodyName; __instance.bestObservedSubtitle = "<sprite name=\"CloudLeft\" tint=1> " + text + " <sprite name=\"CloudRight\" tint=1>"; } } } [HarmonyPatch(typeof(CombatDirector), "AttemptSpawnOnTarget")] [HarmonyILManipulator] private static void AllowNegativeCredit(ILContext context) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(context); System.Type typeFromHandle = typeof(CombatDirector); FieldInfo field = typeFromHandle.GetField("skipSpawnIfTooCheap"); val.TryGotoNext(new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchLdfld(i, field) }); field = typeFromHandle.GetField("monsterCredit"); while (val.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1] { (Instruction i) => ILPatternMatchingExt.MatchLdfld(i, field) })) { Instruction previous = val.Previous; val.EmitDelegate<Func<float>>((Func<float>)(() => 1f + debt.Value / 100f)); val.Emit(OpCodes.Mul); val.Next = previous; } } [HarmonyPatch(typeof(CombatDirector), "OnDisable")] [HarmonyPrefix] private static void InheritDebt(CombatDirector __instance) { ref float monsterCredit = ref __instance.monsterCredit; if (monsterCredit > 0f) { monsterCredit /= 2.5f; } monsterCredit = 2.5f * Mathf.Floor(monsterCredit); } } internal static class Extension { internal static bool IsBoss(this DirectorCard card) { SpawnCard spawnCard = card.spawnCard; CharacterSpawnCard val = (CharacterSpawnCard)(object)((spawnCard is CharacterSpawnCard) ? spawnCard : null); if (val == null || val.forbiddenAsBoss) { return false; } return ((SpawnCard)val).prefab.GetComponent<CharacterMaster>().bodyPrefab.GetComponent<CharacterBody>().isChampion; } } }