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 EnemySoundFixes v1.9.6
EnemySoundFixes.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DunGen; using DunGen.Graph; using GameNetcodeStuff; using HarmonyLib; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.Audio; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("EnemySoundFixes")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Fixes numerous issues with missing sound effects, or SFX playing when they shouldn't.")] [assembly: AssemblyFileVersion("1.9.6.0")] [assembly: AssemblyInformationalVersion("1.9.6+8879bdbb1fcb54dc212a91af8a6789ee4048eaf6")] [assembly: AssemblyProduct("EnemySoundFixes")] [assembly: AssemblyTitle("EnemySoundFixes")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.9.6.0")] [module: UnverifiableCode] [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 EnemySoundFixes { internal static class LobbyCompatibility { internal static void Init() { PluginHelper.RegisterPlugin("butterystancakes.lethalcompany.enemysoundfixes", Version.Parse("1.9.6"), (CompatibilityLevel)0, (VersionStrictness)0); } } internal enum CruiserMute { Nothing = -1, NotRadio, All } [BepInPlugin("butterystancakes.lethalcompany.enemysoundfixes", "Enemy Sound Fixes", "1.9.6")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal const string PLUGIN_GUID = "butterystancakes.lethalcompany.enemysoundfixes"; internal const string PLUGIN_NAME = "Enemy Sound Fixes"; internal const string PLUGIN_VERSION = "1.9.6"; internal static ManualLogSource Logger; internal static ConfigEntry<bool> configThumperNoThunder; internal static ConfigEntry<bool> configBetterMimicSteps; internal static ConfigEntry<bool> configFixDoorSounds; internal static ConfigEntry<bool> configShootTheDog; internal static ConfigEntry<bool> configEclipsesBlockMusic; internal static ConfigEntry<bool> configWalkieHearsTalkies; internal static ConfigEntry<CruiserMute> configSpaceMutesCruiser; internal static ConfigEntry<float> configMusicDopplerLevel; private const string GUID_LOBBY_COMPATIBILITY = "BMX.LobbyCompatibility"; private const string GUID_SOUND_API = "me.loaforc.soundapi"; private const string GUID_UPTURNED_VARIETY = "butterystancakes.lethalcompany.upturnedvariety"; internal static bool INSTALLED_SOUND_API; internal static bool INSTALLED_UPTURNED_VARIETY; private void Awake() { //IL_0214: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; if (Chainloader.PluginInfos.ContainsKey("BMX.LobbyCompatibility")) { Logger.LogInfo((object)"CROSS-COMPATIBILITY - Lobby Compatibility detected"); LobbyCompatibility.Init(); } if (Chainloader.PluginInfos.ContainsKey("me.loaforc.soundapi")) { INSTALLED_SOUND_API = true; Logger.LogInfo((object)"CROSS-COMPATIBILITY - loaforcsSoundAPI detected"); } if (Chainloader.PluginInfos.ContainsKey("butterystancakes.lethalcompany.upturnedvariety")) { INSTALLED_UPTURNED_VARIETY = true; Logger.LogInfo((object)"CROSS-COMPATIBILITY - Upturned Variety detected"); } configBetterMimicSteps = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "BetterMimicSteps", true, "Mimic footstep volume and distance are altered to sound more accurate to actual players."); configThumperNoThunder = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "ThumperNoThunder", true, "Thumpers no longer play thunder sound effects from their voice when they stop chasing after players."); configShootTheDog = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "ShootTheDog", true, "Makes eyeless dogs play their stun sound effect on death, rather than falling silently."); configSpaceMutesCruiser = ((BaseUnityPlugin)this).Config.Bind<CruiserMute>("Misc", "SpaceMutesCruiser", CruiserMute.NotRadio, "What audio sources should be muted on the Cruiser when in orbit. (Engine sounds, the horn, the radio, etc.)"); configFixDoorSounds = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "FixDoorSounds", true, "Fixes backwards open/close sounds on breaker boxes and storage locker doors. Fixes Rend and Adamance cabin doors using steel door sounds."); configEclipsesBlockMusic = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "EclipsesBlockMusic", true, "Prevents the morning/afternoon ambience music from playing during Eclipsed weather, which has its own ambient track."); configMusicDopplerLevel = ((BaseUnityPlugin)this).Config.Bind<float>("Misc", "MusicDopplerLevel", 0.333f, "Controls how much Unity's simulated \"Doppler effect\" applies to music sources like the dropship, boombox, etc. (This is what causes pitch distortion when moving towards/away from the source of the music)\n1 is the same as vanilla. 0 will disable it completely (so music always plays at the correct pitch)"); configWalkieHearsTalkies = ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "WalkieHearsTalkies", true, "Restores a cut sound effect of idle chatter when walkie-talkies are in use. Only audible when standing near a walkie-talkie that is turned on, someone is transmitting their voice, and you do not have a walkie-talkie turned on in your inventory. (This does *not* actually repeat what is being spoken over the line - it's just SFX)"); ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "DontFixMasks", false, "Legacy setting, doesn't work"); ((BaseUnityPlugin)this).Config.Remove(((BaseUnityPlugin)this).Config["Misc", "DontFixMasks"].Definition); ((BaseUnityPlugin)this).Config.Bind<bool>("Misc", "FixMasks", true, "Legacy setting, doesn't work"); ((BaseUnityPlugin)this).Config.Remove(((BaseUnityPlugin)this).Config["Misc", "FixMasks"].Definition); ((BaseUnityPlugin)this).Config.Save(); new Harmony("butterystancakes.lethalcompany.enemysoundfixes").PatchAll(); Logger.LogInfo((object)"Enemy Sound Fixes v1.9.6 loaded"); } } public class RadioChatter : MonoBehaviour { internal WalkieTalkie walkieTalkie; private AudioSource audio; private void Awake() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) audio = new GameObject("EnemySoundFixes_WalkieTalkieTalkingNotHeld").AddComponent<AudioSource>(); ((Component)audio).transform.SetParent(((Component)this).transform, false); audio.clip = ((Component)this).GetComponent<WalkieTalkie>().talkingOnWalkieTalkieNotHeldSFX; audio.loop = true; AudioSource component = ((Component)this).GetComponent<AudioSource>(); audio.outputAudioMixerGroup = component.outputAudioMixerGroup; audio.SetCustomCurve((AudioSourceCurveType)1, component.GetCustomCurve((AudioSourceCurveType)1)); audio.dopplerLevel = component.dopplerLevel; audio.spread = component.spread; audio.rolloffMode = (AudioRolloffMode)2; audio.SetCustomCurve((AudioSourceCurveType)0, component.GetCustomCurve((AudioSourceCurveType)0)); audio.maxDistance = component.maxDistance; } private void Update() { if ((Object)(object)walkieTalkie == (Object)null) { walkieTalkie = ((Component)this).GetComponent<WalkieTalkie>(); if ((Object)(object)walkieTalkie == (Object)null) { ((Behaviour)this).enabled = false; return; } } if (!((GrabbableObject)walkieTalkie).isBeingUsed || !Plugin.configWalkieHearsTalkies.Value) { SetPlaying(play: false); } else { if ((Object)(object)GameNetworkManager.Instance?.localPlayerController == (Object)null) { return; } if (GameNetworkManager.Instance.localPlayerController.holdingWalkieTalkie || (GameNetworkManager.Instance.localPlayerController.isPlayerDead && (Object)(object)GameNetworkManager.Instance.localPlayerController.spectatedPlayerScript != (Object)null && GameNetworkManager.Instance.localPlayerController.spectatedPlayerScript.holdingWalkieTalkie)) { SetPlaying(play: false); return; } bool playing = false; for (int i = 0; i < StartOfRound.Instance.allPlayerScripts.Length; i++) { if (StartOfRound.Instance.allPlayerScripts[i].holdingWalkieTalkie && StartOfRound.Instance.allPlayerScripts[i].speakingToWalkieTalkie && !((Object)(object)StartOfRound.Instance.allPlayerScripts[i].currentlyHeldObjectServer != (Object)(object)walkieTalkie)) { playing = true; break; } } SetPlaying(playing); } } public void SetPlaying(bool play) { if ((Object)(object)audio == (Object)null) { return; } if (play) { if (!audio.isPlaying) { audio.pitch = Random.Range(0.94f, 1.06f); audio.Play(); audio.time = Random.Range(0f, audio.clip.length - 0.1f); } } else if (audio.isPlaying) { audio.Stop(); } } private void OnDisable() { SetPlaying(play: false); } } internal class References { internal static readonly FieldInfo CREATURE_VOICE = AccessTools.Field(typeof(EnemyAI), "creatureVoice"); internal static readonly FieldInfo IS_ENEMY_DEAD = AccessTools.Field(typeof(EnemyAI), "isEnemyDead"); internal static readonly FieldInfo ENGINE_AUDIO_1 = AccessTools.Field(typeof(VehicleController), "engineAudio1"); internal static readonly MethodInfo REALTIME_SINCE_STARTUP = AccessTools.DeclaredPropertyGetter(typeof(Time), "realtimeSinceStartup"); internal static readonly MethodInfo PLAY_ONE_SHOT = AccessTools.Method(typeof(AudioSource), "PlayOneShot", new Type[1] { typeof(AudioClip) }, (Type[])null); internal static readonly MethodInfo STOP = AccessTools.Method(typeof(AudioSource), "Stop", Array.Empty<Type>(), (Type[])null); internal static readonly MethodInfo DAMAGE_PLAYER = AccessTools.Method(typeof(PlayerControllerB), "DamagePlayer", (Type[])null, (Type[])null); internal static readonly MethodInfo HIT_ENEMY = AccessTools.Method(typeof(EnemyAI), "HitEnemy", (Type[])null, (Type[])null); internal static readonly MethodInfo PLAY_RANDOM_CLIP = AccessTools.Method(typeof(RoundManager), "PlayRandomClip", (Type[])null, (Type[])null); internal static AudioClip baboonTakeDamage; internal static AudioClip hitEnemyBody; internal static AudioClip[] woodenDoorOpen; internal static AudioClip[] woodenDoorClose; internal static AudioClip cruiserDashboardButton; internal static AudioMixerGroup sfx; } public static class PluginInfo { public const string PLUGIN_GUID = "EnemySoundFixes"; public const string PLUGIN_NAME = "EnemySoundFixes"; public const string PLUGIN_VERSION = "1.9.6"; } } namespace EnemySoundFixes.Patches { [HarmonyPatch(typeof(VehicleController))] internal static class CruiserPatches { [CompilerGenerated] private sealed class <TwistKey>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public VehicleController vehicleController; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TwistKey>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.85f); <>1__state = 1; return true; case 1: <>1__state = -1; if (vehicleController.keyIgnitionCoroutine != null && (Object)(object)vehicleController.currentDriver != (Object)null) { vehicleController.currentDriver.movementAudio.PlayOneShot(vehicleController.twistKey); } twistingKey = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static Coroutine twistingKey; [HarmonyPatch("RevCarClientRpc")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPatch("SetIgnition")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> VehicleController_Trans_EngineRev(IEnumerable<CodeInstruction> instructions) { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); for (int i = 4; i < list.Count; i++) { if (list[i].opcode == OpCodes.Callvirt && (MethodInfo)list[i].operand == References.PLAY_ONE_SHOT && list[i - 3].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 3].operand == References.ENGINE_AUDIO_1) { list.InsertRange(i - 4, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(list[i - 4].opcode, list[i - 4].operand), new CodeInstruction(OpCodes.Ldfld, (object)References.ENGINE_AUDIO_1), new CodeInstruction(OpCodes.Callvirt, (object)References.STOP) })); Plugin.Logger.LogDebug((object)"Transpiler (Cruiser): Reset engine rev sounds"); return list; } } Plugin.Logger.LogError((object)"Cruiser transpiler failed"); return list; } [HarmonyPatch("SetVehicleAudioProperties")] [HarmonyPrefix] private static void VehicleController_Pre_SetVehicleAudioProperties(VehicleController __instance, AudioSource audio, ref bool audioActive) { if (audioActive && (((Object)(object)audio == (Object)(object)__instance.extremeStressAudio && __instance.magnetedToShip) || (((Object)(object)audio == (Object)(object)__instance.rollingAudio || (Object)(object)audio == (Object)(object)__instance.skiddingAudio) && (__instance.magnetedToShip || (!__instance.FrontLeftWheel.isGrounded && !__instance.FrontRightWheel.isGrounded && !__instance.BackLeftWheel.isGrounded && !__instance.BackRightWheel.isGrounded))))) { audioActive = false; } } [HarmonyPatch("SetVehicleAudioProperties")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> VehicleController_Trans_SetVehicleAudioProperties(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.DeclaredPropertyGetter(typeof(AudioSource), "volume"); for (int i = 0; i < list.Count - 2; i++) { if (list[i].opcode == OpCodes.Callvirt && (MethodInfo)list[i].operand == methodInfo && list[i + 1].opcode == OpCodes.Ldc_R4 && (float)list[i + 1].operand == 0f && list[i - 2].opcode == OpCodes.Bne_Un) { list[i + 1].operand = 0.001f; list[i + 2].opcode = OpCodes.Bge; Plugin.Logger.LogDebug((object)"Transpiler (Cruiser): Stop audio source when volume is close enough to zero"); break; } } return list; } [HarmonyPatch("LateUpdate")] [HarmonyPostfix] private static void VehicleController_Post_LateUpdate(VehicleController __instance) { if (__instance.magnetedToShip && (StartOfRound.Instance.inShipPhase || !StartOfRound.Instance.shipDoorsEnabled) && Plugin.configSpaceMutesCruiser.Value > CruiserMute.Nothing) { __instance.hornAudio.mute = true; __instance.engineAudio1.mute = true; __instance.engineAudio2.mute = true; __instance.turbulenceAudio.mute = true; if (Plugin.configSpaceMutesCruiser.Value == CruiserMute.NotRadio) { __instance.radioAudio.mute = false; __instance.radioInterference.mute = false; } else { __instance.radioAudio.mute = true; __instance.radioInterference.mute = true; } __instance.pushAudio.mute = true; } else { __instance.hornAudio.mute = false; __instance.engineAudio1.mute = false; __instance.engineAudio2.mute = false; __instance.turbulenceAudio.mute = false; __instance.radioAudio.mute = false; __instance.radioInterference.mute = false; __instance.pushAudio.mute = false; } if (twistingKey != null && __instance.keyIgnitionCoroutine == null) { ((MonoBehaviour)__instance).StopCoroutine(twistingKey); twistingKey = null; } if (__instance.honkingHorn && __instance.hornAudio.isPlaying && __instance.hornAudio.pitch < 1f) { __instance.hornAudio.Stop(); } } [HarmonyPatch("TryIgnition")] [HarmonyPrefix] private static void VehicleController_Pre_TryIgnition(VehicleController __instance, bool isLocalDriver) { if (!__instance.keyIsInIgnition && isLocalDriver && __instance.vehicleID == 0) { if (twistingKey != null) { ((MonoBehaviour)__instance).StopCoroutine(twistingKey); } twistingKey = ((MonoBehaviour)__instance).StartCoroutine(TwistKey(__instance)); } } [IteratorStateMachine(typeof(<TwistKey>d__6))] private static IEnumerator TwistKey(VehicleController vehicleController) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TwistKey>d__6(0) { vehicleController = vehicleController }; } [HarmonyPatch("Awake")] [HarmonyPrefix] private static void VehicleController_Post_Awake(VehicleController __instance) { if (__instance.vehicleID != 0 || (Object)(object)References.cruiserDashboardButton == (Object)null || (Object)(object)References.sfx == (Object)null) { return; } Transform val = ((Component)__instance).transform.Find("Triggers"); if (!((Object)(object)val != (Object)null)) { return; } Transform[] array = (Transform[])(object)new Transform[2] { val.Find("ChangeChannel (1)"), val.Find("ChangeChannel (2)") }; InteractTrigger val3 = default(InteractTrigger); foreach (Transform val2 in array) { if (!((Object)(object)val2 == (Object)null) && ((Component)val2).TryGetComponent<InteractTrigger>(ref val3) && !((Object)(object)((Component)val2).GetComponent<AudioSource>() != (Object)null)) { AudioSource audioSource = ((Component)val3).gameObject.AddComponent<AudioSource>(); audioSource.clip = References.cruiserDashboardButton; audioSource.outputAudioMixerGroup = References.sfx; audioSource.spatialBlend = 1f; audioSource.spread = 33f; audioSource.rolloffMode = (AudioRolloffMode)1; audioSource.minDistance = 4f; audioSource.maxDistance = 15f; ((UnityEvent<PlayerControllerB>)(object)val3.onInteract).AddListener((UnityAction<PlayerControllerB>)delegate { audioSource.Play(); }); Plugin.Logger.LogDebug((object)("Cruiser: Dashboard button (\"" + ((Object)val2).name + "\")")); } } } } [HarmonyPatch(typeof(DoorLock))] internal static class DoorPatches { [HarmonyPatch("UnlockDoor")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> DoorLock_Trans_UnlockDoor(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); bool flag = false; bool flag2 = false; MethodInfo methodInfo = AccessTools.Method(typeof(AudioSource), "Stop", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(AudioSource), "PlayOneShot", new Type[1] { typeof(AudioClip) }, (Type[])null); FieldInfo fieldInfo = AccessTools.Field(typeof(DoorLock), "doorLockSFX"); for (int i = 2; i < list.Count && !(list[i].opcode == OpCodes.Brtrue) && !(list[i].opcode == OpCodes.Brtrue_S); i++) { if (list[i].opcode == OpCodes.Callvirt) { MethodInfo methodInfo3 = list[i].operand as MethodInfo; if (!flag && methodInfo3 == methodInfo && list[i - 1].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 1].operand == fieldInfo) { list.RemoveRange(i - 2, 3); i -= 3; flag = true; Plugin.Logger.LogDebug((object)"Transpiler (Door): Don't stop SFX"); } else if (!flag2 && methodInfo3 == methodInfo2 && i >= 4 && list[i - 3].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 3].operand == fieldInfo) { list.RemoveRange(i - 4, 5); i -= 5; flag2 = true; Plugin.Logger.LogDebug((object)"Transpiler (Door): Don't play unlock SFX"); } } } if (!flag || !flag2) { Plugin.Logger.LogError((object)"Door transpiler failed"); } return list; } [HarmonyPatch("UnlockDoor")] [HarmonyPrefix] private static void DoorLock_Pre_UnlockDoor(DoorLock __instance, ref bool __state) { __state = __instance.isLocked; } [HarmonyPatch("UnlockDoor")] [HarmonyPostfix] private static void DoorLock_Post_UnlockDoor(DoorLock __instance, bool __state) { if (__state && !__instance.isLocked) { __instance.doorLockSFX.Stop(); __instance.doorLockSFX.PlayOneShot(__instance.unlockSFX); } } } [HarmonyPatch] internal static class GeneralPatches { internal static bool playHitSound; private static bool patchedDoorSfx; [HarmonyPatch(typeof(QuickMenuManager), "Start")] [HarmonyPostfix] private static void QuickMenuManager_Post_Start(QuickMenuManager __instance) { AudioClip val = null; try { AssetBundle obj = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "enemysoundfixes")); val = obj.LoadAsset<AudioClip>("StunFlowerman"); obj.Unload(false); } catch { Plugin.Logger.LogError((object)"Encountered some error loading assets from bundle \"enemysoundfixes\". Did you install the plugin correctly?"); } List<SpawnableEnemyWithRarity> enemies = __instance.testAllEnemiesLevel.Enemies; List<SpawnableEnemyWithRarity> outsideEnemies = __instance.testAllEnemiesLevel.OutsideEnemies; List<SpawnableEnemyWithRarity> daytimeEnemies = __instance.testAllEnemiesLevel.DaytimeEnemies; List<SpawnableEnemyWithRarity> list = new List<SpawnableEnemyWithRarity>(enemies.Count + outsideEnemies.Count + daytimeEnemies.Count); list.AddRange(enemies); list.AddRange(outsideEnemies); list.AddRange(daytimeEnemies); EnemyType val2 = null; EnemyType val3 = null; foreach (SpawnableEnemyWithRarity item in list) { switch (((Object)item.enemyType).name) { case "BaboonHawk": if ((Object)(object)References.baboonTakeDamage == (Object)null) { References.baboonTakeDamage = item.enemyType.hitBodySFX; Plugin.Logger.LogDebug((object)"Cached baboon hawk damage sound"); } item.enemyType.hitBodySFX = null; Plugin.Logger.LogDebug((object)"Overwritten baboon hawk damage sound"); ((EnemyAI)item.enemyType.enemyPrefab.GetComponent<BaboonBirdAI>()).dieSFX = item.enemyType.deathSFX; Plugin.Logger.LogDebug((object)"Overwritten missing baboon hawk death sound"); break; case "CadaverGrowths": item.enemyType.timeToPlayAudio = 1f; item.enemyType.loudnessMultiplier = 0.1f; Plugin.Logger.LogDebug((object)"Adjust cadaver vent sounds"); break; case "CaveDweller": { CaveDwellerAI component2 = item.enemyType.enemyPrefab.GetComponent<CaveDwellerAI>(); component2.clickingAudio1.volume = 0f; component2.clickingAudio2.volume = 0f; Plugin.Logger.LogDebug((object)"Fix maneater clicking volume"); break; } case "Centipede": ((EnemyAI)item.enemyType.enemyPrefab.GetComponent<CentipedeAI>()).creatureSFX.loop = true; Plugin.Logger.LogDebug((object)"Loop snare flea walking and clinging"); break; case "Crawler": if (Plugin.configThumperNoThunder.Value) { EnemyBehaviourState val5 = ((IEnumerable<EnemyBehaviourState>)((EnemyAI)item.enemyType.enemyPrefab.GetComponent<CrawlerAI>()).enemyBehaviourStates).FirstOrDefault((Func<EnemyBehaviourState, bool>)((EnemyBehaviourState enemyBehaviourState) => enemyBehaviourState.name == "searching")); if (val5 != null) { val5.VoiceClip = null; val5.playOneShotVoice = false; Plugin.Logger.LogDebug((object)"Remove thunder sound from thumper"); } } break; case "Flowerman": if ((Object)(object)val != (Object)null) { item.enemyType.stunSFX = val; Plugin.Logger.LogDebug((object)"Fix bracken stun sound"); } break; case "ForestGiant": { ForestGiantAI component3 = item.enemyType.enemyPrefab.GetComponent<ForestGiantAI>(); ((EnemyAI)component3).creatureSFX.spatialBlend = 1f; Plugin.Logger.LogDebug((object)"Fix forest giant global audio volume"); item.enemyType.hitBodySFX = ((IEnumerable<FootstepSurface>)StartOfRound.Instance.footstepSurfaces).FirstOrDefault((Func<FootstepSurface, bool>)((FootstepSurface footstepSurface) => footstepSurface.surfaceTag == "Wood")).hitSurfaceSFX; Plugin.Logger.LogDebug((object)"Overwritten missing forest giant hit sound"); component3.giantBurningAudio.volume = 0f; Plugin.Logger.LogDebug((object)"Fix forest giant burning volume fade"); break; } case "GiantKiwi": { val3 = item.enemyType; GiantKiwiAI component = item.enemyType.enemyPrefab.GetComponent<GiantKiwiAI>(); object obj3; if (component == null) { obj3 = null; } else { GameObject feathersPrefab = component.feathersPrefab; obj3 = ((feathersPrefab != null) ? feathersPrefab.GetComponent<AudioSource>() : null); } AudioSource val4 = (AudioSource)obj3; if ((Object)(object)val4 != (Object)null) { val4.spatialBlend = 1f; Plugin.Logger.LogDebug((object)"Fix sapsucker death poof"); } break; } case "MouthDog": val2 = item.enemyType; break; } if ((Object)(object)References.hitEnemyBody == (Object)null && ((Object)item.enemyType.hitBodySFX).name == "HitEnemyBody") { References.hitEnemyBody = item.enemyType.hitBodySFX; Plugin.Logger.LogDebug((object)"Cached generic damage sound"); } } if ((Object)(object)References.hitEnemyBody != (Object)null) { if ((Object)(object)val2 != (Object)null) { val2.hitBodySFX = References.hitEnemyBody; Plugin.Logger.LogDebug((object)"Overwritten missing eyeless dog hit sound"); } if ((Object)(object)val3 != (Object)null) { val3.hitBodySFX = References.hitEnemyBody; Plugin.Logger.LogDebug((object)"Overwritten missing giant sapsucker hit sound"); } } } [HarmonyPatch(typeof(MouthDogAI), "OnCollideWithEnemy")] [HarmonyPatch(typeof(BushWolfEnemy), "OnCollideWithEnemy")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> EnemyAI_Trans_OnCollideWithEnemy(IEnumerable<CodeInstruction> instructions) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); for (int i = 2; i < list.Count; i++) { if (list[i].opcode == OpCodes.Callvirt && (MethodInfo)list[i].operand == References.HIT_ENEMY) { list.RemoveAt(i - 2); list.InsertRange(i - 2, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)References.IS_ENEMY_DEAD), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ceq, (object)null) })); Plugin.Logger.LogDebug((object)"Transpiler: Don't play hit sound when attacking dead enemy"); break; } } return list; } [HarmonyPatch(typeof(StormyWeather), "PlayThunderEffects")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> StormyWeather_Trans_PlayThunderEffects(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); FieldInfo fieldInfo = AccessTools.Field(typeof(StartOfRound), "shipCreakSFX"); for (int i = 5; i < list.Count; i++) { if (list[i].opcode == OpCodes.Call && (MethodInfo)list[i].operand == References.PLAY_RANDOM_CLIP && list[i - 1].opcode == OpCodes.Ldc_I4 && (int)list[i - 1].operand == 1000 && list[i - 5].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 5].operand == fieldInfo) { list[i - 1].opcode = OpCodes.Ldc_I4_6; Plugin.Logger.LogDebug((object)"Transpiler (Stormy weather): No \"Hey\" when ship is struck"); break; } } return list; } [HarmonyPatch(typeof(RoundManager), "FinishGeneratingNewLevelClientRpc")] [HarmonyPostfix] private static void RoundManager_Post_FinishGeneratingNewLevelClientRpc() { if (patchedDoorSfx) { return; } patchedDoorSfx = true; if (!Plugin.configFixDoorSounds.Value) { return; } string text = null; if (StartOfRound.Instance.currentLevel.sceneName == "Level5Rend") { text = "/Environment/Map/SnowCabin/FancyDoorMapModel/SteelDoor (1)/DoorMesh/Cube"; } else if (StartOfRound.Instance.currentLevel.sceneName == "Level10Adamance") { text = "/Environment/SnowCabin/FancyDoorMapModel/SteelDoor (1)/DoorMesh/Cube"; } if (!string.IsNullOrEmpty(text) && References.woodenDoorOpen != null && References.woodenDoorOpen.Length != 0 && References.woodenDoorClose != null && References.woodenDoorClose.Length != 0) { GameObject obj = GameObject.Find(text); AnimatedObjectTrigger val = ((obj != null) ? obj.GetComponent<AnimatedObjectTrigger>() : null); if ((Object)(object)val != (Object)null) { val.boolFalseAudios = References.woodenDoorClose; val.boolTrueAudios = References.woodenDoorOpen; Plugin.Logger.LogDebug((object)"Overwritten cabin door sounds"); } } AnimatedObjectTrigger[] array = Object.FindObjectsByType<AnimatedObjectTrigger>((FindObjectsSortMode)0); foreach (AnimatedObjectTrigger val2 in array) { if ((Object)(object)val2.thisAudioSource != (Object)null) { Transform parent = ((Component)val2).transform.parent; if (parent != null) { ((Component)parent).GetComponent<Renderer>(); } if (((Object)val2).name == "PowerBoxDoor" || ((Object)val2.thisAudioSource).name == "storage door") { AudioClip[] boolTrueAudios = (AudioClip[])val2.boolFalseAudios.Clone(); val2.boolFalseAudios = (AudioClip[])val2.boolTrueAudios.Clone(); val2.boolTrueAudios = boolTrueAudios; Plugin.Logger.LogDebug((object)(((Object)val2).name + ": AnimatedObjectTrigger audios")); } } } } [HarmonyPatch(typeof(StartOfRound), "EndOfGameClientRpc")] [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void ResetLoadState() { patchedDoorSfx = false; } [HarmonyPatch(typeof(RoundManager), "Awake")] [HarmonyPostfix] private static void RoundManager_Post_Awake(RoundManager __instance) { PatchManorDoors(__instance); MineshaftPatches(__instance); } private static void PatchManorDoors(RoundManager roundManager) { //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Unknown result type (might be due to invalid IL or missing references) //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04bf: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) AudioMixerGroup outputAudioMixerGroup = null; IndoorMapType val = ((IEnumerable<IndoorMapType>)roundManager.dungeonFlowTypes).FirstOrDefault((Func<IndoorMapType, bool>)delegate(IndoorMapType dungeonFlowType) { DungeonFlow dungeonFlow = dungeonFlowType.dungeonFlow; return ((dungeonFlow != null) ? ((Object)dungeonFlow).name : null) == "Level2Flow"; }); if (val == null) { return; } bool flag = References.woodenDoorOpen == null || References.woodenDoorOpen.Length < 1 || References.woodenDoorClose == null || References.woodenDoorClose.Length < 1; foreach (GraphNode node in val.dungeonFlow.Nodes) { foreach (TileSet tileSet in node.TileSets) { if (!(((Object)tileSet).name == "Level2CapTiles")) { continue; } GameObject val2 = ((IEnumerable<GameObjectChance>)tileSet.TileWeights.Weights).FirstOrDefault((Func<GameObjectChance, bool>)delegate(GameObjectChance weight) { GameObject value3 = weight.Value; return ((value3 != null) ? ((Object)value3).name : null) == "GarageTile"; })?.Value; if (!((Object)(object)val2 != (Object)null)) { continue; } Transform obj = val2.transform.Find("SpawnInteractables"); GameObject val3 = ((obj == null) ? null : ((Component)obj).GetComponent<SpawnSyncedObject>()?.spawnPrefab); if ((Object)(object)val3 != (Object)null) { Transform obj2 = val3.transform.Find("GarbageBinContainer/GarbageBin"); AnimatedObjectTrigger val4 = ((obj2 != null) ? ((Component)obj2).GetComponent<AnimatedObjectTrigger>() : null); if ((Object)(object)val4 != (Object)null && !Object.op_Implicit((Object)(object)((Component)val4).GetComponent<AudioSource>())) { AudioSource thisAudioSource = val4.thisAudioSource; val4.thisAudioSource = ((Component)val4).gameObject.AddComponent<AudioSource>(); outputAudioMixerGroup = thisAudioSource.outputAudioMixerGroup; val4.thisAudioSource.outputAudioMixerGroup = outputAudioMixerGroup; val4.thisAudioSource.pitch = thisAudioSource.pitch; val4.thisAudioSource.spatialBlend = thisAudioSource.spatialBlend; val4.thisAudioSource.dopplerLevel = thisAudioSource.dopplerLevel; val4.thisAudioSource.spread = thisAudioSource.spread; val4.thisAudioSource.rolloffMode = thisAudioSource.rolloffMode; val4.thisAudioSource.minDistance = thisAudioSource.minDistance; val4.thisAudioSource.maxDistance = thisAudioSource.maxDistance; } } } } foreach (GraphLine line in val.dungeonFlow.Lines) { foreach (DungeonArchetype dungeonArchetype in line.DungeonArchetypes) { foreach (TileSet tileSet2 in dungeonArchetype.TileSets) { if (((Object)tileSet2).name == "Level2HallwayTilesB") { if (!flag) { continue; } GameObject val5 = ((IEnumerable<GameObjectChance>)tileSet2.TileWeights.Weights).FirstOrDefault((Func<GameObjectChance, bool>)delegate(GameObjectChance weight) { GameObject value2 = weight.Value; return ((value2 != null) ? ((Object)value2).name : null) == "ManorStartRoomSmall"; })?.Value; if (!((Object)(object)val5 != (Object)null)) { continue; } Transform obj3 = val5.transform.Find("Doorways"); object obj4; if (obj3 == null) { obj4 = null; } else { Doorway componentInChildren = ((Component)obj3).GetComponentInChildren<Doorway>(); if (componentInChildren == null) { obj4 = null; } else { List<GameObjectWeight> connectorPrefabWeights = componentInChildren.ConnectorPrefabWeights; if (connectorPrefabWeights == null) { obj4 = null; } else { GameObjectWeight? obj5 = ((IEnumerable<GameObjectWeight>)connectorPrefabWeights).FirstOrDefault((Func<GameObjectWeight, bool>)((GameObjectWeight prefab) => ((Object)prefab.GameObject).name == "FancyDoorMapSpawn")); if (obj5 == null) { obj4 = null; } else { SpawnSyncedObject component = obj5.GameObject.GetComponent<SpawnSyncedObject>(); if (component == null) { obj4 = null; } else { GameObject spawnPrefab = component.spawnPrefab; obj4 = ((spawnPrefab != null) ? spawnPrefab.GetComponentInChildren<AnimatedObjectTrigger>() : null); } } } } } AnimatedObjectTrigger val6 = (AnimatedObjectTrigger)obj4; if ((Object)(object)val6 != (Object)null) { References.woodenDoorClose = val6.boolFalseAudios; References.woodenDoorOpen = val6.boolTrueAudios; Plugin.Logger.LogDebug((object)"Cached wooden door sounds"); flag = false; } } else { if (!(((Object)tileSet2).name == "Level2RoomTiles")) { continue; } GameObject val7 = ((IEnumerable<GameObjectChance>)tileSet2.TileWeights.Weights).FirstOrDefault((Func<GameObjectChance, bool>)delegate(GameObjectChance weight) { GameObject value = weight.Value; return ((value != null) ? ((Object)value).name : null) == "GreenhouseTile"; })?.Value; if (!((Object)(object)val7 != (Object)null)) { continue; } Transform obj6 = val7.transform.Find("GreenhouseSinkContainer/SpawnInteractables"); GameObject val8 = ((obj6 == null) ? null : ((Component)obj6).GetComponent<SpawnSyncedObject>()?.spawnPrefab); if (!((Object)(object)val8 != (Object)null) || !((Object)(object)val8.transform.Find("SwingOpenCabinetAudio") == (Object)null)) { continue; } GameObject val9 = new GameObject("SwingOpenCabinetAudio"); val9.transform.SetParent(val8.transform); val9.transform.SetLocalPositionAndRotation(new Vector3(-10.515533f, -5.3320847f, 5.7967625f), Quaternion.Euler(0f, 90f, 0f)); val9.transform.localScale = Vector3.one; AudioSource val10 = val9.AddComponent<AudioSource>(); val10.outputAudioMixerGroup = outputAudioMixerGroup; val10.volume = 0.717f; val10.pitch = 0.91f; val10.spatialBlend = 1f; val10.spread = 41f; val10.rolloffMode = (AudioRolloffMode)1; val10.minDistance = 1f; val10.maxDistance = 12f; AnimatedObjectTrigger[] componentsInChildren = val8.GetComponentsInChildren<AnimatedObjectTrigger>(); foreach (AnimatedObjectTrigger val11 in componentsInChildren) { if ((Object)(object)val11.triggerAnimator != (Object)null && ((Object)val11.triggerAnimator).name.StartsWith("BigCupboard")) { val11.thisAudioSource = val10; Plugin.Logger.LogDebug((object)("Fixed greenhouse door \"" + ((Object)val11).name + "\"")); } } } } } } } private static void MineshaftPatches(RoundManager roundManager) { IndoorMapType val = ((IEnumerable<IndoorMapType>)roundManager.dungeonFlowTypes).FirstOrDefault((Func<IndoorMapType, bool>)delegate(IndoorMapType dungeonFlowType) { DungeonFlow dungeonFlow = dungeonFlowType.dungeonFlow; return ((dungeonFlow != null) ? ((Object)dungeonFlow).name : null) == "Level3Flow"; }); if (val != null) { PatchMineshaftDoors(val); GetButtonAudio(val); } } private static void PatchMineshaftDoors(IndoorMapType mineshaft) { foreach (GraphLine line in mineshaft.dungeonFlow.Lines) { foreach (DungeonArchetype dungeonArchetype in line.DungeonArchetypes) { foreach (TileSet tileSet in dungeonArchetype.TileSets) { if (!(((Object)tileSet).name == "Level3TunnelTiles")) { continue; } GameObject val = ((IEnumerable<GameObjectChance>)tileSet.TileWeights.Weights).FirstOrDefault((Func<GameObjectChance, bool>)delegate(GameObjectChance weight) { GameObject value = weight.Value; return ((value != null) ? ((Object)value).name : null) == "TunnelSplit"; })?.Value; if (!((Object)(object)val != (Object)null)) { continue; } Transform obj = val.transform.Find("DoorwayPointW"); object obj2; if (obj == null) { obj2 = null; } else { Doorway componentInChildren = ((Component)obj).GetComponentInChildren<Doorway>(); if (componentInChildren == null) { obj2 = null; } else { List<GameObjectWeight> connectorPrefabWeights = componentInChildren.ConnectorPrefabWeights; if (connectorPrefabWeights == null) { obj2 = null; } else { GameObjectWeight? obj3 = ((IEnumerable<GameObjectWeight>)connectorPrefabWeights).FirstOrDefault((Func<GameObjectWeight, bool>)((GameObjectWeight prefab) => ((Object)prefab.GameObject).name == "MineDoorSpawn")); if (obj3 == null) { obj2 = null; } else { SpawnSyncedObject componentInChildren2 = obj3.GameObject.GetComponentInChildren<SpawnSyncedObject>(); if (componentInChildren2 == null) { obj2 = null; } else { GameObject spawnPrefab = componentInChildren2.spawnPrefab; obj2 = ((spawnPrefab != null) ? spawnPrefab.transform : null); } } } } } Transform val2 = (Transform)obj2; if (!((Object)(object)val2 != (Object)null)) { continue; } Collider[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Collider>(); foreach (Collider val3 in componentsInChildren) { if (((Component)val3).gameObject.layer == 8 && ((Object)val3).name == "LOSBlocker" && ((Object)((Component)val3).transform.parent).name == "MineDoorMesh") { ((Component)val3).gameObject.layer = 11; Plugin.Logger.LogDebug((object)"Fixed mineshaft door occlusion"); return; } } } } } } private static void GetButtonAudio(IndoorMapType mineshaft) { if (!((Object)(object)References.cruiserDashboardButton == (Object)null) && !((Object)(object)References.sfx == (Object)null)) { return; } foreach (GraphNode node in mineshaft.dungeonFlow.Nodes) { foreach (TileSet tileSet in node.TileSets) { if (!(((Object)tileSet).name == "MineshaftStartRooms")) { continue; } GameObject val = ((IEnumerable<GameObjectChance>)tileSet.TileWeights.Weights).FirstOrDefault((Func<GameObjectChance, bool>)delegate(GameObjectChance weight) { GameObject value = weight.Value; return ((value != null) ? ((Object)value).name : null) == "MineshaftStartTile"; })?.Value; if (!((Object)(object)val != (Object)null)) { continue; } Transform obj = val.transform.Find("ElevatorSpawn"); object obj2; if (obj == null) { obj2 = null; } else { SpawnSyncedObject componentInChildren = ((Component)obj).GetComponentInChildren<SpawnSyncedObject>(); if (componentInChildren == null) { obj2 = null; } else { GameObject spawnPrefab = componentInChildren.spawnPrefab; if (spawnPrefab == null) { obj2 = null; } else { Transform obj3 = spawnPrefab.transform.Find("AnimContainer/controlBox/redButton"); obj2 = ((obj3 != null) ? ((Component)obj3).GetComponent<AnimatedObjectTrigger>() : null); } } } AnimatedObjectTrigger val2 = (AnimatedObjectTrigger)obj2; if ((Object)(object)val2 != (Object)null && val2.boolFalseAudios != null && val2.boolFalseAudios.Length != 0) { References.cruiserDashboardButton = val2.boolFalseAudios[0]; AudioSource component = ((Component)val2).GetComponent<AudioSource>(); References.sfx = ((component != null) ? component.outputAudioMixerGroup : null); Plugin.Logger.LogDebug((object)"Cached dashboard button sound"); return; } } } } [HarmonyPatch(typeof(EnemyVent), "OpenVentClientRpc")] [HarmonyPostfix] private static void EnemyVent_Post_OpenVentClientRpc(EnemyVent __instance) { __instance.isPlayingAudio = false; __instance.ventAudio.Stop(); } [HarmonyPatch(typeof(GrabbableObject), "PlayDropSFX")] [HarmonyPrefix] private static bool GrabbableObject_Pre_PlayDropSFX(GrabbableObject __instance) { LockPicker val = (LockPicker)(object)((__instance is LockPicker) ? __instance : null); if (val != null) { return !val.isOnDoor; } return true; } [HarmonyPatch(typeof(Landmine), "Detonate")] [HarmonyPostfix] private static void Landmine_Post_Detonate(Landmine __instance) { if ((Object)(object)__instance.mineFarAudio != (Object)null && (Object)(object)__instance.mineDetonateFar != (Object)null) { __instance.mineFarAudio.PlayOneShot(__instance.mineDetonateFar); } } [HarmonyPatch(typeof(ExtensionLadderItem), "StartLadderAnimation")] [HarmonyPostfix] private static void ExtensionLadderItem_Post_StartLadderAnimation(ExtensionLadderItem __instance) { if (__instance.ladderBlinkWarning) { __instance.ladderBlinkWarning = false; Plugin.Logger.LogDebug((object)"Fixed broken extension ladder warning"); } } [HarmonyPatch(typeof(SoundManager), "PlayRandomOutsideMusic")] [HarmonyPrefix] private static bool SoundManager_Pre_PlayRandomOutsideMusic(SoundManager __instance) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 if (Plugin.configEclipsesBlockMusic.Value) { return (int)StartOfRound.Instance.currentLevel.currentWeather != 5; } return true; } [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] [HarmonyWrapSafe] private static void StartOfRound_Post_Awake(StartOfRound __instance) { __instance.speakerAudioSource.dopplerLevel = Plugin.configMusicDopplerLevel.Value; __instance.shipDoorAudioSource.dopplerLevel = Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Ship speakers"); ((IEnumerable<GameObject>)__instance.VehiclesList).FirstOrDefault((Func<GameObject, bool>)((GameObject vehicle) => ((Object)vehicle).name == "CompanyCruiser")).GetComponent<VehicleController>().radioAudio.dopplerLevel = Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Cruiser"); Transform obj = __instance.elevatorTransform.Find("StickyNoteItem"); AudioSource val = ((obj != null) ? ((Component)obj).GetComponent<AudioSource>() : null); if ((Object)(object)val != (Object)null) { val.rolloffMode = (AudioRolloffMode)1; Plugin.Logger.LogDebug((object)"Audio rolloff: Sticky note"); } Transform obj2 = __instance.elevatorTransform.Find("ClipboardManual"); AudioSource val2 = ((obj2 != null) ? ((Component)obj2).GetComponent<AudioSource>() : null); if ((Object)(object)val2 != (Object)null) { val2.rolloffMode = (AudioRolloffMode)1; Plugin.Logger.LogDebug((object)"Audio rolloff: Clipboard"); } foreach (UnlockableItem unlockable in StartOfRound.Instance.unlockablesList.unlockables) { switch (unlockable.unlockableName) { case "Record player": unlockable.prefabObject.GetComponentInChildren<AnimatedObjectTrigger>().thisAudioSource.dopplerLevel = Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Record player"); break; case "Disco Ball": unlockable.prefabObject.GetComponentInChildren<CozyLights>().turnOnAudio.dopplerLevel = 0.92f * Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Disco ball"); break; case "Microwave": ((Component)unlockable.prefabObject.transform.Find("MicrowaveBody")).GetComponent<AudioSource>().playOnAwake = true; Plugin.Logger.LogDebug((object)"Audio: Microwave"); break; } } AudioClip val3 = null; AudioClip val4 = null; AudioClip val5 = null; AudioClip val6 = null; AudioClip val7 = null; List<Item> list = new List<Item>(); List<Item> list2 = new List<Item>(); List<Item> list3 = new List<Item>(); Item val8 = null; foreach (Item items in StartOfRound.Instance.allItemsList.itemsList) { bool flag = false; switch (((Object)items).name) { case "Boombox": items.spawnPrefab.GetComponent<BoomboxItem>().boomboxAudio.dopplerLevel = 0.3f * Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Boombox"); break; case "BottleBin": val4 = items.grabSFX; break; case "ToyCube": case "Brush": case "Phone": case "Remote": case "SteeringWheel": list2.Add(items); break; case "Candy": case "Toothpaste": items.grabSFX = null; break; case "MapDevice": case "ZapGun": case "Cog1": flag = true; break; case "DustPan": val6 = items.dropSFX; break; case "FancyCup": if (!Plugin.INSTALLED_UPTURNED_VARIETY) { list.Add(items); } break; case "FancyPainting": list3.Add(items); break; case "FishTestProp": flag = true; break; case "GarbageLid": case "MetalSheet": list.Add(items); break; case "Mug": val5 = items.dropSFX; break; case "PillBottle": val8 = items; items.grabSFX = null; break; case "RedLocustHive": flag = true; break; case "TeaKettle": val3 = items.grabSFX; break; case "TragedyMask": val7 = items.grabSFX; break; case "WalkieTalkie": { WalkieTalkie component = items.spawnPrefab.GetComponent<WalkieTalkie>(); ((Component)component).gameObject.AddComponent<RadioChatter>().walkieTalkie = component; Plugin.Logger.LogDebug((object)"Walkie talkie: Let's make some noise!"); break; } case "WeedKillerBottle": items.spawnPrefab.GetComponent<SprayPaintItem>().sprayAudio.loop = false; Plugin.Logger.LogDebug((object)"Loop: Weed killer"); break; } if (flag) { items.spawnPrefab.GetComponent<AudioSource>().rolloffMode = (AudioRolloffMode)1; Plugin.Logger.LogDebug((object)("Audio rolloff: " + items.itemName)); } } if ((Object)(object)val3 != (Object)null) { foreach (Item item in list) { item.grabSFX = val3; Plugin.Logger.LogDebug((object)("Audio: " + item.itemName)); } } if ((Object)(object)val4 != (Object)null) { foreach (Item item2 in list2) { item2.grabSFX = val4; Plugin.Logger.LogDebug((object)("Audio: " + item2.itemName)); if (((Object)item2).name == "Phone" && (Object)(object)val6 != (Object)null) { item2.dropSFX = val6; } } } if ((Object)(object)val7 != (Object)null) { foreach (Item item3 in list3) { item3.grabSFX = val7; Plugin.Logger.LogDebug((object)("Audio: " + item3.itemName)); } } if ((Object)(object)val8 != (Object)null && (Object)(object)val5 != (Object)null) { val8.dropSFX = val5; Plugin.Logger.LogDebug((object)("Audio: " + val8.itemName)); } } [HarmonyPatch(typeof(ItemDropship), "Start")] [HarmonyPostfix] private static void ItemDropship_Post_Start(ItemDropship __instance) { Transform val = ((Component)__instance).transform.Find("Music"); if ((Object)(object)val != (Object)null) { ((Component)val).GetComponent<AudioSource>().dopplerLevel = 0.6f * Plugin.configMusicDopplerLevel.Value; Transform obj = val.Find("Music (1)"); AudioSource val2 = ((obj != null) ? ((Component)obj).GetComponent<AudioSource>() : null); if ((Object)(object)val2 != (Object)null) { val2.dopplerLevel = 0.6f * Plugin.configMusicDopplerLevel.Value; } Plugin.Logger.LogDebug((object)"Doppler level: Dropship"); } } [HarmonyPatch(typeof(MineshaftElevatorController), "OnEnable")] [HarmonyPostfix] private static void MineshaftElevatorController_Post_OnEnable(MineshaftElevatorController __instance) { __instance.elevatorJingleMusic.dopplerLevel = 0.58f * Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Mineshaft elevator"); } [HarmonyPatch(typeof(Terminal), "Start")] [HarmonyPostfix] private static void Terminal_Post_Start(Terminal __instance) { BuyableVehicle val = ((IEnumerable<BuyableVehicle>)__instance.buyableVehicles).FirstOrDefault((Func<BuyableVehicle, bool>)((BuyableVehicle buyableVehicle) => buyableVehicle.vehicleDisplayName == "Cruiser")); if (val != null) { GameObject secondaryPrefab = val.secondaryPrefab; AudioSource val2 = ((secondaryPrefab != null) ? ((Component)secondaryPrefab.transform).GetComponent<AudioSource>() : null); if ((Object)(object)val2 != (Object)null) { val2.rolloffMode = (AudioRolloffMode)1; Plugin.Logger.LogDebug((object)"Audio rolloff: Clipboard (Cruiser)"); } } } [HarmonyPatch(typeof(FlashlightItem), "ItemActivate")] [HarmonyPrefix] private static bool FlashlightItem_Pre_ItemActivate(FlashlightItem __instance, bool used) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((GrabbableObject)__instance).itemProperties == (Object)null || ((GrabbableObject)__instance).itemProperties.itemId != 6) { return true; } if (__instance.flashlightInterferenceLevel < 2) { __instance.SwitchFlashlight(used); } __instance.flashlightAudio.PlayOneShot(__instance.flashlightClips[(!((GrabbableObject)__instance).isBeingUsed) ? 1u : 0u]); RoundManager.Instance.PlayAudibleNoise(((Component)__instance).transform.position, 7f, 0.4f, 0, ((GrabbableObject)__instance).isInElevator && StartOfRound.Instance.hangarDoorsClosed, 0); return false; } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerPatches { [HarmonyPatch("DamagePlayer")] [HarmonyPrefix] private static void PlayerControllerB_Pre_DamagePlayer(CauseOfDeath causeOfDeath, ref bool fallDamage) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 if ((int)causeOfDeath == 2 && !fallDamage) { fallDamage = true; Plugin.Logger.LogDebug((object)"Player: Treat Gravity damage as fall damage"); } } [HarmonyPatch("DamagePlayerFromOtherClientClientRpc")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> PlayerControllerB_Trans_DamagePlayerFromOtherClientClientRpc(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); for (int i = 3; i < list.Count; i++) { if (!(list[i].opcode == OpCodes.Call) || !((MethodInfo)list[i].operand == References.DAMAGE_PLAYER)) { continue; } for (int num = i - 1; num > 0; num--) { if (list[num].opcode == OpCodes.Ldarg_1 && list[num + 1].opcode == OpCodes.Ldc_I4_1) { list[num + 1].opcode = OpCodes.Ldc_I4_0; Plugin.Logger.LogDebug((object)"Transpiler (Players): Melee weapons don't stack hit sounds"); break; } } } return list; } } } namespace EnemySoundFixes.Patches.Enemies { [HarmonyPatch(typeof(BaboonBirdAI))] internal static class BaboonHawkPatches { [HarmonyPatch("HitEnemy")] [HarmonyPostfix] private static void BaboonBirdAI_Post_HitEnemy(BaboonBirdAI __instance, bool playHitSFX) { if (playHitSFX && !((EnemyAI)__instance).isEnemyDead) { if (!((EnemyAI)__instance).isEnemyDead && (Object)(object)References.baboonTakeDamage != (Object)null) { ((EnemyAI)__instance).creatureVoice.PlayOneShot(References.baboonTakeDamage); Plugin.Logger.LogDebug((object)"Baboon hawk: Ouch"); } else if ((Object)(object)References.hitEnemyBody != (Object)null) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(References.hitEnemyBody); } } } [HarmonyPatch("OnCollideWithEnemy")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> BaboonBirdAI_Trans_OnCollideWithEnemy(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Expected O, but got Unknown //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Expected O, but got Unknown //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Expected O, but got Unknown //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.Method(typeof(Animator), "ResetTrigger", new Type[1] { typeof(string) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.DeclaredPropertyGetter(typeof(RoundManager), "Instance"); for (int i = 3; i < list.Count; i++) { if (list[i].opcode == OpCodes.Callvirt && (MethodInfo)list[i].operand == methodInfo) { for (int j = i + 1; j < list.Count; j++) { if (list[j].opcode == OpCodes.Call && (MethodInfo)list[j].operand == methodInfo2) { Label label = generator.DefineLabel(); list[j].labels.Add(label); list.InsertRange(i - 3, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)References.IS_ENEMY_DEAD), new CodeInstruction(OpCodes.Brtrue, (object)label) })); Plugin.Logger.LogDebug((object)"Transpiler (Baboon hawk): Don't play hit sound when attacking dead enemy (A)"); i += 3; break; } } } else if (list[i].opcode == OpCodes.Callvirt && (MethodInfo)list[i].operand == References.HIT_ENEMY) { list.RemoveAt(i - 2); list.InsertRange(i - 2, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[4] { new CodeInstruction(OpCodes.Ldarg_2, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)References.IS_ENEMY_DEAD), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ceq, (object)null) })); Plugin.Logger.LogDebug((object)"Transpiler (Baboon hawk): Don't play hit sound when attacking dead enemy (B)"); i += 4; } } return list; } } [HarmonyPatch(typeof(StingrayAI))] internal static class BackwaterGunkfishPatches { [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void StingrayAI_Post_KillEnemy(StingrayAI __instance, bool destroy) { if (!destroy) { AudioSource[] array = (AudioSource[])(object)new AudioSource[3] { __instance.floppingAudio, __instance.slidingAudio, __instance.whiningAudio }; foreach (AudioSource obj in array) { obj.Stop(); obj.mute = true; } } } } [HarmonyPatch(typeof(FlowermanAI))] internal static class BrackenPatches { [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void FlowermanAI_Pre_HitEnemy(FlowermanAI __instance, int force, bool playHitSFX) { GeneralPatches.playHitSound = playHitSFX && !((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).enemyHP <= force; } [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void FlowermanAI_Post_KillEnemy(FlowermanAI __instance, bool destroy) { if (GeneralPatches.playHitSound) { GeneralPatches.playHitSound = false; if (!destroy) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(((EnemyAI)__instance).enemyType.hitBodySFX); Plugin.Logger.LogDebug((object)"Bracken: Play hit sound on death"); } } } } [HarmonyPatch(typeof(ButlerEnemyAI))] internal static class ButlerPatches { [HarmonyPatch("Update")] [HarmonyPostfix] private static void ButlerEnemyAI_Post_Update(ButlerEnemyAI __instance) { if (((EnemyAI)__instance).isEnemyDead && __instance.buzzingAmbience.isPlaying && ((EnemyAI)__instance).creatureAnimator.GetBool("popFinish")) { __instance.buzzingAmbience.Stop(); Plugin.Logger.LogDebug((object)"Butler: Stop buzzing (bugs are free)"); } } } [HarmonyPatch] internal static class CadaverPatches { private static MoldSpreadManager moldSpreadManager; [HarmonyPatch(typeof(CadaverGrowthAI), "Start")] [HarmonyPostfix] private static void CadaverGrowthAI_Post_Start(CadaverGrowthAI __instance) { if ((Object)(object)moldSpreadManager == (Object)null) { moldSpreadManager = Object.FindAnyObjectByType<MoldSpreadManager>(); } if ((Object)(object)moldSpreadManager != (Object)null && (Object)(object)__instance.destroyAudio != (Object)null && (Object)(object)__instance.destroyAudio.clip == (Object)null) { AudioSource destroyAudio = __instance.destroyAudio; AudioSource destroyAudio2 = moldSpreadManager.destroyAudio; destroyAudio.clip = ((destroyAudio2 != null) ? destroyAudio2.clip : null); } } } [HarmonyPatch(typeof(MouthDogAI))] internal static class EyelessDogPatches { private const float TIME_DROP_CARRIED_BODY = 5.01f; private static Dictionary<MouthDogAI, (float Pitch, float Time)> dogPitches = new Dictionary<MouthDogAI, (float, float)>(); [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void MouthDogAI_Post_KillEnemy(MouthDogAI __instance, bool destroy) { if (GeneralPatches.playHitSound) { GeneralPatches.playHitSound = false; if (!destroy && (Object)(object)References.hitEnemyBody != (Object)null) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(((EnemyAI)__instance).enemyType.hitBodySFX); Plugin.Logger.LogDebug((object)"Mouth dog: Play hit sound on death"); } } if (!destroy) { if (Plugin.configShootTheDog.Value && (Object)(object)((EnemyAI)__instance).enemyType.stunSFX != (Object)null) { ((EnemyAI)__instance).creatureVoice.PlayOneShot(((EnemyAI)__instance).enemyType.stunSFX); Plugin.Logger.LogDebug((object)"Eyeless dog: React grievously to agonizing departure"); } else { ((EnemyAI)__instance).creatureVoice.mute = true; Plugin.Logger.LogDebug((object)"Eyeless dog: Don't start breathing after death"); } } } [HarmonyPatch("Start")] [HarmonyPostfix] private static void MouthDogAI_Post_Start(MouthDogAI __instance) { Random random = new Random(StartOfRound.Instance.randomMapSeed + (int)((NetworkBehaviour)__instance).NetworkObjectId); if (random.Next(10) < 2) { ((EnemyAI)__instance).creatureVoice.pitch = 0.6f + 0.7f * (float)random.NextDouble(); } else { ((EnemyAI)__instance).creatureVoice.pitch = 0.9f + 0.2f * (float)random.NextDouble(); } Plugin.Logger.LogDebug((object)"Eyeless dog: Reroll voice pitch (seeded random)"); } [HarmonyPatch("KillPlayerClientRpc")] [HarmonyPrefix] private static void MouthDogAI_Pre_KillPlayerClientRpc(MouthDogAI __instance) { if (!dogPitches.ContainsKey(__instance)) { dogPitches.Add(__instance, (((EnemyAI)__instance).creatureVoice.pitch, Time.timeSinceLevelLoad + 5.01f)); Plugin.Logger.LogDebug((object)$"Eyeless dog #{((Object)__instance).GetInstanceID()}: Cached {((EnemyAI)__instance).creatureVoice.pitch}x voice pitch (kill animation will start)"); } else { Plugin.Logger.LogWarning((object)$"Eyeless dog #{((Object)__instance).GetInstanceID()}: Tried to initiate kill animation before ending previous kill animation"); } } [HarmonyPatch("Update")] [HarmonyPostfix] private static void MouthDogAI_Post_Update(MouthDogAI __instance, bool ___inKillAnimation) { if (!((EnemyAI)__instance).isEnemyDead) { if (dogPitches.Count > 0 && !___inKillAnimation && dogPitches.TryGetValue(__instance, out (float, float) value) && Time.timeSinceLevelLoad >= value.Item2) { dogPitches.Remove(__instance); Plugin.Logger.LogDebug((object)$"Eyeless dog #{((Object)__instance).GetInstanceID()}: Reset voice pitch now that kill sound is done ({((EnemyAI)__instance).creatureVoice.pitch}x -> {value.Item1}x)"); ((EnemyAI)__instance).creatureVoice.pitch = value.Item1; } if (!((EnemyAI)__instance).creatureVoice.isPlaying) { ((EnemyAI)__instance).creatureVoice.Play(); } } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> MouthDogAI_Trans_EnterChaseMode(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); for (int i = 1; i < list.Count; i++) { if (list[i].opcode == OpCodes.Callvirt && (MethodInfo)list[i].operand == References.PLAY_ONE_SHOT && list[i - 1].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 1].operand == AccessTools.Field(typeof(MouthDogAI), "breathingSFX")) { for (int j = i - 4; j <= i; j++) { list[j].opcode = OpCodes.Nop; } Plugin.Logger.LogDebug((object)"Transpiler (Eyeless dog): Fix overlapping breathing"); break; } } return list; } [HarmonyPatch(typeof(EnemyAI), "SubtractFromPowerLevel")] [HarmonyPostfix] private static void EnemyAI_Post_SubtractFromPowerLevel(EnemyAI __instance) { MouthDogAI val = (MouthDogAI)(object)((__instance is MouthDogAI) ? __instance : null); if ((Object)(object)val != (Object)null && dogPitches.Remove(val)) { Plugin.Logger.LogDebug((object)$"Eyeless dog #{((Object)__instance).GetInstanceID()}: Died mid kill animation (clean up cached reference)"); } } [HarmonyPatch(typeof(RoundManager), "ResetEnemyVariables")] [HarmonyPostfix] private static void RoundManager_Post_ResetEnemyVariables() { dogPitches.Clear(); } [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void MouthDogAI_Pre_HitEnemy(MouthDogAI __instance, int force, bool playHitSFX) { GeneralPatches.playHitSound = playHitSFX && !((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).enemyHP <= force; } } [HarmonyPatch(typeof(ForestGiantAI))] internal static class ForestKeeperPatches { private const float TIME_PLAY_AUDIO_2 = 2.2f; [HarmonyPatch("Update")] [HarmonyPostfix] private static void ForestGiantAI_Post_Update(ForestGiantAI __instance) { if (((EnemyAI)__instance).stunNormalizedTimer > 0f || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).currentBehaviourStateIndex == 2) { PlayAudioAnimationEvent component = ((Component)__instance.animationContainer).GetComponent<PlayAudioAnimationEvent>(); AudioSource audioToPlay = component.audioToPlay; if (audioToPlay.isPlaying && (Object)(object)audioToPlay.clip != (Object)null) { audioToPlay.clip = null; audioToPlay.Stop(); Plugin.Logger.LogDebug((object)"Forest keeper: Stop chewing (eating animation interrupted)"); } ParticleSystem particle = component.particle; if (particle.isEmitting) { particle.Stop(); Plugin.Logger.LogDebug((object)"Forest keeper: Stop spraying blood from mouth (eating animation interrupted)"); } } } [HarmonyPatch("StopKillAnimation")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> ForestGiantAI_Trans_Animation(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); for (int i = 1; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Ldfld && (FieldInfo)list[i].operand == References.CREATURE_VOICE) { for (int j = i - 1; j <= i + 1; j++) { list[j].opcode = OpCodes.Nop; list[j].operand = null; } Plugin.Logger.LogDebug((object)"Transpiler (Forest Keeper): Don't interrupt voice"); break; } } return list; } [HarmonyPatch("AnimationEventA")] [HarmonyPostfix] private static void ForestGiantAI_Post_AnimationEventA(ForestGiantAI __instance) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(__instance.giantFall); Plugin.Logger.LogDebug((object)"Forest keeper: Fallen down"); } [HarmonyPatch(typeof(PlayAudioAnimationEvent), "PlayAudio2")] [HarmonyPrefix] private static bool PlayAudioAnimationEvent_Pre_PlayAudio2(PlayAudioAnimationEvent __instance) { if (((Object)__instance.audioClip2).name == "FGiantEatPlayerSFX") { EnemyAI mainScript = ((Component)__instance).GetComponent<EnemyAnimationEvent>().mainScript; ForestGiantAI val = (ForestGiantAI)(object)((mainScript is ForestGiantAI) ? mainScript : null); if ((Object)(object)((EnemyAI)val).inSpecialAnimationWithPlayer != (Object)null && (Object)(object)((EnemyAI)val).inSpecialAnimationWithPlayer.inAnimationWithEnemy == (Object)(object)val) { __instance.audioToPlay.PlayOneShot(__instance.audioClip2); Plugin.Logger.LogDebug((object)"Forest keeper: Play bite sound effect with overlap"); } else { Plugin.Logger.LogDebug((object)"Forest keeper: Don't bite (player was teleported)"); } return false; } return true; } [HarmonyPatch(typeof(PlayAudioAnimationEvent), "PlayParticle")] [HarmonyPrefix] private static bool PlayAudioAnimationEvent_Pre_PlayParticle(PlayAudioAnimationEvent __instance) { if ((Object)(object)__instance.audioClip2 != (Object)null && ((Object)__instance.audioClip2).name == "FGiantEatPlayerSFX") { EnemyAI mainScript = ((Component)__instance).GetComponent<EnemyAnimationEvent>().mainScript; if ((Object)(object)mainScript.inSpecialAnimationWithPlayer == (Object)null || (Object)(object)mainScript.inSpecialAnimationWithPlayer.inAnimationWithEnemy != (Object)(object)mainScript) { Plugin.Logger.LogDebug((object)"Forest keeper: Don't spray blood (player was teleported)"); return false; } } return true; } [HarmonyPatch(typeof(EnemyAI), "CancelSpecialAnimationWithPlayer")] [HarmonyPrefix] private static void EnemyAI_Pre_CancelSpecialAnimationWithPlayer(EnemyAI __instance) { if (!(__instance is ForestGiantAI) || !((Object)(object)__instance.inSpecialAnimationWithPlayer != (Object)null) || !((Object)(object)__instance.inSpecialAnimationWithPlayer.inAnimationWithEnemy == (Object)(object)__instance) || __instance.inSpecialAnimationWithPlayer.isPlayerDead) { return; } PlayAudioAnimationEvent component = ((Component)((ForestGiantAI)((__instance is ForestGiantAI) ? __instance : null)).animationContainer).GetComponent<PlayAudioAnimationEvent>(); AudioSource audioToPlay = component.audioToPlay; if (!audioToPlay.isPlaying) { return; } AudioClip clip = audioToPlay.clip; if (((clip != null) ? ((Object)clip).name : null) == "Roar" && audioToPlay.time > 2.2f) { audioToPlay.Stop(); Plugin.Logger.LogDebug((object)"Forest keeper: Stop chewing (player was teleported)"); ParticleSystem particle = component.particle; if (particle.isEmitting) { particle.Stop(); Plugin.Logger.LogDebug((object)"Forest keeper: Stop spraying blood from mouth (player was teleported)"); } } } } [HarmonyPatch(typeof(GiantKiwiAI))] internal static class GiantSapsuckerPatches { [HarmonyPatch("Update")] [HarmonyPostfix] private static void GiantKiwiAI_Post_Update(GiantKiwiAI __instance) { if (((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).creatureSFX.isPlaying) { ((EnemyAI)__instance).creatureSFX.Stop(); Plugin.Logger.LogDebug((object)"Sapsucker: Stop snoring (dead)"); } } } [HarmonyPatch(typeof(HoarderBugAI))] internal static class HoardingBugPatches { [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void HoarderBugAI_Post_KillEnemy(HoarderBugAI __instance, bool destroy) { if (GeneralPatches.playHitSound) { GeneralPatches.playHitSound = false; if (!destroy) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(((EnemyAI)__instance).enemyType.hitBodySFX); Plugin.Logger.LogDebug((object)"Hoarding bug: Play hit sound on death"); } } if (!destroy) { ((EnemyAI)__instance).creatureVoice.PlayOneShot(((EnemyAI)__instance).enemyType.deathSFX); Plugin.Logger.LogDebug((object)"Hoarding bug: Played backup death sound"); } } [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void HoarderBugAI_Pre_HitEnemy(HoarderBugAI __instance, int force, bool playHitSFX) { GeneralPatches.playHitSound = playHitSFX && !((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).enemyHP <= force; } } [HarmonyPatch(typeof(BushWolfEnemy))] internal static class KidnapperFoxPatches { [HarmonyPatch("HitTongueLocalClient")] [HarmonyPostfix] private static void BushWolfEnemy_Post_HitTongueLocalClient(BushWolfEnemy __instance) { ((EnemyAI)__instance).creatureVoice.PlayOneShot(__instance.hitBushWolfSFX); Plugin.Logger.LogDebug((object)"Kidnapper fox: Bit my tongue"); } [HarmonyPatch("Update")] [HarmonyPostfix] private static void BushWolfEnemy_Post_Update(BushWolfEnemy __instance, bool ___dragging) { if ((!___dragging || ((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).stunNormalizedTimer > 0f) && ((EnemyAI)__instance).creatureVoice.isPlaying && (Object)(object)((EnemyAI)__instance).creatureVoice.clip == (Object)(object)__instance.snarlSFX) { ((EnemyAI)__instance).creatureVoice.clip = null; Plugin.Logger.LogDebug((object)"Kidnapper fox: Cancel snarl (failsafe)"); } if (((EnemyAI)__instance).isEnemyDead && __instance.spitParticle.isEmitting) { __instance.spitParticle.Stop(); Plugin.Logger.LogDebug((object)"Kidnapper fox: Cancel drool"); } } [HarmonyPatch("CancelReelingPlayerIn")] [HarmonyPrefix] private static void BushWolfEnemy_Pre_CancelReelingPlayerIn(BushWolfEnemy __instance, ref bool ___dragging) { if (___dragging && ((EnemyAI)__instance).isEnemyDead) { ___dragging = false; Plugin.Logger.LogDebug((object)"Kidnapper fox: Don't let dragging interrupt death voice"); } } [HarmonyPatch("HitEnemy")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> BushWolfEnemy_Trans_HitEnemy(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.Method(typeof(BushWolfEnemy), "CancelReelingPlayerIn", (Type[])null, (Type[])null); Label label = generator.DefineLabel(); list[list.Count - 1].labels.Add(label); for (int num = list.Count - 1; num >= 0; num--) { if (list[num].opcode == OpCodes.Call && (MethodInfo)list[num].operand == methodInfo) { list.InsertRange(num + 1, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldarg_0, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)References.IS_ENEMY_DEAD), new CodeInstruction(OpCodes.Brtrue, (object)label) })); Plugin.Logger.LogDebug((object)"Transpiler (Kidnapper fox): Don't cry when dead"); break; } } return list; } } [HarmonyPatch(typeof(CaveDwellerAI))] internal static class ManeaterPatches { [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void CaveDwellerAI_Pre_HitEnemy(CaveDwellerAI __instance, int force, bool playHitSFX) { GeneralPatches.playHitSound = playHitSFX && !((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).enemyHP <= 1; } [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void CaveDwellerAI_Post_KillEnemy(CaveDwellerAI __instance, bool destroy) { if (destroy) { return; } if (GeneralPatches.playHitSound) { GeneralPatches.playHitSound = false; if (!destroy) { ((EnemyAI)__instance).creatureSFX.Stop(); ((EnemyAI)__instance).creatureSFX.PlayOneShot(((EnemyAI)__instance).enemyType.hitBodySFX); Plugin.Logger.LogDebug((object)"Maneater: Play hit sound on death"); } } AudioSource[] array = (AudioSource[])(object)new AudioSource[5] { __instance.clickingAudio1, __instance.clickingAudio2, __instance.walkingAudio, __instance.screamAudio, __instance.screamAudioNonDiagetic }; foreach (AudioSource obj in array) { obj.Stop(); obj.mute = true; } } } [HarmonyPatch(typeof(MaskedPlayerEnemy))] internal static class MaskedPatches { private static EntranceTeleport mainEntranceScript; [HarmonyPatch("Start")] [HarmonyPostfix] private static void MaskedPlayerEnemy_Post_Start(MaskedPlayerEnemy __instance) { //IL_004f: 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_00ba: 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_00c3: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.configBetterMimicSteps.Value) { return; } AudioSource val = GameNetworkManager.Instance?.localPlayerController?.movementAudio; if ((Object)(object)val == (Object)null) { return; } ((Component)__instance.movementAudio).transform.localPosition = new Vector3(0f, 0.278f, 0f); __instance.movementAudio.volume = val.volume; __instance.movementAudio.dopplerLevel = val.dopplerLevel; __instance.movementAudio.spread = val.spread; __instance.movementAudio.rolloffMode = (AudioRolloffMode)2; foreach (AudioSourceCurveType value in Enum.GetValues(typeof(AudioSourceCurveType))) { __instance.movementAudio.SetCustomCurve(value, val.GetCustomCurve(value)); } Plugin.Logger.LogDebug((object)"Mimic: Footsteps match players"); } [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void MaskedPlayerEnemy_Pre_HitEnemy(MaskedPlayerEnemy __instance, int force, bool playHitSFX) { GeneralPatches.playHitSound = playHitSFX && !((EnemyAI)__instance).isEnemyDead && ((EnemyAI)__instance).enemyHP <= force; } [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void MaskedPlayerEnemy_Post_KillEnemy(MaskedPlayerEnemy __instance, bool destroy) { if (GeneralPatches.playHitSound) { GeneralPatches.playHitSound = false; if (!destroy) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(((EnemyAI)__instance).enemyType.hitBodySFX); Plugin.Logger.LogDebug((object)"Mimic: Play hit sound on death"); } } } [HarmonyPatch("TeleportMaskedEnemy")] [HarmonyTranspiler] [HarmonyPriority(800)] private static IEnumerable<CodeInstruction> MaskedPlayerEnemy_Trans_TeleportMaskedEnemy(IEnumerable<CodeInstruction> instructions) { List<CodeInstruction> list = instructions.ToList(); MethodInfo methodInfo = AccessTools.Method(typeof(RoundManager), "FindMainEntranceScript", (Type[])null, (Type[])null); for (int num = list.Count - 2; num >= 0; num--) { if (list[num].opcode == OpCodes.Call && (MethodInfo)list[num].operand == methodInfo) { list.RemoveAt(num); list.RemoveAt(num - 1); Plugin.Logger.LogDebug((object)"Transpiler (Mimic teleport): Remove old sound code"); return list; } list.RemoveAt(num); } Plugin.Logger.LogError((object)"Mimic teleport transpiler failed"); return instructions; } [HarmonyPatch("TeleportMaskedEnemy")] [HarmonyPostfix] private static void MaskedPlayerEnemy_Post_TeleportMaskedEnemy() { if ((Object)(object)mainEntranceScript == (Object)null) { mainEntranceScript = Object.FindObjectsByType<EntranceTeleport>((FindObjectsSortMode)0)?.FirstOrDefault((Func<EntranceTeleport, bool>)((EntranceTeleport entranceTeleport) => entranceTeleport.entranceId == 0)); } if ((Object)(object)mainEntranceScript != (Object)null) { mainEntranceScript.PlayAudioAtTeleportPositions(); Plugin.Logger.LogDebug((object)"Mimic: Play door sound"); } } } [HarmonyPatch(typeof(NutcrackerEnemyAI))] internal static class NutcrackerPatches { [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void NutcrackerEnemyAI_Post_KillEnemy(NutcrackerEnemyAI __instance, bool destroy) { if (!destroy) { ((EnemyAI)__instance).creatureVoice.loop = false; ((EnemyAI)__instance).creatureVoice.clip = null; ((EnemyAI)__instance).creatureVoice.pitch = 1f; ((EnemyAI)__instance).creatureVoice.PlayOneShot(((EnemyAI)__instance).enemyType.deathSFX); Plugin.Logger.LogDebug((object)"Nutcracker: Played death sound"); } } } [HarmonyPatch(typeof(CentipedeAI))] internal static class SnareFleaPatches { [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> CentipedeAI_Trans_delayedShriek(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Expected O, but got Unknown //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); Label label = generator.DefineLabel(); for (int i = 0; i < list.Count - 1; i++) { if (list[i].opcode == OpCodes.Ldloc_1 && list[i + 1].opcode == OpCodes.Ldfld && (FieldInfo)list[i + 1].operand == References.CREATURE_VOICE) { list[i].labels.Add(label); list.InsertRange(i, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[5] { new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)References.IS_ENEMY_DEAD), new CodeInstruction(OpCodes.Brfalse, (object)label), new CodeInstruction(OpCodes.Ldc_I4_0, (object)null), new CodeInstruction(OpCodes.Ret, (object)null) })); Plugin.Logger.LogDebug((object)"Transpiler (Snare flea): Don't shriek when dead (A)"); break; } } return list; } [HarmonyPatch("Update")] [HarmonyPrefix] private static void CentipedeAI_Pre_Update(CentipedeAI __instance) { if (((EnemyAI)__instance).creatureSFX.isPlaying && (Object)(object)((EnemyAI)__instance).creatureSFX.clip == (Object)(object)((EnemyAI)__instance).enemyBehaviourStates[2].SFXClip && (((EnemyAI)__instance).isEnemyDead || ((EnemyAI)__instance).currentBehaviourStateIndex != 2)) { ((EnemyAI)__instance).creatureSFX.Stop(); ((EnemyAI)__instance).creatureSFX.clip = null; Plugin.Logger.LogDebug((object)"Snare flea: Stop walking while dead, clinging to player, or sneaking away"); } } [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void CentipedeAI_Post_KillEnemy(CentipedeAI __instance) { ((EnemyAI)__instance).creatureSFX.clip = null; } [HarmonyPatch(typeof(EnemyAI), "PlayAudioOfCurrentState")] [HarmonyPostfix] private static void EnemyAI_Post_PlayAudioOfCurrentState(EnemyAI __instance) { if (__instance is CentipedeAI && __instance.currentBehaviourStateIndex == 1 && __instance.creatureVoice.pitch > 1f) { __instance.creatureVoice.pitch = 1f; Plugin.Logger.LogDebug((object)"Snare flea: Reset \"voice\" pitch for attacking again"); } } [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void CentipedeAI_Pre_HitEnemy(CentipedeAI __instance) { if (((EnemyAI)__instance).creatureSFX.isPlaying && (Object)(object)((EnemyAI)__instance).creatureSFX.clip == (Object)(object)((EnemyAI)__instance).enemyBehaviourStates[2].SFXClip) { ((EnemyAI)__instance).creatureSFX.Stop(); ((EnemyAI)__instance).creatureSFX.clip = null; } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> CentipedeAI_Trans_fallFromCeiling(IEnumerable<CodeInstruction> instructions, ILGenerator generator) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Expected O, but got Unknown List<CodeInstruction> list = instructions.ToList(); Label label = generator.DefineLabel(); FieldInfo fieldInfo = AccessTools.Field(typeof(CentipedeAI), "shriekClips"); for (int i = 8; i < list.Count - 2; i++) { if (list[i].opcode == OpCodes.Call && (MethodInfo)list[i].operand == References.PLAY_RANDOM_CLIP && list[i - 5].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 5].operand == fieldInfo) { list[i + 2].labels.Add(label); list.InsertRange(i - 8, new <>z__ReadOnlyArray<CodeInstruction>((CodeInstruction[])(object)new CodeInstruction[3] { new CodeInstruction(OpCodes.Ldloc_1, (object)null), new CodeInstruction(OpCodes.Ldfld, (object)References.IS_ENEMY_DEAD), new CodeInstruction(OpCodes.Brtrue, (object)label) })); Plugin.Logger.LogDebug((object)"Transpiler (Snare flea): Don't shriek when dead (B)"); break; } } return list; } [HarmonyPatch("StopClingingToPlayer")] [HarmonyPostfix] private static void CentipedeAI_Post_StopClingingToPlayer(CentipedeAI __instance) { __instance.clingingToPlayer2DAudio.Stop(); } } [HarmonyPatch(typeof(FlowerSnakeEnemy))] internal static class TulipSnakePatches { [HarmonyPatch("Update")] [HarmonyPostfix] private static void FlowerSnakeEnemy_Post_Update(FlowerSnakeEnemy __instance, bool ___flapping) { if (!__instance.flappingAudio.isPlaying) { return; } if (((EnemyAI)__instance).isEnemyDead) { __instance.flappingAudio.Stop(); __instance.flappingAudio.mute = true; Plugin.Logger.LogDebug((object)"Tulip snake: Stop making noise while dead"); } else if (!Plugin.INSTALLED_SOUND_API) { if ((Object)(object)__instance.flappingAudio.clip == (Object)(object)((EnemyAI)__instance).enemyType.audioClips[9]) { if ((Object)(object)__instance.clingingToPlayer != (Object)null) { __instance.flappingAudio.Stop(); Plugin.Logger.LogDebug((object)"Tulip snake: Stop scurrying (latched to player)"); } } else if ((Object)(object)__instance.clingingToPlayer == (Object)null) { __instance.flappingAudio.Stop(); Plugin.Logger.LogDebug((object)"Tulip snake: Stop flapping (no longer clinging)"); } } if (___flapping) { __instance.flappingAudio.volume = 0.85f; } } [HarmonyPatch("StopLeapOnLocalClient")] [HarmonyPostfix] private static void FlowerSnakeEnemy_Post_StopLeapOnLocalClient(FlowerSnakeEnemy __instance, bool landOnGround) { if (landOnGround && !((EnemyAI)__instance).isEnemyDead) { __instance.flappingAudio.pitch = Random.Range(0.8f, 1.2f); Plugin.Logger.LogDebug((object)"Tulip snake: Reroll scurry pitch (landed from leap)"); } } [HarmonyPatch("StopClingingOnLocalClient")] [HarmonyPostfix] private static void FlowerSnakeEnemy_Post_StopClingingOnLocalClient(FlowerSnakeEnemy __instance) { if (!((EnemyAI)__instance).isEnemyDead) { __instance.flappingAudio.pitch = Random.Range(0.8f, 1.2f); Plugin.Logger.LogDebug((object)"Tulip snake: Reroll scurry pitch (dismounted player)"); } } [HarmonyPatch("HitEnemy")] [HarmonyPrefix] private static void FlowerSnakeEnemy_Pre_HitEnemy(FlowerSnakeEnemy __instance, bool playHitSFX) { GeneralPatches.playHitSound = playHitSFX && !((EnemyAI)__instance).isEnemyDead; } [HarmonyPatch("KillEnemy")] [HarmonyPostfix] private static void FlowerSnakeEnemy_Post_KillEnemy(FlowerSnakeEnemy __instance, bool destroy) { if (GeneralPatches.playHitSound) { GeneralPatches.playHitSound = false; if (!destroy && (Object)(object)References.hitEnemyBody != (Object)null) { ((EnemyAI)__instance).creatureSFX.PlayOneShot(References.hitEnemyBody); Plugin.Logger.LogDebug((object)"Tulip snake: Squish"); } } } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } [CompilerGenerated] internal sealed class <>z__ReadOnlyArray<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { int ICollection.Count => _items.Length; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => _items.Length; T IReadOnlyList<T>.this[int index] => _items[index]; int ICollection<T>.Count => _items.Length; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { return _items[index]; } set { throw new NotSupportedException(); } } public <>z__ReadOnlyArray(T[] items) { _items = items; } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.CopyTo(Array array, int index) { ((ICollection)_items).CopyTo(array, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return ((IList)_items).Contains(value); } int IList.IndexOf(object value) { return ((IList)_items).IndexOf(value); } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return ((IEnumerable<T>)_items).GetEnumerator(); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return ((ICollection<T>)_items).Contains(item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { ((ICollection<T>)_items).CopyTo(array, arrayIndex); } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { return ((IList<T>)_items).IndexOf(item); } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } }