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 MiscNewtFixes v1.0.2
MiscNewtFixes.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using RoR2; using UnityEngine; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace FluxSquido.MiscNewtFixes; [BepInPlugin("FluxSquido.MiscNewtFixes", "MiscNewtFixes", "1.0.0")] public class MiscNewtFixesPlugin : BaseUnityPlugin { public const string GUID = "FluxSquido.MiscNewtFixes"; public const string NAME = "MiscNewtFixes"; public const string VERSION = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> CfgFixDistantRoost; internal static ConfigEntry<bool> CfgScorchedAcresMinimum; internal const string GeneralSection = "1. General Fixes"; internal const string DoorSection = "2. Door Fixes"; internal const string BridgeSection = "3. Bridge Fixes"; private void Awake() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; CfgFixDistantRoost = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General Fixes", "Fix Distant Roost Newt Spawn", true, "\"Fixes\" the newt spawns on Distant Roost by increasing the minimum amount of Newt Alter spawns to 1. Note that in vanilla, Distant Roost is seemingly the only map that is intended to have 0-1 newt alter spawns."); CfgScorchedAcresMinimum = ((BaseUnityPlugin)this).Config.Bind<bool>("1. General Fixes", "Scorched Acres Minimum Newt Spawns", true, "Scorched acres can spawn 0-2 newt alters, but an extra 3rd is always guaranteed. Increasing the minimum spawned to 2 fixes an issue in this mod where, when the bridge to one of the newt alters is cut off, another newt alter can still spawn. (I highly suggest keeping this on, unless you turn off the bridge fix for this stage.)"); NewtFixer.BindConfig(((BaseUnityPlugin)this).Config); Harmony val = new Harmony("FluxSquido.MiscNewtFixes"); val.PatchAll(typeof(ToggleGroupAppliedPatch)); val.PatchAll(typeof(DistantRoostMinimumPatch)); Log.LogInfo((object)"MiscNewtFixes 1.0.0 loaded."); } } [HarmonyPatch(typeof(SceneObjectToggleGroup), "OnServerSceneChanged")] internal static class ToggleGroupAppliedPatch { private static void Postfix() { if (!NetworkServer.active) { return; } try { NewtFixer.Run(); } catch (Exception ex) { MiscNewtFixesPlugin.Log.LogError((object)("Newt Altar check failed: " + ex)); } } } [HarmonyPatch(typeof(SceneObjectToggleGroup), "Awake")] internal static class DistantRoostMinimumPatch { private const string DistantRoost = "blackbeach"; private static void Prefix(SceneObjectToggleGroup __instance) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) if (!MiscNewtFixesPlugin.CfgFixDistantRoost.Value || !NetworkServer.active) { return; } Scene scene = ((Component)__instance).gameObject.scene; if (((Scene)(ref scene)).name != "blackbeach" || __instance.toggleGroups == null) { return; } try { for (int i = 0; i < __instance.toggleGroups.Length; i++) { GameObjectToggleGroup val = __instance.toggleGroups[i]; if (val.minEnabled < 1 && val.maxEnabled >= 1 && HasNewtAltar(val.objects)) { __instance.toggleGroups[i].minEnabled = 1; } } } catch (Exception ex) { MiscNewtFixesPlugin.Log.LogError((object)("Distant Roost Newt fix failed: " + ex)); } } private static bool HasNewtAltar(GameObject[] objects) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (objects == null) { return false; } foreach (GameObject val in objects) { if (!((Object)(object)val == (Object)null)) { PortalStatueBehavior componentInChildren = val.GetComponentInChildren<PortalStatueBehavior>(true); if ((Object)(object)componentInChildren != (Object)null && (int)componentInChildren.portalType == 0) { return true; } } } return false; } } internal static class NewtFixer { private sealed class BlockedSpot { public string Section; public string Key; public string Description; public string Stage; public string Piece; public string Why; public bool WhenMissing; public Vector3 Spot; public ConfigEntry<bool> Enabled; public static BlockedSpot Door(string key, string stage, string piece, float x, float y, float z, string blocker = "closed door", string note = null) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) BlockedSpot blockedSpot = new BlockedSpot(); blockedSpot.Section = "2. Door Fixes"; blockedSpot.Key = key; blockedSpot.Stage = stage; blockedSpot.Piece = piece; blockedSpot.Spot = new Vector3(x, y, z); blockedSpot.Why = blocker; blockedSpot.Description = "Moves the Newt Altar to another spot when it spawns behind the " + blocker + " on " + key + "." + ((note == null) ? "" : (" " + note)); return blockedSpot; } public static BlockedSpot Bridge(string key, string stage, string piece, float x, float y, float z, string reach = "that spot is hard or impossible to reach for some survivors") { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) BlockedSpot blockedSpot = new BlockedSpot(); blockedSpot.Section = "3. Bridge Fixes"; blockedSpot.Key = key; blockedSpot.Stage = stage; blockedSpot.Piece = piece; blockedSpot.WhenMissing = true; blockedSpot.Spot = new Vector3(x, y, z); blockedSpot.Why = "missing bridge"; blockedSpot.Description = "Moves the Newt Altar to another spot when it spawns across the bridge on " + key + " and the bridge didn't spawn (" + reach + ")."; return blockedSpot; } } private sealed class Spot { public SceneObjectToggleGroup Group; public int ListIndex; public int FlatIndex; public Vector3 Position; public bool Blocked; public string Why; } private static readonly BlockedSpot[] Blocked = new BlockedSpot[6] { BlockedSpot.Door("Distant Roost", "blackbeach", "DownstairsGate, Closed", 215f, -251f, 20f, "closed door", "This spot is technically reachable on all survivors by going up the side of the mountain towards the Artifact spot, and then jumping down, but for ease sake, and the overall goal of the mod, its an option here. Feel free to toggle off if you prefer going up the mountain."), BlockedSpot.Door("Distant Roost (Variant 2)", "blackbeach2", "DownstairsGate, Closed", -269f, 10f, 7f), BlockedSpot.Door("Siphoned Forest", "snowyforest", "HOLDER: Gate", -250f, 26f, 58f, "collapsed gate", "This spot is completely inaccessible if the gate is collapsed, meaning that without this on, a Newt Alter can become completely unreachable."), BlockedSpot.Door("Abyssal Depths", "dampcavesimple", "HOLDER: Gameplay Space/Ruins/DCRuinGate (Cave Gate 1)/ClosedSet", -1f, -140f, -451f, "closed door", "This spot is completely inaccessible if the door is closed, meaning that without this on, a Newt Alter can become completely unreachable."), BlockedSpot.Bridge("Distant Roost", "blackbeach", "GAMEPLAY SPACE/Terrain/blackbeachIslandBridge", -258f, -161f, -261f), BlockedSpot.Bridge("Scorched Acres", "wispgraveyard", "ENTIRE SCENE HOLDER/HOLDER: Temple Pieces/WPPlatform2 (Level 1)/WPPlatform2 (Level 2)/WPBridgeEntry (Gate: IslandBridge)", -287f, 82f, -194f, "that spot is easily reachable on all survivors, but requires you to jump into the void to get back, so I'm keeping as an option") }; private const float SpotMatchDistance = 15f; private const BindingFlags Private = BindingFlags.Instance | BindingFlags.NonPublic; private static readonly FieldInfo ActivationsField = typeof(SceneObjectToggleGroup).GetField("activations", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly MethodInfo ApplyActivationsMethod = typeof(SceneObjectToggleGroup).GetMethod("ApplyActivations", BindingFlags.Instance | BindingFlags.NonPublic); internal static void BindConfig(ConfigFile config) { BlockedSpot[] blocked = Blocked; foreach (BlockedSpot blockedSpot in blocked) { blockedSpot.Enabled = config.Bind<bool>(blockedSpot.Section, blockedSpot.Key, true, blockedSpot.Description + " Only the host's setting matters."); } } internal static void Run() { if (ActivationsField == null || ApplyActivationsMethod == null) { return; } string text = ((!((Object)(object)SceneCatalog.mostRecentSceneDef != (Object)null)) ? null : SceneCatalog.mostRecentSceneDef.cachedName); if (text == null) { return; } bool flag = false; BlockedSpot[] blocked = Blocked; foreach (BlockedSpot blockedSpot in blocked) { if (blockedSpot.Stage == text && blockedSpot.Enabled.Value) { flag = true; break; } } int num = MinimumFor(text); if (!flag && num == 0) { return; } SceneObjectToggleGroup[] groups = Object.FindObjectsOfType<SceneObjectToggleGroup>(); List<Spot> list = FindNewtSpots(groups); if (list.Count != 0) { Random rng = MakeRng(groups, text); if (flag && MarkBlocked(text, list)) { Reroll(list, rng, text); } if (num > 0) { TopUp(list, rng, text, num); } } } private static int MinimumFor(string scene) { if (scene == "wispgraveyard" && MiscNewtFixesPlugin.CfgScorchedAcresMinimum.Value) { return 2; } return 0; } private static void TopUp(List<Spot> spots, Random rng, string scene, int minimum) { int num = 0; List<Spot> list = new List<Spot>(); foreach (Spot spot2 in spots) { if (!spot2.Blocked) { if (IsOn(spot2)) { num++; } else { list.Add(spot2); } } } int num2 = 0; HashSet<SceneObjectToggleGroup> hashSet = new HashSet<SceneObjectToggleGroup>(); while (num < minimum && list.Count > 0) { int index = rng.Next(list.Count); Spot spot = list[index]; list.RemoveAt(index); ((bool[])ActivationsField.GetValue(spot.Group))[spot.FlatIndex] = true; hashSet.Add(spot.Group); num++; num2++; } foreach (SceneObjectToggleGroup item in hashSet) { Apply(item); } if (num2 > 0) { MiscNewtFixesPlugin.Log.LogInfo((object)("[" + scene + "] Added " + num2 + " Newt Altar" + ((num2 <= 1) ? "" : "s") + " (minimum " + minimum + ").")); } } private static bool IsOn(Spot spot) { bool[] array = (bool[])ActivationsField.GetValue(spot.Group); return array != null && spot.FlatIndex < array.Length && array[spot.FlatIndex]; } private static List<Spot> FindNewtSpots(SceneObjectToggleGroup[] groups) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) List<Spot> list = new List<Spot>(); foreach (SceneObjectToggleGroup val in groups) { if (val.toggleGroups == null) { continue; } int num = 0; for (int j = 0; j < val.toggleGroups.Length; j++) { GameObject[] objects = val.toggleGroups[j].objects; if (objects == null) { continue; } int num2 = 0; while (num2 < objects.Length) { PortalStatueBehavior val2 = NewtOf(objects[num2]); if ((Object)(object)val2 != (Object)null) { list.Add(new Spot { Group = val, ListIndex = j, FlatIndex = num, Position = ((Component)val2).transform.position }); } num2++; num++; } } } return list; } private static PortalStatueBehavior NewtOf(GameObject obj) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return null; } PortalStatueBehavior componentInChildren = obj.GetComponentInChildren<PortalStatueBehavior>(true); return (!((Object)(object)componentInChildren != (Object)null) || (int)componentInChildren.portalType != 0) ? null : componentInChildren; } private static bool MarkBlocked(string scene, List<Spot> spots) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) bool result = false; List<Transform> list = null; BlockedSpot[] blocked = Blocked; foreach (BlockedSpot blockedSpot in blocked) { if (blockedSpot.Stage != scene || !blockedSpot.Enabled.Value) { continue; } if (list == null) { list = ActiveTransforms(); } if (PieceIsThere(list, blockedSpot.Piece) != blockedSpot.WhenMissing) { Spot spot = Nearest(spots, blockedSpot.Spot); if (spot != null) { spot.Blocked = true; spot.Why = blockedSpot.Why; result = true; } } } return result; } private static List<Transform> ActiveTransforms() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = new List<Transform>(); List<Transform> list2 = new List<Transform>(); for (int i = 0; i < SceneManager.sceneCount; i++) { Scene sceneAt = SceneManager.GetSceneAt(i); if (!((Scene)(ref sceneAt)).isLoaded) { continue; } GameObject[] rootGameObjects = ((Scene)(ref sceneAt)).GetRootGameObjects(); foreach (GameObject val in rootGameObjects) { if (val.activeSelf) { val.GetComponentsInChildren<Transform>(false, list2); list.AddRange(list2); } } } return list; } private static bool PieceIsThere(List<Transform> active, string piece) { int num = piece.LastIndexOf('/'); string text = ((num < 0) ? piece : piece.Substring(num + 1)); foreach (Transform item in active) { if (((Object)item).name != text || (num >= 0 && PathOf(item) != piece)) { continue; } Collider[] componentsInChildren = ((Component)item).GetComponentsInChildren<Collider>(false); foreach (Collider val in componentsInChildren) { if (val.enabled && !val.isTrigger) { return true; } } } return false; } private static string PathOf(Transform t) { string text = ((Object)t).name; Transform parent = t.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static Spot Nearest(List<Spot> spots, Vector3 at) { //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_0028: Unknown result type (might be due to invalid IL or missing references) Spot result = null; float num = 225f; foreach (Spot spot in spots) { Vector3 val = spot.Position - at; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= num) { num = sqrMagnitude; result = spot; } } return result; } private static Random MakeRng(SceneObjectToggleGroup[] groups, string scene) { Run instance = Run.instance; int num = ((!((Object)(object)instance != (Object)null)) ? Environment.TickCount : ((int)instance.seed ^ (int)(instance.seed >> 32) ^ (instance.stageClearCount * 7919))); foreach (SceneObjectToggleGroup obj in groups) { if (ActivationsField.GetValue(obj) is bool[] array) { for (int j = 0; j < array.Length; j++) { num = num * 31 + (array[j] ? (j + 1) : 0); } } } return new Random(num ^ scene.GetHashCode()); } private static void Reroll(List<Spot> spots, Random rng, string scene) { List<Spot> list = new List<Spot>(); foreach (Spot spot2 in spots) { if (!spot2.Blocked) { continue; } bool[] array = (bool[])ActivationsField.GetValue(spot2.Group); if (!array[spot2.FlatIndex]) { continue; } list.Clear(); foreach (Spot spot3 in spots) { if ((Object)(object)spot3.Group == (Object)(object)spot2.Group && spot3.ListIndex == spot2.ListIndex && !spot3.Blocked && !array[spot3.FlatIndex]) { list.Add(spot3); } } if (list.Count == 0) { MiscNewtFixesPlugin.Log.LogInfo((object)("[" + scene + "] Newt Altar unreachable (" + spot2.Why + "), no free spot; leaving it.")); } else { Spot spot = list[rng.Next(list.Count)]; array[spot2.FlatIndex] = false; array[spot.FlatIndex] = true; Apply(spot2.Group); MiscNewtFixesPlugin.Log.LogInfo((object)("[" + scene + "] Newt Altar unreachable (" + spot2.Why + "), moved it.")); } } } private static void Apply(SceneObjectToggleGroup group) { ApplyActivationsMethod.Invoke(group, null); ((NetworkBehaviour)group).SetDirtyBit(1u); } }