Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of EnemyVariety v0.3.3
EnemyVariety.dll
Decompiled 2 weeks 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; } } }