using 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.10.0")] [assembly: AssemblyInformationalVersion("1.9.10+8d2d9068659c79bd8c5d598f301ccfc43fae566e")] [assembly: AssemblyProduct("EnemySoundFixes")] [assembly: AssemblyTitle("EnemySoundFixes")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.9.10.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.10"), (CompatibilityLevel)0, (VersionStrictness)0); } } internal enum CruiserMute { Nothing = -1, NotRadio, All } [BepInPlugin("butterystancakes.lethalcompany.enemysoundfixes", "Enemy Sound Fixes", "1.9.10")] [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.10"; internal static ManualLogSource Logger; internal static ConfigEntry configThumperNoThunder; internal static ConfigEntry configBetterMimicSteps; internal static ConfigEntry configFixDoorSounds; internal static ConfigEntry configShootTheDog; internal static ConfigEntry configEclipsesBlockMusic; internal static ConfigEntry configWalkieHearsTalkies; internal static ConfigEntry configSpaceMutesCruiser; internal static ConfigEntry 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("Misc", "BetterMimicSteps", true, "Mimic footstep volume and distance are altered to sound more accurate to actual players."); configThumperNoThunder = ((BaseUnityPlugin)this).Config.Bind("Misc", "ThumperNoThunder", true, "Thumpers no longer play thunder sound effects from their voice when they stop chasing after players."); configShootTheDog = ((BaseUnityPlugin)this).Config.Bind("Misc", "ShootTheDog", true, "Makes eyeless dogs play their stun sound effect on death, rather than falling silently."); configSpaceMutesCruiser = ((BaseUnityPlugin)this).Config.Bind("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("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("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("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("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("Misc", "DontFixMasks", false, "Legacy setting, doesn't work"); ((BaseUnityPlugin)this).Config.Remove(((BaseUnityPlugin)this).Config["Misc", "DontFixMasks"].Definition); ((BaseUnityPlugin)this).Config.Bind("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.10 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(); ((Component)audio).transform.SetParent(((Component)this).transform, false); audio.clip = ((Component)this).GetComponent().talkingOnWalkieTalkieNotHeldSFX; audio.loop = true; AudioSource component = ((Component)this).GetComponent(); 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(); 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[])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 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.10"; } } namespace EnemySoundFixes.Patches { [HarmonyPatch(typeof(VehicleController))] internal static class CruiserPatches { [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public VehicleController vehicleController; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public 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 VehicleController_Trans_EngineRev(IEnumerable 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 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[])(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 VehicleController_Trans_SetVehicleAudioProperties(IEnumerable instructions) { List 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(d__6))] private static IEnumerator TwistKey(VehicleController vehicleController) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new 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(ref val3) && !((Object)(object)((Component)val2).GetComponent() != (Object)null)) { AudioSource audioSource = ((Component)val3).gameObject.AddComponent(); 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)(object)val3.onInteract).AddListener((UnityAction)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 DoorLock_Trans_UnlockDoor(IEnumerable instructions) { List 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("StunFlowerman"); obj.Unload(false); } catch { Plugin.Logger.LogError((object)"Encountered some error loading assets from bundle \"enemysoundfixes\". Did you install the plugin correctly?"); } List enemies = __instance.testAllEnemiesLevel.Enemies; List outsideEnemies = __instance.testAllEnemiesLevel.OutsideEnemies; List daytimeEnemies = __instance.testAllEnemiesLevel.DaytimeEnemies; List list = new List(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 "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(); component2.clickingAudio1.volume = 0f; component2.clickingAudio2.volume = 0f; Plugin.Logger.LogDebug((object)"Fix maneater clicking volume"); break; } case "Centipede": ((EnemyAI)item.enemyType.enemyPrefab.GetComponent()).creatureSFX.loop = true; Plugin.Logger.LogDebug((object)"Loop snare flea walking and clinging"); break; case "Crawler": if (Plugin.configThumperNoThunder.Value) { EnemyBehaviourState val5 = ((IEnumerable)((EnemyAI)item.enemyType.enemyPrefab.GetComponent()).enemyBehaviourStates).FirstOrDefault((Func)((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(); ((EnemyAI)component3).creatureSFX.spatialBlend = 1f; Plugin.Logger.LogDebug((object)"Fix forest giant global audio volume"); item.enemyType.hitBodySFX = ((IEnumerable)StartOfRound.Instance.footstepSurfaces).FirstOrDefault((Func)((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(); object obj3; if (component == null) { obj3 = null; } else { GameObject feathersPrefab = component.feathersPrefab; obj3 = ((feathersPrefab != null) ? feathersPrefab.GetComponent() : 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 EnemyAI_Trans_OnCollideWithEnemy(IEnumerable instructions, MethodBase __originalMethod) { //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 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[])(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 ({__originalMethod.DeclaringType}.{__originalMethod.Name}): Don't play hit sound when attacking dead enemy"); break; } } return list; } [HarmonyPatch(typeof(StormyWeather), "PlayThunderEffects")] [HarmonyTranspiler] private static IEnumerable StormyWeather_Trans_PlayThunderEffects(IEnumerable instructions) { List 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() : 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((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(); } 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)roundManager.dungeonFlowTypes).FirstOrDefault((Func)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)tileSet.TileWeights.Weights).FirstOrDefault((Func)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()?.spawnPrefab); if ((Object)(object)val3 != (Object)null) { Transform obj2 = val3.transform.Find("GarbageBinContainer/GarbageBin"); AnimatedObjectTrigger val4 = ((obj2 != null) ? ((Component)obj2).GetComponent() : null); if ((Object)(object)val4 != (Object)null && !Object.op_Implicit((Object)(object)((Component)val4).GetComponent())) { AudioSource thisAudioSource = val4.thisAudioSource; val4.thisAudioSource = ((Component)val4).gameObject.AddComponent(); 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)tileSet2.TileWeights.Weights).FirstOrDefault((Func)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(); if (componentInChildren == null) { obj4 = null; } else { List connectorPrefabWeights = componentInChildren.ConnectorPrefabWeights; if (connectorPrefabWeights == null) { obj4 = null; } else { GameObjectWeight? obj5 = ((IEnumerable)connectorPrefabWeights).FirstOrDefault((Func)((GameObjectWeight prefab) => ((Object)prefab.GameObject).name == "FancyDoorMapSpawn")); if (obj5 == null) { obj4 = null; } else { SpawnSyncedObject component = obj5.GameObject.GetComponent(); if (component == null) { obj4 = null; } else { GameObject spawnPrefab = component.spawnPrefab; obj4 = ((spawnPrefab != null) ? spawnPrefab.GetComponentInChildren() : 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)tileSet2.TileWeights.Weights).FirstOrDefault((Func)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()?.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(); 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(); 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)roundManager.dungeonFlowTypes).FirstOrDefault((Func)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)tileSet.TileWeights.Weights).FirstOrDefault((Func)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(); if (componentInChildren == null) { obj2 = null; } else { List connectorPrefabWeights = componentInChildren.ConnectorPrefabWeights; if (connectorPrefabWeights == null) { obj2 = null; } else { GameObjectWeight? obj3 = ((IEnumerable)connectorPrefabWeights).FirstOrDefault((Func)((GameObjectWeight prefab) => ((Object)prefab.GameObject).name == "MineDoorSpawn")); if (obj3 == null) { obj2 = null; } else { SpawnSyncedObject componentInChildren2 = obj3.GameObject.GetComponentInChildren(); 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(); 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)tileSet.TileWeights.Weights).FirstOrDefault((Func)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(); 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() : 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(); 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)__instance.VehiclesList).FirstOrDefault((Func)((GameObject vehicle) => ((Object)vehicle).name == "CompanyCruiser")).GetComponent().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() : 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() : 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().thisAudioSource.dopplerLevel = Plugin.configMusicDopplerLevel.Value; Plugin.Logger.LogDebug((object)"Doppler level: Record player"); break; case "Disco Ball": unlockable.prefabObject.GetComponentInChildren().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().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 list = new List(); List list2 = new List(); List list3 = new List(); Item val8 = null; foreach (Item items in StartOfRound.Instance.allItemsList.itemsList) { bool flag = false; switch (((Object)items).name) { case "Boombox": items.spawnPrefab.GetComponent().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(); ((Component)component).gameObject.AddComponent().walkieTalkie = component; Plugin.Logger.LogDebug((object)"Walkie talkie: Let's make some noise!"); break; } case "WeedKillerBottle": items.spawnPrefab.GetComponent().sprayAudio.loop = false; Plugin.Logger.LogDebug((object)"Loop: Weed killer"); break; } if (flag) { items.spawnPrefab.GetComponent().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)); } List list4 = new List(); foreach (Item items2 in StartOfRound.Instance.allItemsList.itemsList) { if (!((Object)(object)items2 == (Object)null)) { GameObject spawnPrefab = items2.spawnPrefab; if (Object.op_Implicit((Object)(object)((spawnPrefab != null) ? spawnPrefab.GetComponentInChildren() : null))) { list4.Add(((Object)items2).name); } } } foreach (Item items3 in StartOfRound.Instance.allItemsList.itemsList) { if (!((Object)(object)items3 == (Object)null)) { Plugin.Logger.LogInfo((object)(((Object)items3).name + " is " + (list4.Contains(((Object)items3).name) ? string.Empty : "NOT ") + "occluded")); } } } [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().dopplerLevel = 0.6f * Plugin.configMusicDopplerLevel.Value; Transform obj = val.Find("Music (1)"); AudioSource val2 = ((obj != null) ? ((Component)obj).GetComponent() : 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)__instance.buyableVehicles).FirstOrDefault((Func)((BuyableVehicle buyableVehicle) => buyableVehicle.vehicleDisplayName == "Cruiser")); if (val != null) { GameObject secondaryPrefab = val.secondaryPrefab; AudioSource val2 = ((secondaryPrefab != null) ? ((Component)secondaryPrefab.transform).GetComponent() : 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_006b: 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 && ((Object)((GrabbableObject)__instance).itemProperties).name != "FlashLaserPointer")) { 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(CozyLights), "SetAudio")] [HarmonyPostfix] private static void CozyLights_Post_SetAudio(CozyLights __instance) { if (!__instance.cozyLightsOn && __instance.turnOnAudio.isPlaying && __instance.turnOnAudio.volume > 0.3f) { AudioSource turnOnAudio = __instance.turnOnAudio; turnOnAudio.volume *= 0.3f; } } } [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 PlayerControllerB_Trans_DamagePlayerFromOtherClientClientRpc(IEnumerable instructions) { List 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("OnCollideWithEnemy")] [HarmonyTranspiler] private static IEnumerable BaboonBirdAI_Trans_OnCollideWithEnemy(IEnumerable 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 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[])(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[])(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(); } 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(CadaverBloomAI), "KillEnemy")] [HarmonyPostfix] private static void CadaverBloomAI_Post_KillEnemy(CadaverBloomAI __instance, bool destroy) { if (!destroy) { ((EnemyAI)__instance).creatureSFX.clip = null; AudioSource[] array = (AudioSource[])(object)new AudioSource[2] { __instance.breathingSFX, __instance.burstSource }; foreach (AudioSource obj in array) { obj.Stop(); obj.mute = true; } } } } [HarmonyPatch(typeof(MouthDogAI))] internal static class EyelessDogPatches { private const float TIME_DROP_CARRIED_BODY = 5.01f; private static Dictionary dogPitches = new Dictionary(); [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 MouthDogAI_Trans_EnterChaseMode(IEnumerable instructions) { List 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(); 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 ForestGiantAI_Trans_Animation(IEnumerable instructions) { List 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().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().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(); 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 BushWolfEnemy_Trans_HitEnemy(IEnumerable 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 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[])(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 MaskedPlayerEnemy_Trans_TeleportMaskedEnemy(IEnumerable instructions) { List 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((FindObjectsSortMode)0)?.FirstOrDefault((Func)((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 CentipedeAI_Trans_delayedShriek(IEnumerable 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 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[])(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 CentipedeAI_Trans_fallFromCeiling(IEnumerable 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 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[])(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"); } } } [HarmonyPatch("MakeChuckleClientRpc")] [HarmonyTranspiler] private static IEnumerable FlowerSnakeEnemy_Trans_MakeChuckleClientRpc(IEnumerable instructions) { List list = instructions.ToList(); FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyType), "audioClips"); 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_5 && list[i - 5].opcode == OpCodes.Ldfld && (FieldInfo)list[i - 5].operand == fieldInfo) { list[i - 1].opcode = OpCodes.Ldc_I4_4; Plugin.Logger.LogDebug((object)"Transpiler (Tulip snake): Remove wingflap from chuckle pool"); break; } } return list; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } [CompilerGenerated] internal sealed class <>z__ReadOnlyArray : IEnumerable, ICollection, IList, IEnumerable, IReadOnlyCollection, IReadOnlyList, ICollection, IList { 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.Count => _items.Length; T IReadOnlyList.this[int index] => _items[index]; int ICollection.Count => _items.Length; bool ICollection.IsReadOnly => true; T IList.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 IEnumerable.GetEnumerator() { return ((IEnumerable)_items).GetEnumerator(); } void ICollection.Add(T item) { throw new NotSupportedException(); } void ICollection.Clear() { throw new NotSupportedException(); } bool ICollection.Contains(T item) { return ((ICollection)_items).Contains(item); } void ICollection.CopyTo(T[] array, int arrayIndex) { ((ICollection)_items).CopyTo(array, arrayIndex); } bool ICollection.Remove(T item) { throw new NotSupportedException(); } int IList.IndexOf(T item) { return ((IList)_items).IndexOf(item); } void IList.Insert(int index, T item) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } }