Decompiled source of H3TVR v1.1.5
H3TVR.dll
Decompiled 5 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net.Sockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using FistVR; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.UI; using Valve.Newtonsoft.Json; using Valve.VR; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace H3TVR { public class AudioManager : MonoBehaviour { [CompilerGenerated] private sealed class <CleanupAudioSource>d__104 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string sourceKey; public float delay; public AudioManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CleanupAudioSource>d__104(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; if (<>4__this.activeSources.ContainsKey(sourceKey)) { if ((Object)(object)<>4__this.activeSources[sourceKey] != (Object)null && (Object)(object)((Component)<>4__this.activeSources[sourceKey]).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)<>4__this.activeSources[sourceKey]).gameObject); } <>4__this.activeSources.Remove(sourceKey); } 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(); } } [CompilerGenerated] private sealed class <LoadAudioClipCoroutine>d__76 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string filePath; public string effectKey; public AudioManager <>4__this; private string <url>5__1; private WWW <www>5__2; private AudioClip <clip>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadAudioClipCoroutine>d__76(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <url>5__1 = null; <www>5__2 = null; <clip>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <url>5__1 = "file://" + filePath; <www>5__2 = new WWW(<url>5__1); <>1__state = -3; <>2__current = <www>5__2; <>1__state = 1; return true; case 1: <>1__state = -3; if (string.IsNullOrEmpty(<www>5__2.error)) { <clip>5__3 = WWWAudioExtensions.GetAudioClip(<www>5__2, false, false, <>4__this.GetAudioType(filePath)); if ((Object)(object)<clip>5__3 != (Object)null) { ((Object)<clip>5__3).name = effectKey; <>4__this.audioClips[effectKey] = <clip>5__3; <>4__this.logger.LogDebug((object)("[AudioManager] Loaded: " + effectKey + " from " + filePath)); } <clip>5__3 = null; } else { <>4__this.logger.LogWarning((object)("[AudioManager] Failed to load " + Path.GetFileName(filePath) + ": " + <www>5__2.error)); } <>m__Finally1(); <www>5__2 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<www>5__2 != null) { ((IDisposable)<www>5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadCustomAudioFileCoroutine>d__96 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public string filePath; public string effectKey; public AudioManager <>4__this; private string <url>5__1; private WWW <www>5__2; private AudioClip <clip>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadCustomAudioFileCoroutine>d__96(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <url>5__1 = null; <www>5__2 = null; <clip>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_00a4: Unknown result type (might be due to invalid IL or missing references) try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <url>5__1 = "file://" + filePath; <www>5__2 = new WWW(<url>5__1); <>1__state = -3; <>2__current = <www>5__2; <>1__state = 1; return true; case 1: <>1__state = -3; if (string.IsNullOrEmpty(<www>5__2.error)) { <clip>5__3 = WWWAudioExtensions.GetAudioClip(<www>5__2, false, false, <>4__this.GetAudioType(filePath)); if ((Object)(object)<clip>5__3 != (Object)null) { ((Object)<clip>5__3).name = effectKey; <>4__this.audioClips[effectKey] = <clip>5__3; <>4__this.effectNameToFile[effectKey] = filePath; <>4__this.logger.LogInfo((object)("[AudioManager] Loaded custom: " + effectKey)); } <clip>5__3 = null; } <>m__Finally1(); <www>5__2 = null; return false; } } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<www>5__2 != null) { ((IDisposable)<www>5__2).Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string AUDIO_FOLDER = "H3TVR_Audio"; private const string AUDIO_PATHS_CONFIG = "H3TVR_AudioPaths.ini"; private const float DEFAULT_VOLUME = 0.7f; private const float DEFAULT_PITCH = 1f; private const float SPATIAL_BLEND_2D = 0f; private const float SPATIAL_BLEND_3D = 1f; private const int CLEANUP_FRAME_THRESHOLD = 5; private const float SYNC_LOAD_TIMEOUT = 30f; private H3TVRImproved plugin; private ManualLogSource logger; private bool isInitialized = false; private string audioFolderPath; private string audioPathsConfigFile; private Dictionary<string, AudioClip> audioClips = new Dictionary<string, AudioClip>(); private Dictionary<string, AudioSource> activeSources = new Dictionary<string, AudioSource>(); private Dictionary<string, string> effectNameToFile = new Dictionary<string, string>(); private List<string> audioSearchPaths = new List<string>(); private ConfigEntry<bool> enableAudioEffects; private ConfigEntry<float> masterVolume; private ConfigEntry<float> effectsVolume; private ConfigEntry<float> weaponSoundsVolume; private ConfigEntry<float> ambientSoundsVolume; private ConfigEntry<bool> enableSpatialAudio; private ConfigEntry<bool> enable3DAudio; private ConfigEntry<float> maxAudioDistance; private ConfigEntry<int> maxSimultaneousSounds; private ConfigEntry<float> shurikenVolume; private ConfigEntry<float> hydrationVolume; private ConfigEntry<float> slomoVolume; private ConfigEntry<float> dangerCloseVolume; private ConfigEntry<float> skittySubGunVolume; private ConfigEntry<float> destroyQuickbeltVolume; private ConfigEntry<float> wondertoyVolume; private ConfigEntry<string> customAudioDirectory1; private ConfigEntry<string> customAudioDirectory2; private ConfigEntry<string> customAudioDirectory3; private ConfigEntry<string> shurikenThrowPath; private ConfigEntry<string> shurikenSpawnPath; private ConfigEntry<string> hydrationDrinkPath; private ConfigEntry<string> hydrationSpawnPath; private ConfigEntry<string> slomoStartPath; private ConfigEntry<string> slomoEndPath; private ConfigEntry<string> slomoActivePath; private ConfigEntry<string> dangerClosePath; private ConfigEntry<string> explosionPath; private ConfigEntry<string> gunSpawnPath; private ConfigEntry<string> destroyQuickbeltPath; private ConfigEntry<string> itemDestroyPath; private ConfigEntry<string> wondertoySpawnPath; private ConfigEntry<string> wondertoyActivatePath; private ConfigEntry<string> uiConfirmPath; private ConfigEntry<string> uiErrorPath; private ConfigEntry<string> systemReadyPath; private ConfigEntry<string> stovepipeJamPath; private ConfigEntry<string> stovepipeDoubleFeedPath; private ConfigEntry<string> stovepipeFailureToFeedPath; private ConfigEntry<string> stovepipeFailureToEjectPath; private ConfigEntry<string> stovepipeFailureToFirePath; private ConfigEntry<string> stovepipeHangFirePath; private ConfigEntry<string> stovepipeClearJamPath; private ConfigEntry<string> stovepipeCyclingPath; private ConfigEntry<string> stovepipeGenericPath; public void Initialize(H3TVRImproved pluginInstance, ManualLogSource logSource) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) if (isInitialized) { return; } plugin = pluginInstance; logger = logSource; try { SetupConfiguration(); SetupAudioFolders(); LoadCustomPathsConfig(); LoadConfiguredPaths(); ScanForAudioFiles(); LoadAudioClips(); isInitialized = true; logger.LogInfo((object)$"[AudioManager] Initialized - Found {effectNameToFile.Count} audio files across {audioSearchPaths.Count} locations"); PlayEffect("system_ready", Vector3.zero, is3D: false); } catch (Exception ex) { logger.LogError((object)("[AudioManager] Init failed: " + ex.Message)); } } private void SetupConfiguration() { enableAudioEffects = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Audio", "EnableAudioEffects", true, "Enable all audio effects"); masterVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio", "MasterVolume", 1f, "Master volume (0.0-1.0)"); effectsVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio", "EffectsVolume", 0.8f, "Effects volume (0.0-1.0)"); weaponSoundsVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio", "WeaponSoundsVolume", 0.9f, "Weapon sounds volume (0.0-1.0)"); ambientSoundsVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio", "AmbientSoundsVolume", 0.6f, "Ambient sounds volume (0.0-1.0)"); enableSpatialAudio = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Audio", "EnableSpatialAudio", true, "Enable 3D positional audio"); enable3DAudio = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Audio", "Enable3DAudio", true, "Enable full 3D audio processing"); maxAudioDistance = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio", "MaxAudioDistance", 50f, "Max distance for 3D audio"); maxSimultaneousSounds = ((BaseUnityPlugin)plugin).Config.Bind<int>("Audio", "MaxSimultaneousSounds", 10, "Max simultaneous sounds"); shurikenVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "ShurikenVolume", 0.8f, "Shuriken sounds volume"); hydrationVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "HydrationVolume", 0.7f, "Hydration sounds volume"); slomoVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "SlomoVolume", 0.9f, "Slomo effects volume"); dangerCloseVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "DangerCloseVolume", 1f, "Danger close volume"); skittySubGunVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "SkittySubGunVolume", 0.8f, "Weapon spawn volume"); destroyQuickbeltVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "DestroyQuickbeltVolume", 0.6f, "Destruction volume"); wondertoyVolume = ((BaseUnityPlugin)plugin).Config.Bind<float>("Audio.Effects", "WondertoyVolume", 0.7f, "Wondertoy volume"); customAudioDirectory1 = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.CustomPaths", "CustomDirectory1", "", "Additional audio directory (can be anywhere on your computer, e.g., C:\\My Sounds\\Game Audio)"); customAudioDirectory2 = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.CustomPaths", "CustomDirectory2", "", "Additional audio directory (can be anywhere on your computer)"); customAudioDirectory3 = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.CustomPaths", "CustomDirectory3", "", "Additional audio directory (can be anywhere on your computer)"); shurikenThrowPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "ShurikenThrow", "", "Full path to shuriken throw sound (e.g., C:\\My Audio\\shuriken.wav). Leave empty for auto-detection."); shurikenSpawnPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "ShurikenSpawn", "", "Full path to shuriken spawn sound. Leave empty for auto-detection."); hydrationDrinkPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "HydrationDrink", "", "Full path to hydration drink sound. Leave empty for auto-detection."); hydrationSpawnPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "HydrationSpawn", "", "Full path to hydration spawn sound. Leave empty for auto-detection."); slomoStartPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "SlomoStart", "", "Full path to slomo start sound. Leave empty for auto-detection."); slomoEndPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "SlomoEnd", "", "Full path to slomo end sound. Leave empty for auto-detection."); slomoActivePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "SlomoActive", "", "Full path to slomo active loop sound. Leave empty for auto-detection."); dangerClosePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "DangerClose", "", "Full path to danger close sound. Leave empty for auto-detection."); explosionPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "Explosion", "", "Full path to explosion sound. Leave empty for auto-detection."); gunSpawnPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "GunSpawn", "", "Full path to gun spawn sound. Leave empty for auto-detection."); destroyQuickbeltPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "DestroyQuickbelt", "", "Full path to destroy quickbelt sound. Leave empty for auto-detection."); itemDestroyPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "ItemDestroy", "", "Full path to item destroy sound. Leave empty for auto-detection."); wondertoySpawnPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "WondertoySpawn", "", "Full path to wondertoy spawn sound. Leave empty for auto-detection."); wondertoyActivatePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "WondertoyActivate", "", "Full path to wondertoy activate sound. Leave empty for auto-detection."); uiConfirmPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "UIConfirm", "", "Full path to UI confirm sound. Leave empty for auto-detection."); uiErrorPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "UIError", "", "Full path to UI error sound. Leave empty for auto-detection."); systemReadyPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths", "SystemReady", "", "Full path to system ready sound. Leave empty for auto-detection."); stovepipeJamPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "WeaponJam", "", "Full path to weapon jam sound. Leave empty for auto-detection."); stovepipeDoubleFeedPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "DoubleFeed", "", "Full path to double feed sound. Leave empty for auto-detection."); stovepipeFailureToFeedPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "FailureToFeed", "", "Full path to failure to feed sound. Leave empty for auto-detection."); stovepipeFailureToEjectPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "FailureToEject", "", "Full path to failure to eject sound. Leave empty for auto-detection."); stovepipeFailureToFirePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "FailureToFire", "", "Full path to failure to fire sound. Leave empty for auto-detection."); stovepipeHangFirePath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "HangFire", "", "Full path to hang fire sound. Leave empty for auto-detection."); stovepipeClearJamPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "ClearJam", "", "Full path to clear jam sound. Leave empty for auto-detection."); stovepipeCyclingPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "Cycling", "", "Full path to cycling sound. Leave empty for auto-detection."); stovepipeGenericPath = ((BaseUnityPlugin)plugin).Config.Bind<string>("Audio.FilePaths.Stovepipe", "GenericMalfunction", "", "Full path to generic malfunction sound. Leave empty for auto-detection."); } private void LoadConfiguredPaths() { RegisterConfigPath("shuriken", shurikenThrowPath.Value); RegisterConfigPath("shuriken_spawn", shurikenSpawnPath.Value); RegisterConfigPath("hydration", hydrationDrinkPath.Value); RegisterConfigPath("hydration_spawn", hydrationSpawnPath.Value); RegisterConfigPath("slomo_start", slomoStartPath.Value); RegisterConfigPath("slomo_end", slomoEndPath.Value); RegisterConfigPath("slomo_active", slomoActivePath.Value); RegisterConfigPath("danger_close", dangerClosePath.Value); RegisterConfigPath("explosion", explosionPath.Value); RegisterConfigPath("gun_spawn", gunSpawnPath.Value); RegisterConfigPath("skitty_sub_gun", gunSpawnPath.Value); RegisterConfigPath("destroy_quickbelt", destroyQuickbeltPath.Value); RegisterConfigPath("item_destroy", itemDestroyPath.Value); RegisterConfigPath("wondertoy", wondertoySpawnPath.Value); RegisterConfigPath("wondertoy_activate", wondertoyActivatePath.Value); RegisterConfigPath("ui_confirm", uiConfirmPath.Value); RegisterConfigPath("ui_error", uiErrorPath.Value); RegisterConfigPath("system_ready", systemReadyPath.Value); RegisterConfigPath("stovepipe_jam", stovepipeJamPath.Value); RegisterConfigPath("stovepipe_malfunction", stovepipeJamPath.Value); RegisterConfigPath("stovepipe_double_feed", stovepipeDoubleFeedPath.Value); RegisterConfigPath("stovepipe_failure_to_feed", stovepipeFailureToFeedPath.Value); RegisterConfigPath("stovepipe_failure_to_eject", stovepipeFailureToEjectPath.Value); RegisterConfigPath("stovepipe_failure_to_fire", stovepipeFailureToFirePath.Value); RegisterConfigPath("stovepipe_hang_fire", stovepipeHangFirePath.Value); RegisterConfigPath("stovepipe_clear_jam", stovepipeClearJamPath.Value); RegisterConfigPath("stovepipe_cycling", stovepipeCyclingPath.Value); RegisterConfigPath("stovepipe_generic", stovepipeGenericPath.Value); } private void RegisterConfigPath(string effectKey, string filePath) { if (!string.IsNullOrEmpty(filePath)) { if (File.Exists(filePath)) { effectNameToFile[effectKey] = filePath; logger.LogInfo((object)("[AudioManager] Config path registered: " + effectKey + " -> " + filePath)); } else { logger.LogWarning((object)("[AudioManager] Config path not found for " + effectKey + ": " + filePath)); } } } private void SetupAudioFolders() { try { string directoryName = Path.GetDirectoryName(((BaseUnityPlugin)plugin).Info.Location); audioFolderPath = Path.Combine(directoryName, "H3TVR_Audio"); audioPathsConfigFile = Path.Combine(directoryName, "H3TVR_AudioPaths.ini"); if (!Directory.Exists(audioFolderPath)) { Directory.CreateDirectory(audioFolderPath); CreateReadme(); } audioSearchPaths.Add(audioFolderPath); AddSubdirectoriesRecursive(audioFolderPath); AddCustomDirectories(); logger.LogInfo((object)$"[AudioManager] Scanning {audioSearchPaths.Count} directories for audio files"); } catch (Exception ex) { logger.LogError((object)("[AudioManager] Folder setup failed: " + ex.Message)); } } private void AddCustomDirectories() { AddCustomDirectory(customAudioDirectory1.Value); AddCustomDirectory(customAudioDirectory2.Value); AddCustomDirectory(customAudioDirectory3.Value); } private void AddCustomDirectory(string path) { if (string.IsNullOrEmpty(path)) { return; } try { if (Directory.Exists(path)) { if (!audioSearchPaths.Contains(path)) { audioSearchPaths.Add(path); AddSubdirectoriesRecursive(path); logger.LogInfo((object)("[AudioManager] Added custom directory: " + path)); } } else { logger.LogWarning((object)("[AudioManager] Custom directory not found: " + path)); } } catch (Exception ex) { logger.LogWarning((object)("[AudioManager] Error adding custom directory " + path + ": " + ex.Message)); } } private void AddSubdirectoriesRecursive(string directory) { try { string[] directories = Directory.GetDirectories(directory); string[] array = directories; foreach (string text in array) { if (!audioSearchPaths.Contains(text)) { audioSearchPaths.Add(text); } AddSubdirectoriesRecursive(text); } } catch (Exception ex) { logger.LogWarning((object)("[AudioManager] Could not scan subdirectory: " + ex.Message)); } } private void LoadCustomPathsConfig() { if (!File.Exists(audioPathsConfigFile)) { CreatePathsConfigTemplate(); return; } try { string[] array = File.ReadAllLines(audioPathsConfigFile); int num = 0; string[] array2 = array; foreach (string text in array2) { if (text == null || text.Trim().Length == 0 || text.TrimStart(new char[0]).StartsWith("#") || text.TrimStart(new char[0]).StartsWith(";")) { continue; } string[] array3 = text.Split(new char[1] { '=' }, 2); if (array3.Length != 2) { continue; } string text2 = array3[0].Trim(); string text3 = array3[1].Trim(); if (File.Exists(text3)) { if (!effectNameToFile.ContainsKey(text2)) { effectNameToFile[text2] = text3; num++; logger.LogDebug((object)("[AudioManager] INI path loaded: " + text2 + " -> " + text3)); } } else { logger.LogWarning((object)("[AudioManager] File not found for " + text2 + ": " + text3)); } } if (num > 0) { logger.LogInfo((object)$"[AudioManager] Loaded {num} custom audio paths from INI config"); } } catch (Exception ex) { logger.LogError((object)("[AudioManager] Error loading custom paths config: " + ex.Message)); } } private void CreatePathsConfigTemplate() { string contents = "# H3TVR Enhanced Edition - Custom Audio Paths Configuration\r\n# ============================================================\r\n# \r\n# NOTE: You can now configure audio paths directly in BepInEx config!\r\n# This INI file is still supported for backwards compatibility.\r\n# BepInEx config paths take priority over this file.\r\n#\r\n# Use this file to point to audio files ANYWHERE on your computer!\r\n# Format: effectName=C:\\Full\\Path\\To\\Your\\Audio\\File.wav\r\n#\r\n# Supported formats: .wav, .ogg, .mp3, .aif, .aiff\r\n#\r\n# EXAMPLES:\r\n# shuriken=C:\\Users\\YourName\\Music\\Sound Effects\\shuriken_throw.wav\r\n# slomo_start=D:\\Game Audio\\slomo_start.ogg\r\n# explosion=E:\\Downloads\\explosion.mp3\r\n#\r\n# Available effect names:\r\n# -----------------------\r\n# Shuriken: shuriken, shuriken_spawn\r\n# Hydration: hydration, hydration_spawn\r\n# Slomo: slomo_start, slomo_end, slomo_active\r\n# Danger Close: danger_close, explosion\r\n# Weapons: gun_spawn, skitty_sub_gun\r\n# Destruction: destroy_quickbelt, item_destroy\r\n# Wondertoy: wondertoy, wondertoy_activate\r\n# UI: ui_confirm, ui_error\r\n# System: system_ready\r\n# Stovepipe: stovepipe_jam, stovepipe_malfunction, stovepipe_double_feed,\r\n# stovepipe_failure_to_feed, stovepipe_failure_to_eject,\r\n# stovepipe_failure_to_fire, stovepipe_hang_fire,\r\n# stovepipe_clear_jam, stovepipe_cycling, stovepipe_generic\r\n#\r\n# YOUR CUSTOM PATHS (uncomment and edit):\r\n# ========================================\r\n\r\n# shuriken=C:\\Path\\To\\Your\\shuriken_throw.wav\r\n# explosion=C:\\Path\\To\\Your\\explosion.wav\r\n# slomo_start=C:\\Path\\To\\Your\\slomo_start.ogg\r\n\r\n"; try { File.WriteAllText(audioPathsConfigFile, contents); logger.LogInfo((object)("[AudioManager] Created custom paths config template: " + audioPathsConfigFile)); } catch (Exception ex) { logger.LogWarning((object)("[AudioManager] Could not create paths config template: " + ex.Message)); } } private void CreateReadme() { string contents = "H3TVR Enhanced Edition - Audio Files\r\n====================================\r\n\r\nULTIMATE FLEXIBILITY - Configure audio files DIRECTLY in BepInEx config!\r\n\r\nMETHOD 1: BepInEx Config (RECOMMENDED - easiest!)\r\n Open BepInEx\\config\\com.h3tvr.improved.cfg\r\n Find [Audio.FilePaths] section\r\n Set full paths for each effect:\r\n ShurikenThrow = C:\\My Sounds\\shuriken.wav\r\n Explosion = D:\\Downloads\\boom.mp3\r\n\r\nMETHOD 2: Use H3TVR_AudioPaths.ini to point to files anywhere\r\n\r\nMETHOD 3: Place files in this folder (auto-detected by name)\r\n\r\nMETHOD 4: Add custom directories in BepInEx config\r\n\r\nSUPPORTED FORMATS: .wav, .ogg, .mp3, .aif, .aiff\r\n\r\nEFFECT FILE NAMES (case-insensitive, auto-detected):\r\n----------------------------------------------------\r\n\r\nSHURIKEN:\r\n - shuriken_throw.*\r\n - shuriken_spawn.*\r\n\r\nHYDRATION:\r\n - hydration_drink.*\r\n - hydration_spawn.*\r\n\r\nSLOMO:\r\n - slomo_start.*\r\n - slomo_end.*\r\n - slomo_active.*\r\n\r\nDANGER CLOSE:\r\n - danger_close.*\r\n - explosion.*\r\n\r\nWEAPONS:\r\n - gun_spawn.*\r\n\r\nDESTRUCTION:\r\n - destroy_quickbelt.*\r\n - item_destroy.*\r\n\r\nWONDERTOY:\r\n - wondertoy_spawn.*\r\n - wondertoy_activate.*\r\n\r\nUI SOUNDS:\r\n - ui_confirm.*\r\n - ui_error.*\r\n\r\nSYSTEM:\r\n - system_ready.*\r\n\r\nSTOVEPIPE (weapon malfunctions):\r\n - weapon_jam.*\r\n - double_feed.*\r\n - failure_to_feed.*\r\n - failure_to_eject.*\r\n - failure_to_fire.*\r\n - hang_fire.*\r\n - clear_jam.*\r\n - cycling.*\r\n - generic_malfunction.*\r\n\r\nPRIORITY ORDER:\r\n--------------\r\n1. BepInEx config paths (highest priority)\r\n2. H3TVR_AudioPaths.ini\r\n3. Auto-detected files in folders\r\n"; try { File.WriteAllText(Path.Combine(audioFolderPath, "README.txt"), contents); } catch { } } private void ScanForAudioFiles() { Dictionary<string, string> dictionary = new Dictionary<string, string> { { "shuriken", "shuriken_throw" }, { "shuriken_spawn", "shuriken_spawn" }, { "hydration", "hydration_drink" }, { "hydration_spawn", "hydration_spawn" }, { "slomo_start", "slomo_start" }, { "slomo_end", "slomo_end" }, { "slomo_active", "slomo_active" }, { "danger_close", "danger_close" }, { "explosion", "explosion" }, { "skitty_sub_gun", "gun_spawn" }, { "gun_spawn", "gun_spawn" }, { "destroy_quickbelt", "destroy_quickbelt" }, { "item_destroy", "item_destroy" }, { "wondertoy", "wondertoy_spawn" }, { "wondertoy_activate", "wondertoy_activate" }, { "ui_confirm", "ui_confirm" }, { "ui_error", "ui_error" }, { "system_ready", "system_ready" }, { "stovepipe_jam", "weapon_jam" }, { "stovepipe_malfunction", "weapon_jam" }, { "stovepipe_double_feed", "double_feed" }, { "stovepipe_failure_to_feed", "failure_to_feed" }, { "stovepipe_failure_to_eject", "failure_to_eject" }, { "stovepipe_failure_to_fire", "failure_to_fire" }, { "stovepipe_hang_fire", "hang_fire" }, { "stovepipe_clear_jam", "clear_jam" }, { "stovepipe_cycling", "cycling" }, { "stovepipe_generic", "generic_malfunction" } }; string[] array = new string[5] { ".wav", ".ogg", ".mp3", ".aif", ".aiff" }; foreach (string audioSearchPath in audioSearchPaths) { if (!Directory.Exists(audioSearchPath)) { continue; } try { string[] files = Directory.GetFiles(audioSearchPath); string[] array2 = files; foreach (string text in array2) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text); string value = Path.GetExtension(text).ToLower(); if (Array.IndexOf(array, value) == -1) { continue; } foreach (KeyValuePair<string, string> item in dictionary) { if (fileNameWithoutExtension.Equals(item.Value, StringComparison.OrdinalIgnoreCase)) { if (!effectNameToFile.ContainsKey(item.Key)) { effectNameToFile[item.Key] = text; logger.LogDebug((object)("[AudioManager] Auto-detected: " + item.Key + " -> " + Path.GetFileName(text))); } break; } } } } catch (Exception ex) { logger.LogWarning((object)("[AudioManager] Error scanning " + audioSearchPath + ": " + ex.Message)); } } logger.LogInfo((object)$"[AudioManager] Discovered {effectNameToFile.Count} audio files"); } private void LoadAudioClips() { foreach (KeyValuePair<string, string> item in effectNameToFile) { LoadAudioClip(item.Value, item.Key); } } private void LoadAudioClip(string filePath, string effectKey) { if (File.Exists(filePath)) { ((MonoBehaviour)this).StartCoroutine(LoadAudioClipCoroutine(filePath, effectKey)); } } private IEnumerator LoadAudioClipCoroutine(string filePath, string effectKey) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadAudioClipCoroutine>d__76(0) { <>4__this = this, filePath = filePath, effectKey = effectKey }; } private AudioType GetAudioType(string filePath) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) switch (Path.GetExtension(filePath).ToLower()) { case ".wav": return (AudioType)20; case ".ogg": return (AudioType)14; case ".mp3": return (AudioType)13; case ".aif": case ".aiff": return (AudioType)2; default: return (AudioType)20; } } public void PlayShurikenSound(string action = "throw", Vector3 position = default(Vector3), bool is3D = true, string customFilePath = null, float customVolume = -1f) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { string effectKey = ((action == "throw") ? "shuriken" : ("shuriken_" + action)); float volume = ((customVolume >= 0f) ? customVolume : (shurikenVolume.Value * effectsVolume.Value * masterVolume.Value)); PlayEffect(effectKey, position, is3D, volume, 1f, customFilePath); } } public void PlayHydrationSound(string action = "drink", Vector3 position = default(Vector3), bool is3D = true, string customFilePath = null, float customVolume = -1f) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { string effectKey = ((action == "drink") ? "hydration" : ("hydration_" + action)); float volume = ((customVolume >= 0f) ? customVolume : (hydrationVolume.Value * effectsVolume.Value * masterVolume.Value)); PlayEffect(effectKey, position, is3D, volume, 1f, customFilePath); } } public void PlaySlomoSound(string phase = "start", Vector3 position = default(Vector3), bool is3D = false, string customFilePath = null, float customVolume = -1f) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { string effectKey = "slomo_" + phase; float volume = ((customVolume >= 0f) ? customVolume : (slomoVolume.Value * ambientSoundsVolume.Value * masterVolume.Value)); float pitch = ((phase == "active") ? Time.timeScale : 1f); PlayEffect(effectKey, position, is3D, volume, pitch, customFilePath); } } public void PlayDangerCloseSound(string type = "danger_close", Vector3 position = default(Vector3), bool is3D = true, string customFilePath = null, float customVolume = -1f) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { float volume = ((customVolume >= 0f) ? customVolume : (dangerCloseVolume.Value * effectsVolume.Value * masterVolume.Value)); PlayEffect(type, position, is3D, volume, 1f, customFilePath); } } public void PlayWeaponSpawnSound(string type = "skitty_sub_gun", Vector3 position = default(Vector3), bool is3D = true, string customFilePath = null, float customVolume = -1f) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { float volume = ((customVolume >= 0f) ? customVolume : (skittySubGunVolume.Value * weaponSoundsVolume.Value * masterVolume.Value)); PlayEffect(type, position, is3D, volume, 1f, customFilePath); } } public void PlayDestructionSound(string type = "destroy_quickbelt", Vector3 position = default(Vector3), bool is3D = false, string customFilePath = null, float customVolume = -1f) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { float volume = ((customVolume >= 0f) ? customVolume : (destroyQuickbeltVolume.Value * effectsVolume.Value * masterVolume.Value)); PlayEffect(type, position, is3D, volume, 1f, customFilePath); } } public void PlayWondertoySound(string action = "spawn", Vector3 position = default(Vector3), bool is3D = true, string customFilePath = null, float customVolume = -1f) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { string effectKey = ((action == "spawn") ? "wondertoy" : ("wondertoy_" + action)); float volume = ((customVolume >= 0f) ? customVolume : (wondertoyVolume.Value * effectsVolume.Value * masterVolume.Value)); PlayEffect(effectKey, position, is3D, volume, 1f, customFilePath); } } public void PlayUISound(string type = "confirm", Vector3 position = default(Vector3), string customFilePath = null, float customVolume = -1f) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (enableAudioEffects.Value) { string effectKey = "ui_" + type; float volume = ((customVolume >= 0f) ? customVolume : (effectsVolume.Value * masterVolume.Value * 0.5f)); PlayEffect(effectKey, position, is3D: false, volume, 1f, customFilePath); } } public void PlayStovepipeSound(string action, Vector3 position, bool is3D = true, string customSound = null, float volume = 1f) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (isInitialized && enableAudioEffects.Value) { string stovepipeSoundKey = GetStovepipeSoundKey(action); PlayEffect(stovepipeSoundKey, position, is3D, volume, 1f, customSound); } } public void PlayStovepipeEffect(Vector3 position, string effectType) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) PlayStovepipeSound(effectType, position); } public void RescanAudioFiles() { logger.LogInfo((object)"[AudioManager] Rescanning for audio files..."); LoadConfiguredPaths(); LoadCustomPathsConfig(); ScanForAudioFiles(); LoadAudioClips(); } public bool RegisterCustomAudioFile(string effectKey, string absoluteFilePath) { if (string.IsNullOrEmpty(effectKey) || string.IsNullOrEmpty(absoluteFilePath)) { logger.LogWarning((object)"[AudioManager] Cannot register: empty key or path"); return false; } if (!File.Exists(absoluteFilePath)) { logger.LogWarning((object)("[AudioManager] File not found: " + absoluteFilePath)); return false; } effectNameToFile[effectKey] = absoluteFilePath; LoadAudioClip(absoluteFilePath, effectKey); logger.LogInfo((object)("[AudioManager] Registered custom audio: " + effectKey + " -> " + absoluteFilePath)); return true; } private void PlayEffect(string effectKey, Vector3 position, bool is3D, float volume = 0.7f, float pitch = 1f, string customFilePath = null) { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if (!enableAudioEffects.Value || !isInitialized || string.IsNullOrEmpty(effectKey)) { return; } volume = Mathf.Clamp(volume, 0f, 2f); pitch = Mathf.Clamp(pitch, 0.1f, 10f); if (activeSources.Count >= maxSimultaneousSounds.Value) { CleanupFinishedSources(); if (activeSources.Count >= maxSimultaneousSounds.Value) { return; } } AudioClip audioClip = GetAudioClip(effectKey, customFilePath); if (!((Object)(object)audioClip == (Object)null)) { CreateAndPlayAudioSource(effectKey, audioClip, position, is3D, volume, pitch); } } private AudioClip GetAudioClip(string effectKey, string customFilePath) { if (!string.IsNullOrEmpty(customFilePath)) { AudioClip val = LoadCustomAudioFileSync(customFilePath); if ((Object)(object)val != (Object)null) { return val; } } if (audioClips.ContainsKey(effectKey)) { return audioClips[effectKey]; } return null; } private void CreateAndPlayAudioSource(string effectKey, AudioClip clip, Vector3 position, bool is3D, float volume, float pitch) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_00ba: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("H3TVR_Audio_" + effectKey); AudioSource val2 = val.AddComponent<AudioSource>(); val2.clip = clip; val2.volume = Mathf.Clamp01(volume); val2.pitch = Mathf.Clamp(pitch, 0.1f, 3f); val2.playOnAwake = false; val2.loop = false; if (is3D && enableSpatialAudio.Value) { val2.spatialBlend = (enable3DAudio.Value ? 1f : 0.5f); val2.maxDistance = maxAudioDistance.Value; val2.rolloffMode = (AudioRolloffMode)0; val2.dopplerLevel = 0.1f; ((Component)val2).transform.position = position; } else { val2.spatialBlend = 0f; } string text = $"{effectKey}_{Time.time}_{Random.Range(1000, 9999)}"; activeSources[text] = val2; val2.Play(); ((MonoBehaviour)this).StartCoroutine(CleanupAudioSource(text, clip.length + 0.1f)); } public void StopEffectSounds(string effectKey) { if (string.IsNullOrEmpty(effectKey)) { return; } List<string> list = new List<string>(); foreach (KeyValuePair<string, AudioSource> activeSource in activeSources) { if (!activeSource.Key.StartsWith(effectKey + "_")) { continue; } if ((Object)(object)activeSource.Value != (Object)null) { activeSource.Value.Stop(); if ((Object)(object)((Component)activeSource.Value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)activeSource.Value).gameObject); } } list.Add(activeSource.Key); } foreach (string item in list) { activeSources.Remove(item); } } public void StopAllAudio() { foreach (KeyValuePair<string, AudioSource> activeSource in activeSources) { if ((Object)(object)activeSource.Value != (Object)null) { activeSource.Value.Stop(); if ((Object)(object)((Component)activeSource.Value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)activeSource.Value).gameObject); } } } activeSources.Clear(); } public bool LoadCustomAudioFile(string filePath, string effectKey, bool replaceExisting = true) { if (string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(effectKey)) { return false; } if (!File.Exists(filePath)) { return false; } if (effectNameToFile.ContainsKey(effectKey) && !replaceExisting) { return false; } ((MonoBehaviour)this).StartCoroutine(LoadCustomAudioFileCoroutine(filePath, effectKey)); return true; } private IEnumerator LoadCustomAudioFileCoroutine(string filePath, string effectKey) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadCustomAudioFileCoroutine>d__96(0) { <>4__this = this, filePath = filePath, effectKey = effectKey }; } private AudioClip LoadCustomAudioFileSync(string filePath) { //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) try { string text = filePath; if (!Path.IsPathRooted(filePath)) { text = null; foreach (string audioSearchPath in audioSearchPaths) { string text2 = Path.Combine(audioSearchPath, filePath); if (File.Exists(text2)) { text = text2; break; } } if (text == null) { return null; } } if (!File.Exists(text)) { return null; } string text3 = $"temp_{Path.GetFileName(text)}_{text.GetHashCode()}"; if (audioClips.ContainsKey(text3)) { return audioClips[text3]; } string text4 = "file://" + text; WWW val = new WWW(text4); try { float num = Time.realtimeSinceStartup + 30f; while (!val.isDone && string.IsNullOrEmpty(val.error)) { if (Time.realtimeSinceStartup > num) { return null; } Thread.Sleep(10); } if (string.IsNullOrEmpty(val.error)) { AudioClip audioClip = WWWAudioExtensions.GetAudioClip(val, false, false, GetAudioType(text)); if ((Object)(object)audioClip != (Object)null) { ((Object)audioClip).name = text3; audioClips[text3] = audioClip; return audioClip; } } } finally { ((IDisposable)val)?.Dispose(); } } catch { } return null; } public bool PlayLoadedEffect(string effectName, Vector3 position = default(Vector3), bool is3D = true, float volume = 0.8f, float pitch = 1f) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!enableAudioEffects.Value || !isInitialized) { return false; } if (!HasEffect(effectName)) { return false; } float volume2 = volume * effectsVolume.Value * masterVolume.Value; PlayEffect(effectName, position, is3D, volume2, pitch); return true; } public bool HasEffect(string effectName) { return !string.IsNullOrEmpty(effectName) && audioClips.ContainsKey(effectName); } public bool IsInitialized() { return isInitialized; } public void LogConfiguration() { logger.LogInfo((object)"[AudioManager] Configuration:"); logger.LogInfo((object)$" Enabled: {enableAudioEffects.Value}"); logger.LogInfo((object)$" Master Volume: {masterVolume.Value}"); logger.LogInfo((object)$" Loaded Clips: {audioClips.Count}"); logger.LogInfo((object)$" Active Sources: {activeSources.Count}"); logger.LogInfo((object)$" Search Paths: {audioSearchPaths.Count}"); logger.LogInfo((object)" Loaded Effects:"); foreach (KeyValuePair<string, string> item in effectNameToFile) { logger.LogInfo((object)(" " + item.Key + " -> " + item.Value)); } } private string GetStovepipeSoundKey(string action) { string text = action.ToLower().Replace(" ", "_"); if (text == "jam" || text == "malfunction") { return "stovepipe_jam"; } return "stovepipe_" + text; } private void CleanupFinishedSources() { List<string> list = new List<string>(); foreach (KeyValuePair<string, AudioSource> activeSource in activeSources) { if (!((Object)(object)activeSource.Value == (Object)null) && activeSource.Value.isPlaying) { continue; } list.Add(activeSource.Key); if ((Object)(object)activeSource.Value != (Object)null && (Object)(object)((Component)activeSource.Value).gameObject != (Object)null) { try { Object.Destroy((Object)(object)((Component)activeSource.Value).gameObject); } catch { } } } foreach (string item in list) { activeSources.Remove(item); } } private IEnumerator CleanupAudioSource(string sourceKey, float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <CleanupAudioSource>d__104(0) { <>4__this = this, sourceKey = sourceKey, delay = delay }; } private void OnDestroy() { StopAllAudio(); foreach (AudioClip value in audioClips.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } audioClips.Clear(); effectNameToFile.Clear(); audioSearchPaths.Clear(); ManualLogSource obj = logger; if (obj != null) { obj.LogInfo((object)"[AudioManager] Destroyed and cleaned up"); } } } public class EffectsManager : MonoBehaviour { [CompilerGenerated] private sealed class <ActivatePillowSlomo>d__9 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float duration; public EffectsManager <>4__this; private float <maxSlomoValue>5__1; private float <waitTime>5__2; private float <scaleSpeed>5__3; private float <returnSpeed>5__4; private float <originalTimeScale>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ActivatePillowSlomo>d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.plugin.GetSlomoConfig(out <maxSlomoValue>5__1, out <waitTime>5__2, out <scaleSpeed>5__3, out <returnSpeed>5__4); <originalTimeScale>5__5 = Time.timeScale; Time.timeScale = <maxSlomoValue>5__1; Time.fixedDeltaTime = Time.timeScale / SteamVR.instance.hmd_DisplayFrequency; <>4__this.slomoController?.UpdateMovementScale(Time.timeScale); <>4__this.logger.LogInfo((object)$"Pillow slow motion activated for {duration} seconds (scale: {<maxSlomoValue>5__1})"); <>2__current = (object)new WaitForSecondsRealtime(duration); <>1__state = 1; return true; case 1: <>1__state = -1; Time.timeScale = <originalTimeScale>5__5; Time.fixedDeltaTime = Time.timeScale / SteamVR.instance.hmd_DisplayFrequency; <>4__this.slomoController?.UpdateMovementScale(Time.timeScale); <>4__this.logger.LogInfo((object)"Pillow slow motion effect ended"); 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(); } } [CompilerGenerated] private sealed class <ActivatePillowZeroGravity>d__15 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float duration; public EffectsManager <>4__this; private GravityMode <originalGravityMode>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ActivatePillowZeroGravity>d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <originalGravityMode>5__1 = GM.Options.SimulationOptions.ObjectGravityMode; GM.Options.SimulationOptions.ObjectGravityMode = (GravityMode)3; GM.CurrentSceneSettings.RefreshGravity(); <>4__this.logger.LogInfo((object)$"Pillow zero gravity activated for {duration} seconds"); <>2__current = (object)new WaitForSecondsRealtime(duration); <>1__state = 1; return true; case 1: <>1__state = -1; GM.Options.SimulationOptions.ObjectGravityMode = <originalGravityMode>5__1; GM.CurrentSceneSettings.RefreshGravity(); <>4__this.logger.LogInfo((object)"Pillow zero gravity effect ended"); 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(); } } [CompilerGenerated] private sealed class <RealisticFallWait>d__14 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action onComplete; public EffectsManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RealisticFallWait>d__14(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSecondsRealtime(1f); <>1__state = 1; return true; case 1: <>1__state = -1; onComplete?.Invoke(); 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(); } } [CompilerGenerated] private sealed class <SlomoWait>d__8 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action onComplete; public EffectsManager <>4__this; private float <maxSlomoValue>5__1; private float <waitTime>5__2; private float <scaleSpeed>5__3; private float <returnSpeed>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <SlomoWait>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>4__this.plugin.GetSlomoConfig(out <maxSlomoValue>5__1, out <waitTime>5__2, out <scaleSpeed>5__3, out <returnSpeed>5__4); <>2__current = (object)new WaitForSecondsRealtime(<waitTime>5__2); <>1__state = 1; return true; case 1: <>1__state = -1; onComplete?.Invoke(); 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(); } } [CompilerGenerated] private sealed class <ZeroGWait>d__13 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public Action onComplete; public EffectsManager <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ZeroGWait>d__13(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(6f); <>1__state = 1; return true; case 1: <>1__state = -1; onComplete?.Invoke(); 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 H3TVRImproved plugin; private SlomoMovementController slomoController; private ManualLogSource logger; private static EffectsManager instance; public void Initialize(H3TVRImproved pluginInstance, SlomoMovementController controller, ManualLogSource logSource) { plugin = pluginInstance; slomoController = controller; logger = logSource; instance = this; } public static bool IsInitialized() { return (Object)(object)instance != (Object)null; } public void SlomoScaleDown() { plugin.GetSlomoConfig(out var maxSlomoValue, out var _, out var scaleSpeed, out var _); if (Time.timeScale > maxSlomoValue) { Time.timeScale -= scaleSpeed * Time.unscaledDeltaTime; Time.fixedDeltaTime = Time.timeScale / SteamVR.instance.hmd_DisplayFrequency; Time.timeScale = Mathf.Clamp(Time.timeScale, 0f, 1f); slomoController?.UpdateMovementScale(Time.timeScale); } if (Time.timeScale <= maxSlomoValue) { plugin.SetSlomoStatus("Wait"); } } public void SlomoReturn() { plugin.GetSlomoConfig(out var _, out var _, out var _, out var returnSpeed); if (Time.timeScale != 1f) { Time.timeScale += returnSpeed * Time.unscaledDeltaTime; Time.fixedDeltaTime = Time.timeScale / SteamVR.instance.hmd_DisplayFrequency; Time.timeScale = Mathf.Clamp(Time.timeScale, 0f, 1f); slomoController?.UpdateMovementScale(Time.timeScale); } } public IEnumerator SlomoWait(Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <SlomoWait>d__8(0) { <>4__this = this, onComplete = onComplete }; } public IEnumerator ActivatePillowSlomo(float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActivatePillowSlomo>d__9(0) { <>4__this = this, duration = duration }; } public void ZeroGravityBumpDown() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) try { GM.Options.SimulationOptions.ObjectGravityMode = (GravityMode)3; GM.CurrentSceneSettings.RefreshGravity(); } catch (Exception ex) { logger.LogError((object)("ZeroGravityBumpDown failed: " + ex.Message)); } } public void ZeroGravityBumpUp() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) try { GM.Options.SimulationOptions.ObjectGravityMode = (GravityMode)1; GM.CurrentSceneSettings.RefreshGravity(); } catch (Exception ex) { logger.LogError((object)("ZeroGravityBumpUp failed: " + ex.Message)); } } public void RealisticFall() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) try { GM.Options.SimulationOptions.ObjectGravityMode = (GravityMode)0; GM.CurrentSceneSettings.RefreshGravity(); } catch (Exception ex) { logger.LogError((object)("RealisticFall failed: " + ex.Message)); } } public IEnumerator ZeroGWait(Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ZeroGWait>d__13(0) { <>4__this = this, onComplete = onComplete }; } public IEnumerator RealisticFallWait(Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RealisticFallWait>d__14(0) { <>4__this = this, onComplete = onComplete }; } public IEnumerator ActivatePillowZeroGravity(float duration) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ActivatePillowZeroGravity>d__15(0) { <>4__this = this, duration = duration }; } public bool CheckVRButtonPress(string buttonName) { try { FVRViveHand[] array = GM.CurrentMovementManager?.Hands; if (array == null || array.Length == 0) { return false; } switch (buttonName.ToLower()) { case "leftx": return array.Length != 0 && (Object)(object)array[0] != (Object)null && array[0].Input.AXButtonDown; case "rightx": return array.Length > 1 && (Object)(object)array[1] != (Object)null && array[1].Input.AXButtonDown; case "lefty": return array.Length != 0 && (Object)(object)array[0] != (Object)null && array[0].Input.BYButtonDown; case "righty": return array.Length > 1 && (Object)(object)array[1] != (Object)null && array[1].Input.BYButtonDown; case "leftgrip": return array.Length != 0 && (Object)(object)array[0] != (Object)null && array[0].Input.GripDown; case "rightgrip": return array.Length > 1 && (Object)(object)array[1] != (Object)null && array[1].Input.GripDown; case "lefttrigger": return array.Length != 0 && (Object)(object)array[0] != (Object)null && array[0].Input.TriggerDown; case "righttrigger": return array.Length > 1 && (Object)(object)array[1] != (Object)null && array[1].Input.TriggerDown; case "lefttouchpad": return array.Length != 0 && (Object)(object)array[0] != (Object)null && array[0].Input.TouchpadDown; case "righttouchpad": return array.Length > 1 && (Object)(object)array[1] != (Object)null && array[1].Input.TouchpadDown; default: logger.LogWarning((object)("Unknown VR button configuration: " + buttonName + ". Using default LeftX.")); return array.Length != 0 && (Object)(object)array[0] != (Object)null && array[0].Input.AXButtonDown; } } catch (Exception ex) { logger.LogError((object)("CheckVRButtonPress failed for button " + buttonName + ": " + ex.Message)); return false; } } public void EnableMeatHands() { try { FVRViveHand[] array = GM.CurrentMovementManager?.Hands; if (array == null || array.Length < 2) { logger.LogWarning((object)"Cannot enable meat hands: Hand references not available"); return; } array[0].SpawnSausageFingers(); array[1].SpawnSausageFingers(); logger.LogInfo((object)"Meat hands enabled"); } catch (Exception ex) { logger.LogError((object)("EnableMeatHands failed: " + ex.Message)); } } public static void PlayStovepipeParticles(Vector3 position, StovepipeIntegrationManager.MalfunctionType malfunctionType) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)instance == (Object)null) { EffectsManager effectsManager = instance; if (effectsManager != null) { ManualLogSource obj = effectsManager.logger; if (obj != null) { obj.LogWarning((object)"EffectsManager not initialized for Stovepipe particles"); } } return; } GameObject val = CreateStovepipeParticleEffect(position, malfunctionType); if ((Object)(object)val != (Object)null) { ManualLogSource obj2 = instance.logger; if (obj2 != null) { obj2.LogDebug((object)$"Playing Stovepipe particle effect for {malfunctionType} at {position}"); } Object.Destroy((Object)(object)val, 3f); } } catch (Exception ex) { EffectsManager effectsManager2 = instance; if (effectsManager2 != null) { ManualLogSource obj3 = effectsManager2.logger; if (obj3 != null) { obj3.LogError((object)("PlayStovepipeParticles failed: " + ex.Message)); } } } } private static GameObject CreateStovepipeParticleEffect(Vector3 position, StovepipeIntegrationManager.MalfunctionType malfunctionType) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject($"StovepipeEffect_{malfunctionType}"); val.transform.position = position; ParticleSystem val2 = val.AddComponent<ParticleSystem>(); MainModule main = val2.main; EmissionModule emission = val2.emission; ShapeModule shape = val2.shape; VelocityOverLifetimeModule velocityOverLifetime = val2.velocityOverLifetime; switch (malfunctionType) { case StovepipeIntegrationManager.MalfunctionType.Stovepipe: ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.8f, 0.6f, 0.2f, 0.8f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.02f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(20f); break; case StovepipeIntegrationManager.MalfunctionType.DoubleFeed: ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.7f, 0.7f, 0.2f, 0.9f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.015f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.5f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(30f); break; case StovepipeIntegrationManager.MalfunctionType.FailureToEject: ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.6f, 0.4f, 0.2f, 0.7f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.018f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(2.5f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(15f); break; case StovepipeIntegrationManager.MalfunctionType.FailureToFeed: ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.8f, 0.8f, 0.3f, 0.6f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.012f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(25f); break; case StovepipeIntegrationManager.MalfunctionType.DirtyGun: ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.3f, 0.3f, 0.3f, 0.8f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.008f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(3f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(40f); break; default: ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.5f, 0.5f, 0.5f, 0.6f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.01f); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(1.5f); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(20f); break; } ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.5f); ((MainModule)(ref main)).maxParticles = 50; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)4; ((ShapeModule)(ref shape)).angle = 15f; ((ShapeModule)(ref shape)).radius = 0.05f; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).enabled = true; ((VelocityOverLifetimeModule)(ref velocityOverLifetime)).space = (ParticleSystemSimulationSpace)0; return val; } catch (Exception ex) { EffectsManager effectsManager = instance; if (effectsManager != null) { ManualLogSource obj = effectsManager.logger; if (obj != null) { obj.LogError((object)("CreateStovepipeParticleEffect failed: " + ex.Message)); } } return null; } } public static void CreateMalfunctionSmokeEffect(Vector3 position, float intensity = 1f) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)instance == (Object)null)) { GameObject val = new GameObject("MalfunctionSmoke"); val.transform.position = position; ParticleSystem val2 = val.AddComponent<ParticleSystem>(); MainModule main = val2.main; EmissionModule emission = val2.emission; ShapeModule shape = val2.shape; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.2f, 0.2f, 0.2f, 0.6f)); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(0.1f * intensity); ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(5f); ((MainModule)(ref main)).startSpeed = MinMaxCurve.op_Implicit(0.2f); ((MainModule)(ref main)).maxParticles = (int)(30f * intensity); ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(10f * intensity); ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)10; ((ShapeModule)(ref shape)).radius = 0.03f; Object.Destroy((Object)(object)val, 6f); ManualLogSource obj = instance.logger; if (obj != null) { obj.LogDebug((object)$"Created malfunction smoke effect at {position} with intensity {intensity}"); } } } catch (Exception ex) { EffectsManager effectsManager = instance; if (effectsManager != null) { ManualLogSource obj2 = effectsManager.logger; if (obj2 != null) { obj2.LogError((object)("CreateMalfunctionSmokeEffect failed: " + ex.Message)); } } } } } public class EnhancedChatSpawner : MonoBehaviour { public struct ChatSosigStats { public int ActiveAllies; public int ActiveEnemies; public int QueueLength; public int TotalSpawned; } public enum SpawnPriority { Low, Normal, High, Immediate } [CompilerGenerated] private sealed class <CleanupCoroutine>d__49 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public EnhancedChatSpawner <>4__this; private WaitForSeconds <wait>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <CleanupCoroutine>d__49(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(10f); break; case 1: <>1__state = -1; <>4__this.CleanupDeadSosigs(); break; } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <LoadTemplatesDelayed>d__33 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public EnhancedChatSpawner <>4__this; private SosigEnemyTemplate[] <sosigObjects>5__1; private SosigEnemyTemplate[] <>s__2; private int <>s__3; private SosigEnemyTemplate <template>5__4; private Exception <ex>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <LoadTemplatesDelayed>d__33(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <sosigObjects>5__1 = null; <>s__2 = null; <template>5__4 = null; <ex>5__5 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; try { <sosigObjects>5__1 = Resources.FindObjectsOfTypeAll<SosigEnemyTemplate>(); if (<sosigObjects>5__1 != null && <sosigObjects>5__1.Length != 0) { <>4__this.cachedSosigTemplates = <sosigObjects>5__1; <>s__2 = <>4__this.cachedSosigTemplates; for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++) { <template>5__4 = <>s__2[<>s__3]; if ((Object)(object)<template>5__4 != (Object)null) { <>4__this.allyTemplates.Add(<template>5__4); <>4__this.enemyTemplates.Add(<template>5__4); } <template>5__4 = null; } <>s__2 = null; if (<>4__this.cachedSosigTemplates.Length != 0) { <>4__this.defaultAllyTemplate = <>4__this.cachedSosigTemplates[0]; } ManualLogSource logger = <>4__this.logger; if (logger != null) { logger.LogInfo((object)$"Loaded {<>4__this.allyTemplates.Count} sosig templates"); } } else { ManualLogSource logger2 = <>4__this.logger; if (logger2 != null) { logger2.LogWarning((object)"No sosig templates found - spawning may be limited"); } } <sosigObjects>5__1 = null; } catch (Exception ex) { <ex>5__5 = ex; ManualLogSource logger3 = <>4__this.logger; if (logger3 != null) { logger3.LogError((object)("Template loading failed: " + <ex>5__5.Message)); } } 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(); } } [CompilerGenerated] private sealed class <UpdateSosigsCoroutine>d__46 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public EnhancedChatSpawner <>4__this; private WaitForSeconds <wait>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <UpdateSosigsCoroutine>d__46(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <wait>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <wait>5__1 = new WaitForSeconds(1f); break; case 1: <>1__state = -1; <>4__this.UpdateAllySosigs(); <>4__this.UpdateEnemySosigs(); break; } <>2__current = <wait>5__1; <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public static List<Sosig> spawnedChatters = new List<Sosig>(); public static List<Sosig> spawnedEnemyChatters = new List<Sosig>(); private H3TVRImproved plugin; private ManualLogSource logger; private TwitchChatManager twitchManager; [Header("Sosig Templates")] public SosigEnemyTemplate defaultAllyTemplate; public List<SosigEnemyTemplate> allyTemplates = new List<SosigEnemyTemplate>(); public List<SosigEnemyTemplate> enemyTemplates = new List<SosigEnemyTemplate>(); private SosigEnemyTemplate[] cachedSosigTemplates; public GameObject nameplateAlly; public GameObject nameplateEnemy; public string SpawnerName = "ChatUser"; private ConfigEntry<int> maxAllySosigs; private ConfigEntry<int> maxEnemySosigs; private ConfigEntry<float> spawnCooldown; private ConfigEntry<bool> enableNameplates; private ConfigEntry<float> sosigLifetime; private ConfigEntry<bool> enableAutoCleanup; private ConfigEntry<float> enemyIFF; private ConfigEntry<KeyCode> spawnAllyKey; private ConfigEntry<KeyCode> spawnEnemyKey; private ConfigEntry<KeyCode> clearSosigsKey; private ConfigEntry<float> followDistance; private ConfigEntry<float> enemyAggressionDistance; private float lastSpawnTime; private static readonly LayerMask EnvironmentMask = LayerMask.op_Implicit(LayerMask.GetMask(new string[1] { "Environment" })); public static EnhancedChatSpawner Instance { get; private set; } public void Initialize(H3TVRImproved pluginInstance, ManualLogSource logSource) { if ((Object)(object)Instance != (Object)null) { Object.Destroy((Object)(object)this); return; } Instance = this; plugin = pluginInstance; logger = logSource; InitializeConfiguration(); InitializeSosigTemplates(); ManualLogSource obj = logger; if (obj != null) { obj.LogInfo((object)"Enhanced Chat Spawner initialized (H3TwitchTools style)"); } ((MonoBehaviour)this).StartCoroutine(UpdateSosigsCoroutine()); ((MonoBehaviour)this).StartCoroutine(CleanupCoroutine()); } private void InitializeConfiguration() { H3TVRImproved h3TVRImproved = plugin; if (((h3TVRImproved != null) ? ((BaseUnityPlugin)h3TVRImproved).Config : null) == null) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)"Plugin config is null"); } return; } try { maxAllySosigs = ((BaseUnityPlugin)plugin).Config.Bind<int>("Chat Spawner", "MaxAllySosigs", 8, "Maximum ally sosigs"); maxEnemySosigs = ((BaseUnityPlugin)plugin).Config.Bind<int>("Chat Spawner", "MaxEnemySosigs", 8, "Maximum enemy sosigs"); spawnCooldown = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "SpawnCooldown", 2f, "Cooldown between spawns"); enableNameplates = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner", "EnableNameplates", true, "Show nameplates above sosigs"); sosigLifetime = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "SosigLifetime", 300f, "Sosig lifetime in seconds (0 = infinite)"); enableAutoCleanup = ((BaseUnityPlugin)plugin).Config.Bind<bool>("Chat Spawner", "EnableAutoCleanup", true, "Auto cleanup dead sosigs"); enemyIFF = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "EnemyIFF", 1f, "Enemy IFF code"); followDistance = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "FollowDistance", 6f, "Distance for allies to follow player"); enemyAggressionDistance = ((BaseUnityPlugin)plugin).Config.Bind<float>("Chat Spawner", "EnemyAggressionDistance", 20f, "Distance at which enemies become aggressive"); spawnAllyKey = ((BaseUnityPlugin)plugin).Config.Bind<KeyCode>("Chat Spawner Keys", "SpawnAllyKey", (KeyCode)112, "Spawn ally key"); spawnEnemyKey = ((BaseUnityPlugin)plugin).Config.Bind<KeyCode>("Chat Spawner Keys", "SpawnEnemyKey", (KeyCode)111, "Spawn enemy key"); clearSosigsKey = ((BaseUnityPlugin)plugin).Config.Bind<KeyCode>("Chat Spawner Keys", "ClearSosigsKey", (KeyCode)127, "Clear sosigs key"); ManualLogSource obj2 = logger; if (obj2 != null) { obj2.LogInfo((object)"Configuration initialized successfully"); } } catch (Exception ex) { ManualLogSource obj3 = logger; if (obj3 != null) { obj3.LogError((object)("Config init failed: " + ex.Message)); } } } private void InitializeSosigTemplates() { try { ((MonoBehaviour)this).StartCoroutine(LoadTemplatesDelayed()); } catch (Exception ex) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)("Template initialization failed: " + ex.Message)); } } } private IEnumerator LoadTemplatesDelayed() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <LoadTemplatesDelayed>d__33(0) { <>4__this = this }; } public void SpawningSequence(string username) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) try { if (spawnedChatters.Count >= maxAllySosigs.Value) { ManualLogSource obj = logger; if (obj != null) { obj.LogWarning((object)"Max ally sosigs reached"); } return; } if (Time.time - lastSpawnTime < spawnCooldown.Value) { ManualLogSource obj2 = logger; if (obj2 != null) { obj2.LogWarning((object)"Spawn cooldown active"); } return; } SosigEnemyTemplate randomTemplate = GetRandomTemplate(isFriendly: true); if ((Object)(object)randomTemplate == (Object)null) { ManualLogSource obj3 = logger; if (obj3 != null) { obj3.LogError((object)"No ally template available"); } return; } Vector3 pos = CalculateAllySpawnPoint(); Quaternion identity = Quaternion.identity; Sosig val = SpawnSosig(randomTemplate, pos, identity, 0); if ((Object)(object)val != (Object)null) { SetupAllyBehavior(val); if (enableNameplates.Value && (Object)(object)nameplateAlly != (Object)null) { AttachNameplate(val, username ?? "Ally", nameplateAlly, isEnemy: false); } spawnedChatters.Add(val); lastSpawnTime = Time.time; ManualLogSource obj4 = logger; if (obj4 != null) { obj4.LogInfo((object)("Spawned ally sosig for " + username)); } } } catch (Exception ex) { ManualLogSource obj5 = logger; if (obj5 != null) { obj5.LogError((object)("Ally spawn failed: " + ex.Message)); } } } public void SpawningSequenceEnemy(int IFF, string username) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) try { if (spawnedEnemyChatters.Count >= maxEnemySosigs.Value) { ManualLogSource obj = logger; if (obj != null) { obj.LogWarning((object)"Max enemy sosigs reached"); } return; } if (Time.time - lastSpawnTime < spawnCooldown.Value) { ManualLogSource obj2 = logger; if (obj2 != null) { obj2.LogWarning((object)"Spawn cooldown active"); } return; } SosigEnemyTemplate randomTemplate = GetRandomTemplate(isFriendly: false); if ((Object)(object)randomTemplate == (Object)null) { ManualLogSource obj3 = logger; if (obj3 != null) { obj3.LogError((object)"No enemy template available"); } return; } Vector3 pos = CalculateEnemySpawnPoint(); Quaternion identity = Quaternion.identity; int iFF = ((IFF > 0) ? IFF : Mathf.Max(1, (int)enemyIFF.Value)); Sosig val = SpawnSosig(randomTemplate, pos, identity, iFF); if ((Object)(object)val != (Object)null) { SetupEnemyBehavior(val); if (enableNameplates.Value && (Object)(object)nameplateEnemy != (Object)null) { AttachNameplate(val, username ?? "Enemy", nameplateEnemy, isEnemy: true); } spawnedEnemyChatters.Add(val); lastSpawnTime = Time.time; ManualLogSource obj4 = logger; if (obj4 != null) { obj4.LogInfo((object)("Spawned enemy sosig for " + username)); } } } catch (Exception ex) { ManualLogSource obj5 = logger; if (obj5 != null) { obj5.LogError((object)("Enemy spawn failed: " + ex.Message)); } } } private Sosig SpawnSosig(SosigEnemyTemplate template, Vector3 pos, Quaternion rot, int IFF) { //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)template == (Object)null || template.SosigPrefabs == null || template.SosigPrefabs.Count == 0) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)"Invalid template"); } return null; } FVRObject val = template.SosigPrefabs[Random.Range(0, template.SosigPrefabs.Count)]; if ((Object)(object)((val != null) ? ((AnvilAsset)val).GetGameObject() : null) == (Object)null) { ManualLogSource obj2 = logger; if (obj2 != null) { obj2.LogError((object)"Invalid prefab"); } return null; } GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), pos, rot); Sosig componentInChildren = val2.GetComponentInChildren<Sosig>(); if ((Object)(object)componentInChildren == (Object)null) { Object.Destroy((Object)(object)val2); return null; } if (template.ConfigTemplates != null && template.ConfigTemplates.Count > 0) { SosigConfigTemplate val3 = template.ConfigTemplates[Random.Range(0, template.ConfigTemplates.Count)]; if ((Object)(object)val3 != (Object)null) { componentInChildren.Configure(val3); } } componentInChildren.E.IFFCode = IFF; if (IFF < componentInChildren.Priority.IFFChart.Length) { componentInChildren.Priority.IFFChart[IFF] = true; } EquipWeapons(componentInChildren, template, pos, rot); if (template.OutfitConfig != null && template.OutfitConfig.Count > 0) { ApplyOutfit(componentInChildren, template.OutfitConfig[Random.Range(0, template.OutfitConfig.Count)]); } return componentInChildren; } catch (Exception ex) { ManualLogSource obj3 = logger; if (obj3 != null) { obj3.LogError((object)("Sosig spawn failed: " + ex.Message)); } return null; } } private void EquipWeapons(Sosig sosig, SosigEnemyTemplate template, Vector3 pos, Quaternion rot) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) try { if (template.WeaponOptions != null && template.WeaponOptions.Count > 0) { EquipWeapon(sosig, template.WeaponOptions[Random.Range(0, template.WeaponOptions.Count)], pos, rot); } if (template.WeaponOptions_Secondary != null && template.WeaponOptions_Secondary.Count > 0) { EquipWeapon(sosig, template.WeaponOptions_Secondary[Random.Range(0, template.WeaponOptions_Secondary.Count)], pos, rot); } if (template.WeaponOptions_Tertiary != null && template.WeaponOptions_Tertiary.Count > 0) { EquipWeapon(sosig, template.WeaponOptions_Tertiary[Random.Range(0, template.WeaponOptions_Tertiary.Count)], pos, rot); } } catch (Exception ex) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)("Weapon equip failed: " + ex.Message)); } } } private void EquipWeapon(Sosig sosig, FVRObject weaponObj, Vector3 pos, Quaternion rot) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Invalid comparison between Unknown and I4 //IL_008d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)((weaponObj != null) ? ((AnvilAsset)weaponObj).GetGameObject() : null) == (Object)null) { return; } GameObject val = Object.Instantiate<GameObject>(((AnvilAsset)weaponObj).GetGameObject(), pos + Vector3.up * 0.1f, rot); SosigWeapon component = val.GetComponent<SosigWeapon>(); if ((Object)(object)component != (Object)null) { component.SetAutoDestroy(true); component.O.SpawnLockable = false; component.SetAmmoClamping(true); component.IsShakeReloadable = false; if ((int)component.Type == 0) { sosig.Inventory.FillAmmoWithType(component.AmmoType); } sosig.Inventory.Init(); sosig.Inventory.FillAllAmmo(); sosig.InitHands(); sosig.ForceEquip(component); } } catch (Exception ex) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)("Weapon equip error: " + ex.Message)); } } } private void ApplyOutfit(Sosig sosig, SosigOutfitConfig outfit) { try { if (!((Object)(object)outfit == (Object)null) && sosig.Links.Count >= 4) { if (Random.value < outfit.Chance_Headwear) { SpawnAccessory(outfit.Headwear, sosig.Links[0]); } if (Random.value < outfit.Chance_Facewear) { SpawnAccessory(outfit.Facewear, sosig.Links[0]); } if (Random.value < outfit.Chance_Eyewear) { SpawnAccessory(outfit.Eyewear, sosig.Links[0]); } if (Random.value < outfit.Chance_Torsowear) { SpawnAccessory(outfit.Torsowear, sosig.Links[1]); } if (Random.value < outfit.Chance_Pantswear) { SpawnAccessory(outfit.Pantswear, sosig.Links[2]); } if (sosig.Links.Count > 3 && Random.value < outfit.Chance_Pantswear_Lower) { SpawnAccessory(outfit.Pantswear_Lower, sosig.Links[3]); } if (Random.value < outfit.Chance_Backpacks) { SpawnAccessory(outfit.Backpacks, sosig.Links[1]); } if (Random.value < outfit.Chance_TorosDecoration) { SpawnAccessory(outfit.TorosDecoration, sosig.Links[1]); } } } catch (Exception ex) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)("Outfit apply failed: " + ex.Message)); } } } private void SpawnAccessory(List<FVRObject> accessories, SosigLink link) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (accessories == null || accessories.Count == 0 || (Object)(object)link == (Object)null) { return; } try { FVRObject val = accessories[Random.Range(0, accessories.Count)]; if (!((Object)(object)((val != null) ? ((AnvilAsset)val).GetGameObject() : null) == (Object)null)) { GameObject val2 = Object.Instantiate<GameObject>(((AnvilAsset)val).GetGameObject(), ((Component)link).transform.position, ((Component)link).transform.rotation); val2.transform.SetParent(((Component)link).transform); SosigWearable component = val2.GetComponent<SosigWearable>(); if ((Object)(object)component != (Object)null) { component.RegisterWearable(link); } } } catch (Exception ex) { ManualLogSource obj = logger; if (obj != null) { obj.LogError((object)("Accessory spawn failed: " + ex.Message)); } } } private void SetupAllyBehavior(Sosig sosig) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) try { FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody; object obj; if (currentPlayerBody == null) { obj = null; } else { Transform head = currentPlayerBody.Head; obj = ((head != null) ? ((Component)head).transform : null); } if (!((Object)obj == (Object)null)) { Vector3 position = ((Component)GM.CurrentPlayerBody.Head).transform.position; float num = (float)(Random.Range(0, 2) * 2 - 1) * Random.Range(0.75f, 2.5f); float num2 = (float)(Random.Range(0, 2) * 2 - 1) * Random.Range(0.75f, 2.5f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(position.x + num, position.y, position.z + num2); sosig.CommandAssaultPoint(val); sosig.FallbackOrder = (SosigOrder)4; } } catch (Exception ex) { ManualLogSource obj2 = logger; if (obj2 != null) { obj2.LogError((object)("Ally behavior setup failed: " + ex.Message)); } } } private void SetupEnemyBehavior(Sosig sosig) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) try { FVRPlayerBody currentPlayerBody = GM.CurrentPlayerBody; if (!((Object)(object)((currentPlayerBody != null) ? ((Component)currentPlayerBody).transform : null) == (Object)null)) { sosig.CommandAssaultPoint(((Component)GM.CurrentPlayerBody).transform.position); sosig.FallbackOrder = (SosigOrder)4; } } catch (Exception ex) { ManualLogSource obj = logger; if (ob