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 Taborusic Modpack v0.3.6
plugins/TestPackCompatibilityFix/TestPackCompatibilityFix.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using TMPro; using UnityEngine; [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.1.0.0")] namespace TestPackCompatibilityFix; [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("dieforlol1.testpack.compatibilityfix", "TestPack Compatibility Fix", "0.1.0")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "dieforlol1.testpack.compatibilityfix"; public const string PluginName = "TestPack Compatibility Fix"; public const string PluginVersion = "0.1.0"; internal static ManualLogSource ModLogger; private void Awake() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) ModLogger = ((BaseUnityPlugin)this).Logger; new Harmony("dieforlol1.testpack.compatibilityfix").PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"TestPack Compatibility Fix 0.1.0 loaded"); } } internal static class RagdollTagCompatibility { internal const string IndexedTagFormat = "PlayerRagdoll{0}"; internal const string GenericRagdollTag = "PlayerRagdoll"; internal static string FormatRagdollTag(string format, object playerIdValue) { if (format == "PlayerRagdoll{0}" && TryConvertPlayerId(playerIdValue, out var playerId) && playerId >= 4) { return "PlayerRagdoll"; } return string.Format(format, playerIdValue); } private static bool TryConvertPlayerId(object value, out int playerId) { try { playerId = Convert.ToInt32(value); return true; } catch { playerId = -1; return false; } } } [HarmonyPatch(typeof(DeadBodyInfo), "Start")] internal static class DeadBodyInfoStartPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo objB = AccessTools.Method(typeof(string), "Format", new Type[2] { typeof(string), typeof(object) }, (Type[])null); MethodInfo operand = AccessTools.Method(typeof(RagdollTagCompatibility), "FormatRagdollTag", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i < list.Count; i++) { CodeInstruction val = list[i]; bool flag = false; for (int j = Math.Max(0, i - 5); j < i; j++) { if (list[j].opcode == OpCodes.Ldstr && string.Equals(list[j].operand as string, "PlayerRagdoll{0}", StringComparison.Ordinal)) { flag = true; break; } } bool flag2 = (val.opcode == OpCodes.Call || val.opcode == OpCodes.Callvirt) && object.Equals(val.operand, objB); if (flag && flag2) { val.opcode = OpCodes.Call; val.operand = operand; num++; } } if (num != 1) { Plugin.ModLogger.LogError((object)("Ragdoll tag patch expected one replacement, got " + num + ".")); } return list; } } [HarmonyPatch(typeof(PlayerPhysicsRegion), "OnTriggerStay")] internal static class PlayerPhysicsRegionPatch { private static bool Prefix(PlayerPhysicsRegion __instance, Collider other) { if ((Object)(object)other == (Object)null || ((Component)other).gameObject.layer != 20 || ((Object)((Component)other).gameObject).name != "spine.002") { return true; } DeadBodyInfo componentInParent = ((Component)other).GetComponentInParent<DeadBodyInfo>(); if ((Object)(object)componentInParent == (Object)null || componentInParent.playerObjectId < 4) { return true; } if (!componentInParent.isParentedToPhysicsRegion) { componentInParent.SetPhysicsParent(__instance.physicsTransform, __instance.physicsCollider); } return false; } } internal static class RadarNameCompatibility { internal static void Repair(ManualCameraRenderer renderer, bool updateVisibleLabel) { if ((Object)(object)renderer == (Object)null || renderer.radarTargets == null) { return; } int num = 0; for (int i = 0; i < renderer.radarTargets.Count; i++) { TransformAndName val = renderer.radarTargets[i]; if (val != null && !((Object)(object)val.transform == (Object)null)) { PlayerControllerB component = ((Component)val.transform).gameObject.GetComponent<PlayerControllerB>(); if (!((Object)(object)component == (Object)null) && !string.IsNullOrEmpty(component.playerUsername) && !LabelBelongsToPlayer(val.name, component.playerUsername)) { val.name = component.playerUsername; num++; } } } if (num > 0) { Plugin.ModLogger.LogDebug((object)("Repaired " + num + " mismatched radar player name(s).")); } if (updateVisibleLabel && renderer.targetTransformIndex >= 0 && renderer.targetTransformIndex < renderer.radarTargets.Count && !((Object)(object)StartOfRound.Instance == (Object)null) && !((Object)(object)StartOfRound.Instance.mapScreenPlayerName == (Object)null)) { TransformAndName val2 = renderer.radarTargets[renderer.targetTransformIndex]; if (val2 != null) { ((TMP_Text)StartOfRound.Instance.mapScreenPlayerName).text = val2.name ?? string.Empty; } } } private static bool LabelBelongsToPlayer(string label, string username) { if (string.Equals(label, username, StringComparison.Ordinal)) { return true; } if (string.IsNullOrEmpty(label) || !label.StartsWith(username, StringComparison.Ordinal) || label.Length == username.Length) { return false; } for (int i = username.Length; i < label.Length; i++) { if (!char.IsDigit(label[i])) { return false; } } return true; } } [HarmonyPatch(typeof(PlayerControllerB), "SendNewPlayerValuesClientRpc")] internal static class NewPlayerValuesPatch { private static void Postfix() { if ((Object)(object)StartOfRound.Instance != (Object)null) { RadarNameCompatibility.Repair(StartOfRound.Instance.mapScreen, updateVisibleLabel: true); } } } [HarmonyPatch(typeof(ManualCameraRenderer), "SyncOrderOfRadarBoostersInList")] internal static class RadarOrderPatch { private static void Postfix(ManualCameraRenderer __instance) { RadarNameCompatibility.Repair(__instance, updateVisibleLabel: true); } } [HarmonyPatch(typeof(ManualCameraRenderer), "updateMapTarget")] internal static class UpdateMapTargetPatch { private static void Prefix(ManualCameraRenderer __instance) { RadarNameCompatibility.Repair(__instance, updateVisibleLabel: false); } } [HarmonyPatch(typeof(ManualCameraRenderer), "UpdateRadarTargetName")] internal static class UpdateRadarTargetNamePatch { private static void Prefix(ManualCameraRenderer __instance) { RadarNameCompatibility.Repair(__instance, updateVisibleLabel: false); } } [HarmonyPatch] internal static class FacilityMeltdownEnemyFilterPatch { private static readonly HashSet<string> LoggedEnemyNames = new HashSet<string>(StringComparer.Ordinal); private static bool Prepare() { return AccessTools.TypeByName("FacilityMeltdown.MeltdownSequence.Behaviours.MeltdownHandler+<>c__DisplayClass20_0") != null; } private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("FacilityMeltdown.MeltdownSequence.Behaviours.MeltdownHandler+<>c__DisplayClass20_0"); if (!(type == null)) { return AccessTools.Method(type, "<HandleEnemies>b__0", (Type[])null, (Type[])null); } return null; } private static bool Prefix(SpawnableEnemyWithRarity enemy, ref bool __result) { if (enemy == null || (Object)(object)enemy.enemyType == (Object)null) { __result = false; return false; } Type type = AccessTools.TypeByName("Dawn.EnemyTypeExtensions"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "GetDawnInfo", new Type[1] { typeof(EnemyType) }, (Type[])null)); if (methodInfo == null) { return true; } object obj; try { obj = methodInfo.Invoke(null, new object[1] { enemy.enemyType }); } catch (Exception ex) { Plugin.ModLogger.LogWarning((object)("Could not check FacilityMeltdown enemy metadata: " + ex.GetBaseException().Message)); __result = false; return false; } if (obj != null) { return true; } string text = (string.IsNullOrEmpty(enemy.enemyType.enemyName) ? ((Object)enemy.enemyType).name : enemy.enemyType.enemyName); if (LoggedEnemyNames.Add(text)) { Plugin.ModLogger.LogDebug((object)("FacilityMeltdown skipped enemy without Dawn metadata: " + text)); } __result = false; return false; } } [HarmonyPatch] internal static class FacilityMeltdownEmergencyLightsPatch { private static bool Prepare() { return AccessTools.TypeByName("FacilityMeltdown.MeltdownSequence.MeltdownEffects+<EmergencyLights>d__8") != null; } private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("FacilityMeltdown.MeltdownSequence.MeltdownEffects+<EmergencyLights>d__8"); if (!(type == null)) { return AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null); } return null; } private static bool Prefix(ref bool __result) { RoundManager instance = RoundManager.Instance; if ((Object)(object)instance == (Object)null || instance.allPoweredLightsAnimators == null) { __result = false; return false; } instance.allPoweredLightsAnimators.RemoveAll((Animator animator) => (Object)(object)animator == (Object)null); return true; } } [HarmonyPatch] internal static class TheCabinetFollowingStatePatch { private static FieldInfo ownerField; private static bool Prepare() { return AccessTools.TypeByName("TheCabinet.CabinetState_Following") != null; } private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("TheCabinet.CabinetState_Following"); if (type == null) { return null; } ownerField = AccessTools.Field(type.BaseType, "owner"); return AccessTools.Method(type, "ExecuteSlow", (Type[])null, (Type[])null); } private static bool Prefix(object __instance) { if (ownerField == null) { return true; } object? value = ownerField.GetValue(__instance); EnemyAI val = (EnemyAI)((value is EnemyAI) ? value : null); if ((Object)(object)val != (Object)null) { return (Object)(object)val.targetPlayer != (Object)null; } return false; } } [HarmonyPatch] internal static class CoronerGiantSapsuckerLogPatch { private static MethodInfo validatePlayerDead; private static bool Prepare() { if (AccessTools.TypeByName("Coroner.Patch.GiantKiwiAIAnimationEventBPatch") != null) { return AccessTools.TypeByName("Coroner.Patch.CauseOfDeathPatchState") != null; } return false; } private static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("Coroner.Patch.GiantKiwiAIAnimationEventBPatch"); Type type2 = AccessTools.TypeByName("Coroner.Patch.CauseOfDeathPatchState"); validatePlayerDead = ((type2 == null) ? null : AccessTools.Method(type2, "ValidateIsPlayerDead", new Type[1] { typeof(bool) }, (Type[])null)); if (!(type == null)) { return AccessTools.Method(type, "Postfix", (Type[])null, (Type[])null); } return null; } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; for (int i = 1; i < list.Count; i++) { CodeInstruction val = list[i]; if ((val.opcode == OpCodes.Call || val.opcode == OpCodes.Callvirt) && object.Equals(val.operand, validatePlayerDead) && list[i - 1].opcode == OpCodes.Ldc_I4_1) { list[i - 1].opcode = OpCodes.Ldc_I4_0; list[i - 1].operand = null; num++; } } if (num != 1) { Plugin.ModLogger.LogWarning((object)("Coroner Giant Sapsucker log patch expected one replacement, got " + num + ".")); } return list; } } [HarmonyPatch(typeof(PlayerControllerB), "DestroyItemInSlot")] internal static class DestroyItemInUtilitySlotPatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Expected O, but got Unknown //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(instructions); MethodInfo objB = AccessTools.PropertyGetter(typeof(HUDManager), "Instance"); FieldInfo objB2 = AccessTools.Field(typeof(HUDManager), "itemSlotIcons"); MethodInfo objB3 = AccessTools.PropertySetter(typeof(Behaviour), "enabled"); MethodInfo methodInfo = AccessTools.Method(typeof(DestroyItemInUtilitySlotPatch), "UpdateSlotIcon", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i + 5 < list.Count; i++) { if ((list[i].opcode == OpCodes.Call || list[i].opcode == OpCodes.Callvirt) && object.Equals(list[i].operand, objB) && list[i + 1].opcode == OpCodes.Ldfld && object.Equals(list[i + 1].operand, objB2) && list[i + 2].opcode == OpCodes.Ldarg_1 && list[i + 3].opcode == OpCodes.Ldelem_Ref && list[i + 4].opcode == OpCodes.Ldc_I4_0 && (list[i + 5].opcode == OpCodes.Call || list[i + 5].opcode == OpCodes.Callvirt) && object.Equals(list[i + 5].operand, objB3)) { CodeInstruction val = new CodeInstruction(OpCodes.Ldarg_1, (object)null); val.labels.AddRange(list[i].labels); val.blocks.AddRange(list[i].blocks); CodeInstruction val2 = new CodeInstruction(OpCodes.Call, (object)methodInfo); val2.labels.AddRange(list[i + 5].labels); val2.blocks.AddRange(list[i + 5].blocks); list.RemoveRange(i, 6); list.Insert(i, val2); list.Insert(i, val); num++; i++; } } if (num != 1) { Plugin.ModLogger.LogWarning((object)("Utility-slot icon patch expected one replacement, got " + num + ".")); } return list; } private static void UpdateSlotIcon(int itemSlot) { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return; } if (itemSlot == 50) { if ((Object)(object)instance.itemOnlySlotIcon != (Object)null) { ((Behaviour)instance.itemOnlySlotIcon).enabled = false; } } else if (instance.itemSlotIcons != null && itemSlot >= 0 && itemSlot < instance.itemSlotIcons.Length && (Object)(object)instance.itemSlotIcons[itemSlot] != (Object)null) { ((Behaviour)instance.itemSlotIcons[itemSlot]).enabled = false; } } }
plugins/Taborusic/Taborusic.SonicThumperCompat.dll
Decompiled a month agousing System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Unity.Netcode; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: ComVisible(false)] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyVersion("1.1.0.0")] namespace Taborusic.SonicThumperCompat; [BepInPlugin("Dieforl0l.Taborusic.SonicThumperCompat", "Taborusic SonicThumper Compatibility", "1.1.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { private sealed class RemovedPostfix { internal MethodBase Target; internal string Owner; internal HarmonyMethod Method; } public const string PluginGuid = "Dieforl0l.Taborusic.SonicThumperCompat"; public const string PluginName = "Taborusic SonicThumper Compatibility"; public const string PluginVersion = "1.1.0"; internal const float DefaultChaseVolume = 0.32f; private static Plugin instance; private readonly HashSet<ChaseAudioLifecycle> activeSources = new HashSet<ChaseAudioLifecycle>(); private readonly List<RemovedPostfix> removedPostfixes = new List<RemovedPostfix>(); private FieldInfo angeredAudioField; private FieldInfo rpcExecStageField; private ConfigEntry<float> chaseVolume; private Harmony harmony; private bool ready; internal float Volume => NormalizeVolume((chaseVolume == null) ? 0.32f : chaseVolume.Value); internal static float NormalizeVolume(float value) { if (float.IsNaN(value) || float.IsInfinity(value)) { return 0.32f; } return Math.Max(0f, Math.Min(1f, value)); } private void Awake() { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown chaseVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "ChaseVolume", 0.32f, new ConfigDescription("Local Sonic chase music volume; 0 mutes it. Applied to active sources on the next frame.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0])); harmony = new Harmony("Dieforl0l.Taborusic.SonicThumperCompat"); try { Type type = AccessTools.TypeByName("SonicThumper.Plugin"); Type type2 = AccessTools.TypeByName("SonicThumper.Patches.SonicThumperPatch"); MethodInfo methodInfo = AccessTools.Method(typeof(CrawlerAI), "BeginChasingPlayerClientRpc", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(CrawlerAI), "EatPlayerBodyClientRpc", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(CrawlerAI), "Start", (Type[])null, (Type[])null); MethodInfo methodInfo4 = AccessTools.Method(typeof(CrawlerAI), "KillEnemy", (Type[])null, (Type[])null); angeredAudioField = ((type == null) ? null : AccessTools.Field(type, "AngeredAudio")); rpcExecStageField = AccessTools.Field(typeof(CrawlerAI), "__rpc_exec_stage"); if (type2 == null || angeredAudioField == null || !angeredAudioField.IsStatic || angeredAudioField.FieldType != typeof(AudioClip) || methodInfo == null || methodInfo2 == null || methodInfo3 == null || methodInfo4 == null || methodInfo4.DeclaringType != typeof(CrawlerAI) || rpcExecStageField == null || !rpcExecStageField.FieldType.IsEnum || Convert.ToInt32(Enum.Parse(rpcExecStageField.FieldType, "Execute")) != 1) { throw new InvalidOperationException("Required SonicThumper/v81 CrawlerAI members were not found; no replacements applied."); } List<Patch> list = FindSonicPostfixes(methodInfo, type2, "StartSonicSound"); List<Patch> list2 = FindSonicPostfixes(methodInfo2, type2, "StopSonicSound"); if (list.Count == 0 || list2.Count == 0) { throw new InvalidOperationException("Expected SonicThumper sound postfixes were not found; refusing a partial replacement."); } RemoveSonicPostfixes(methodInfo, list); RemoveSonicPostfixes(methodInfo2, list2); harmony.Patch((MethodBase)methodInfo, PatchMethod("SoundRpcPrefix"), PatchMethod("BeginChasingPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo2, PatchMethod("SoundRpcPrefix"), PatchMethod("EatPlayerPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, PatchMethod("CrawlerKilledPostfix"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); HarmonyMethod val = PatchMethod("CrawlerStartPrefix"); val.priority = 800; HarmonyMethod val2 = PatchMethod("CrawlerStartPostfix"); val2.priority = 0; harmony.Patch((MethodBase)methodInfo3, val, val2, (HarmonyMethod)null, PatchMethod("CrawlerStartFinalizer"), (HarmonyMethod)null); instance = this; ready = true; SceneManager.sceneUnloaded += OnSceneUnloaded; ((BaseUnityPlugin)this).Logger.LogInfo((object)("SonicThumper compatibility 1.1.0 ready: ChaseVolume=" + Volume + "; per-crawler lifecycle/anti-stacking; SoundAPI BitePlayer preserved; chase is local 3D only (no uncancellable radio one-shot).")); } catch (Exception ex) { Shutdown(); ((BaseUnityPlugin)this).Logger.LogError((object)("SonicThumper compatibility was not enabled: " + ex)); } } private static HarmonyMethod PatchMethod(string name) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown return new HarmonyMethod(AccessTools.Method(typeof(Plugin), name, (Type[])null, (Type[])null)); } private static List<Patch> FindSonicPostfixes(MethodBase target, Type type, string name) { Patches patchInfo = Harmony.GetPatchInfo(target); if (patchInfo != null) { return patchInfo.Postfixes.Where((Patch p) => p.PatchMethod != null && p.PatchMethod.DeclaringType == type && p.PatchMethod.Name == name).ToList(); } return new List<Patch>(); } private void RemoveSonicPostfixes(MethodBase target, List<Patch> patches) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown foreach (Patch patch in patches) { List<RemovedPostfix> list = removedPostfixes; RemovedPostfix removedPostfix = new RemovedPostfix { Target = target, Owner = patch.owner }; HarmonyMethod val = new HarmonyMethod(patch.PatchMethod); val.priority = patch.priority; val.before = patch.before; val.after = patch.after; val.debug = patch.debug; val.wrapTryCatch = patch.wrapTryCatch; removedPostfix.Method = val; list.Add(removedPostfix); harmony.Unpatch(target, patch.PatchMethod); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Replaced " + patches.Count + " SonicThumper postfix(es) on " + target.Name + ".")); } private static void CrawlerStartPrefix(CrawlerAI __instance, out AudioClip __state) { __state = (((Object)(object)__instance == (Object)null) ? null : __instance.bitePlayerSFX); } private static void CrawlerStartPostfix(CrawlerAI __instance, AudioClip __state) { if ((Object)(object)__instance != (Object)null && (Object)(object)__state != (Object)null) { __instance.bitePlayerSFX = __state; } } private static Exception CrawlerStartFinalizer(CrawlerAI __instance, AudioClip __state, Exception __exception) { if (__exception != null) { CrawlerStartPostfix(__instance, __state); } return __exception; } private static void SoundRpcPrefix(CrawlerAI __instance, out bool __state) { Plugin plugin = instance; __state = (Object)(object)plugin != (Object)null && plugin.ready && (Object)(object)__instance != (Object)null && ((NetworkBehaviour)__instance).IsClient && ((NetworkBehaviour)__instance).IsSpawned && (Object)(object)((NetworkBehaviour)__instance).NetworkManager != (Object)null && ((NetworkBehaviour)__instance).NetworkManager.IsListening && Convert.ToInt32(plugin.rpcExecStageField.GetValue(__instance)) == 1; } private static void BeginChasingPostfix(CrawlerAI __instance, bool __state) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown Plugin plugin = instance; if (!__state || (Object)(object)plugin == (Object)null || !plugin.ready || (Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsClient || !((NetworkBehaviour)__instance).IsSpawned || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).currentBehaviourStateIndex != 1) { return; } object? value = plugin.angeredAudioField.GetValue(null); AudioClip val = (AudioClip)((value is AudioClip) ? value : null); if ((Object)(object)val == (Object)null || (Object)(object)plugin.FindSource(__instance) != (Object)null) { return; } GameObject val2 = new GameObject("TaborusicSonicChaseAudio"); ChaseAudioLifecycle chaseAudioLifecycle = null; try { val2.transform.SetParent(((Component)__instance).transform, false); chaseAudioLifecycle = val2.AddComponent<ChaseAudioLifecycle>(); chaseAudioLifecycle.Initialize(plugin, __instance, val); } catch (Exception ex) { if ((Object)(object)chaseAudioLifecycle != (Object)null) { chaseAudioLifecycle.Release("initialization-failed"); } else { Object.Destroy((Object)(object)val2); } ((BaseUnityPlugin)plugin).Logger.LogError((object)("Could not create isolated Sonic chase source: " + ex)); } } private static void EatPlayerPostfix(CrawlerAI __instance, bool __state) { if (__state && (Object)(object)instance != (Object)null) { instance.StopCrawler(__instance, "eat"); } } private static void CrawlerKilledPostfix(CrawlerAI __instance) { if ((Object)(object)instance != (Object)null && (Object)(object)__instance != (Object)null && ((EnemyAI)__instance).isEnemyDead) { instance.StopCrawler(__instance, "death"); } } private ChaseAudioLifecycle FindSource(CrawlerAI crawler) { foreach (ChaseAudioLifecycle activeSource in activeSources) { if ((Object)(object)activeSource != (Object)null && (Object)(object)activeSource.Owner == (Object)(object)crawler) { return activeSource; } } return null; } private void StopCrawler(CrawlerAI crawler, string reason) { if (!((Object)(object)crawler == (Object)null)) { ChaseAudioLifecycle chaseAudioLifecycle = FindSource(crawler); if ((Object)(object)chaseAudioLifecycle != (Object)null) { chaseAudioLifecycle.Release(reason); } } } internal void Register(ChaseAudioLifecycle source) { activeSources.Add(source); ((BaseUnityPlugin)this).Logger.LogDebug((object)("Sonic chase created; active=" + activeSources.Count)); } internal void Unregister(ChaseAudioLifecycle source, string reason) { activeSources.Remove(source); ((BaseUnityPlugin)this).Logger.LogDebug((object)("Sonic chase released (" + reason + "); active=" + activeSources.Count)); } private void OnSceneUnloaded(Scene scene) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) foreach (ChaseAudioLifecycle item in new List<ChaseAudioLifecycle>(activeSources)) { if (!((Object)(object)item != (Object)null)) { continue; } if (!((Object)(object)item.Owner == (Object)null)) { Scene scene2 = ((Component)item.Owner).gameObject.scene; if (((Scene)(ref scene2)).handle != ((Scene)(ref scene)).handle) { continue; } } item.Release("scene-unloaded"); } } private void OnDestroy() { Shutdown(); } private void Shutdown() { //IL_0112: Unknown result type (might be due to invalid IL or missing references) ready = false; if (object.ReferenceEquals(instance, this)) { instance = null; } SceneManager.sceneUnloaded -= OnSceneUnloaded; foreach (ChaseAudioLifecycle item in new List<ChaseAudioLifecycle>(activeSources)) { if ((Object)(object)item != (Object)null) { item.Release("plugin-shutdown"); } } activeSources.Clear(); angeredAudioField = null; rpcExecStageField = null; if (harmony != null) { harmony.UnpatchSelf(); } foreach (RemovedPostfix removed in removedPostfixes) { try { Patches patchInfo = Harmony.GetPatchInfo(removed.Target); if (patchInfo == null || !patchInfo.Postfixes.Any((Patch p) => p.owner == removed.Owner && p.PatchMethod == removed.Method.method)) { new Harmony(removed.Owner).Patch(removed.Target, (HarmonyMethod)null, removed.Method, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Could not restore original Sonic postfix: " + ex)); } } removedPostfixes.Clear(); } } public sealed class ChaseAudioLifecycle : MonoBehaviour { private Plugin plugin; private AudioSource source; private bool released; internal CrawlerAI Owner { get; private set; } internal void Initialize(Plugin ownerPlugin, CrawlerAI crawler, AudioClip clip) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Invalid comparison between Unknown and I4 plugin = ownerPlugin; Owner = crawler; source = ((Component)this).gameObject.AddComponent<AudioSource>(); source.playOnAwake = false; source.loop = false; source.volume = plugin.Volume; AudioSource creatureSFX = ((EnemyAI)crawler).creatureSFX; if ((Object)(object)creatureSFX != (Object)null) { source.outputAudioMixerGroup = creatureSFX.outputAudioMixerGroup; source.spatialBlend = creatureSFX.spatialBlend; source.spatialize = creatureSFX.spatialize; source.dopplerLevel = creatureSFX.dopplerLevel; source.spread = creatureSFX.spread; source.rolloffMode = creatureSFX.rolloffMode; source.minDistance = creatureSFX.minDistance; source.maxDistance = creatureSFX.maxDistance; source.priority = creatureSFX.priority; if ((int)creatureSFX.rolloffMode == 2) { source.SetCustomCurve((AudioSourceCurveType)0, creatureSFX.GetCustomCurve((AudioSourceCurveType)0)); } } source.clip = clip; plugin.Register(this); source.Play(); } private void LateUpdate() { if (!released) { if ((Object)(object)Owner == (Object)null || (Object)(object)plugin == (Object)null) { Release("owner-destroyed"); } else if (((EnemyAI)Owner).isEnemyDead) { Release("death"); } else if (!((NetworkBehaviour)Owner).IsSpawned) { Release("despawn"); } else if (((EnemyAI)Owner).currentBehaviourStateIndex != 1) { Release("chase-ended"); } else if ((Object)(object)source == (Object)null || !source.isPlaying) { Release("clip-finished"); } else { source.volume = plugin.Volume; } } } private void OnDisable() { Release("disabled"); } private void OnDestroy() { Release("destroyed"); } internal void Release(string reason) { if (!released) { released = true; if ((Object)(object)source != (Object)null) { source.Stop(); source.clip = null; } source = null; Plugin plugin = this.plugin; this.plugin = null; Owner = null; if ((Object)(object)plugin != (Object)null) { plugin.Unregister(this, reason); } if ((Object)(object)((Component)this).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } }