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.9.0")]
[assembly: AssemblyInformationalVersion("1.9.9+790cb4bb050aff2274ea9856948a8f958a5ae8fc")]
[assembly: AssemblyProduct("EnemySoundFixes")]
[assembly: AssemblyTitle("EnemySoundFixes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.9.9.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.9"), (CompatibilityLevel)0, (VersionStrictness)0);
}
}
internal enum CruiserMute
{
Nothing = -1,
NotRadio,
All
}
[BepInPlugin("butterystancakes.lethalcompany.enemysoundfixes", "Enemy Sound Fixes", "1.9.9")]
[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.9";
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.9 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.9";
}
}
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_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(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(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<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();
}
}