Decompiled source of Elias Hadi Modpack v1.0.0
BepInEx/plugins/BGN-PizzaTowerEscapeMusic/PizzaTowerEscapeMusic.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PizzaTowerEscapeMusic.Scripting; using PizzaTowerEscapeMusic.Scripting.Conditions; using PizzaTowerEscapeMusic.Scripting.ScriptEvents; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("PizzaTowerEscapeMusic")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Plays music from Pizza Tower when the early ship leave alert appears")] [assembly: AssemblyFileVersion("2.4.0.0")] [assembly: AssemblyInformationalVersion("2.4.0")] [assembly: AssemblyProduct("PizzaTowerEscapeMusic")] [assembly: AssemblyTitle("PizzaTowerEscapeMusic")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.4.0.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.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; } } [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 PizzaTowerEscapeMusic { public class Configuration { private readonly ConfigFile config; internal ConfigEntry<float> volumeMaster; internal ConfigEntry<string> scriptingScripts; public Configuration(ConfigFile config) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown this.config = config; scriptingScripts = config.Bind<string>("Scripting", "Scripts", "Default", new ConfigDescription("The names of the JSON script files that will be loaded (Separated by commas, do not put a space after the commas)", (AcceptableValueBase)null, Array.Empty<object>())); volumeMaster = config.Bind<float>("Volume", "Master", 0.5f, new ConfigDescription("The volume of the music as a whole, all volumes are scaled by this value", (AcceptableValueBase)null, Array.Empty<object>())); RemoveObsoleteEntries(); } private void RemoveObsoleteEntry(string section, string key) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition(section, key); config.Bind<string>(val, "", (ConfigDescription)null); config.Remove(val); } private void ReplaceObsoleteEntry<T>(string section, string key, ConfigEntry<T> replacement) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition(section, key); ConfigEntry<T> val2 = config.Bind<T>(val, (T)((ConfigEntryBase)replacement).DefaultValue, (ConfigDescription)null); if (!EqualityComparer<T>.Default.Equals(val2.Value, (T)((ConfigEntryBase)replacement).DefaultValue)) { replacement.Value = val2.Value; } config.Remove(val); } private void RemoveObsoleteEntries() { RemoveObsoleteEntry("Volume", "InsideFacility"); RemoveObsoleteEntry("Volume", "OutsideFacility"); RemoveObsoleteEntry("Volume", "InsideShip"); RemoveObsoleteEntry("Volume", "CrouchingScale"); RemoveObsoleteEntry("Music", "InsideFacility"); RemoveObsoleteEntry("Music", "OutsideFacility"); RemoveObsoleteEntry("Music", "HeavyWeather"); ReplaceObsoleteEntry<string>("Scripting", "Script", scriptingScripts); config.Save(); } } internal static class CustomManager { public static string GetFilePath(string path, string fallbackPath) { string[] directories = Directory.GetDirectories(Paths.PluginPath); for (int i = 0; i < directories.Length; i++) { string text = directories[i] + "/BGN-PizzaTowerEscapeMusic/" + path; if (File.Exists(text)) { return text; } } string text2 = Paths.PluginPath + "/BGN-PizzaTowerEscapeMusic_Custom/" + path; if (File.Exists(text2)) { return text2; } return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/" + fallbackPath; } } public class GameEventListener : MonoBehaviour { private ManualLogSource logger; public Action OnFrameUpdate = delegate { }; public Action OnSoundManagerCreated = delegate { }; public Action OnSoundManagerDestroyed = delegate { }; public Action OnDungeonDoneGenerating = delegate { }; public Action OnShipLanded = delegate { }; public Action OnShipTakeOff = delegate { }; public Action OnShipReturnToOrbit = delegate { }; public Action OnShipLeavingAlertCalled = delegate { }; public Action OnPlayerDamaged = delegate { }; public Action OnPlayerDeath = delegate { }; public Action OnPlayerEnteredFacility = delegate { }; public Action OnPlayerExitedFacility = delegate { }; public Action OnPlayerEnteredShip = delegate { }; public Action OnPlayerExitedShip = delegate { }; public Action OnApparatusTaken = delegate { }; public Action<SelectableLevel?> OnCurrentMoonChanged = delegate { }; private readonly Dictionary<string, object?> previousValues = new Dictionary<string, object>(); private static LungProp? dockedApparatus; private void Awake() { logger = Logger.CreateLogSource("PizzaTowerEscapeMusic GameEventListener"); OnShipLanded = (Action)Delegate.Combine(OnShipLanded, new Action(FindDockedApparatus)); } private void FindDockedApparatus() { logger.LogDebug((object)"Checking for docked Apparatus..."); LungProp[] array = Object.FindObjectsOfType<LungProp>(); foreach (LungProp val in array) { if (val.isLungDocked) { logger.LogDebug((object)"Found docked Apparatus"); dockedApparatus = val; return; } } logger.LogDebug((object)"Could not find docked Apparatus"); } public static bool IsApparatusDocked() { return (Object)(object)dockedApparatus != (Object)null; } private void Update() { if ((Object)(object)SoundManager.Instance != (Object)null) { OnFrameUpdate(); } CheckSoundManager(); CheckDungeonDoneGenerating(); CheckShipLanded(); CheckShipReturnToOrbit(); CheckShipLeavingAlertCalled(); CheckPlayerDamaged(); CheckPlayerDeath(); CheckPlayerInsideFacility(); CheckPlayerInsideShip(); CheckApparatusTaken(); CheckCurrentMoonChanged(); } private T? UpdateCached<T>(string key, T? currentValue, T? defaultValue) { if (!previousValues.TryGetValue(key, out object value)) { value = defaultValue; } previousValues[key] = currentValue; return (T)value; } private void CheckSoundManager() { bool flag = (Object)(object)SoundManager.Instance != (Object)null; if (UpdateCached("SoundManager", flag, defaultValue: false) != flag) { if (flag) { logger.LogDebug((object)"Sound Manager created"); OnSoundManagerCreated(); } else { logger.LogDebug((object)"Sound Manager destroyed"); OnSoundManagerDestroyed(); } } } private void CheckDungeonDoneGenerating() { bool flag = (Object)(object)RoundManager.Instance != (Object)null && RoundManager.Instance.dungeonCompletedGenerating; bool flag2 = UpdateCached("DungeonDoneGenerating", flag, defaultValue: false); if (flag != flag2 && flag) { logger.LogDebug((object)"Dungeon done generating"); OnDungeonDoneGenerating(); } } private void CheckShipLanded() { bool flag = (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.shipHasLanded; bool flag2 = UpdateCached("ShipLanded", flag, defaultValue: true); if (flag != flag2 && !((Object)(object)StartOfRound.Instance == (Object)null)) { if (flag) { logger.LogDebug((object)"Ship has landed"); OnShipLanded(); } else { logger.LogDebug((object)"Ship has taken off"); OnShipTakeOff(); } } } private void CheckShipReturnToOrbit() { bool flag = (Object)(object)StartOfRound.Instance == (Object)null || (!StartOfRound.Instance.shipHasLanded && !StartOfRound.Instance.shipIsLeaving); bool flag2 = UpdateCached("ShipReturnToOrbit", flag, defaultValue: true); if (flag != flag2 && flag) { logger.LogDebug((object)"Ship returned to orbit"); OnShipReturnToOrbit(); } } private void CheckShipLeavingAlertCalled() { bool flag = (Object)(object)TimeOfDay.Instance != (Object)null && TimeOfDay.Instance.shipLeavingAlertCalled; bool flag2 = UpdateCached("ShipLeavingAlertCalled", flag, defaultValue: false); if (flag != flag2 && flag) { logger.LogDebug((object)"Ship leaving alert called"); OnShipLeavingAlertCalled(); } } private void CheckPlayerDamaged() { if (!((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null)) { int health = GameNetworkManager.Instance.localPlayerController.health; int num = UpdateCached("PlayerDamaged", health, 100); if (health < num) { logger.LogDebug((object)$"Player took damage (Health: {GameNetworkManager.Instance.localPlayerController.health})"); OnPlayerDamaged(); } } } private void CheckPlayerDeath() { bool flag = (Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isPlayerDead; bool flag2 = UpdateCached("PlayerDeath", flag, defaultValue: false); if (flag != flag2 && flag) { logger.LogDebug((object)"Player has died"); OnPlayerDeath(); } } private void CheckPlayerInsideFacility() { bool flag = (Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isInsideFactory; bool flag2 = UpdateCached("PlayerInsideFacility", flag, defaultValue: false); if (flag != flag2) { if (flag) { logger.LogDebug((object)"Player entered facility"); OnPlayerEnteredFacility(); } else { logger.LogDebug((object)"Player exited facility"); OnPlayerExitedFacility(); } } } private void CheckPlayerInsideShip() { bool flag = (Object)(object)GameNetworkManager.Instance != (Object)null && (Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom; bool flag2 = UpdateCached("PlayerInsideShip", flag, defaultValue: false); if (flag != flag2) { if (flag) { logger.LogDebug((object)"Player entered ship"); OnPlayerEnteredShip(); } else { logger.LogDebug((object)"Player exited ship"); OnPlayerExitedShip(); } } } private void CheckApparatusTaken() { bool flag = (Object)(object)dockedApparatus != (Object)null && !dockedApparatus.isLungDocked; bool flag2 = UpdateCached("ApparatusTaken", flag, defaultValue: false); if (flag != flag2 && flag) { dockedApparatus = null; logger.LogDebug((object)"Apparatus was taken"); OnApparatusTaken(); } } private void CheckCurrentMoonChanged() { SelectableLevel val = TimeOfDay.Instance?.currentLevel; SelectableLevel val2 = UpdateCached<SelectableLevel>("CurrentMoon", val, null); if (!((Object)(object)val == (Object)(object)val2)) { logger.LogDebug((object)("Level has changed to " + val?.PlanetName)); OnCurrentMoonChanged(val); } } } public class MusicManager : MonoBehaviour { private class MusicInstance { public Script script; public ScriptEvent_PlayMusic musicEvent; public AudioSource audioSource; public Script.VolumeGroup volumeGroup; private bool isStopping; private float volume; public float FadeSpeed { get; private set; } public MusicInstance(Script script, ScriptEvent_PlayMusic musicEvent, AudioSource audioSource, AudioClip? musicClip) { this.script = script; this.musicEvent = musicEvent; this.audioSource = audioSource; audioSource.clip = musicClip; audioSource.loop = musicEvent.loop; audioSource.Play(); musicInstances.Add(this); if (musicEvent.tag != null) { if (!musicInstancesByTag.TryGetValue(musicEvent.tag, out List<MusicInstance> value)) { value = new List<MusicInstance>(1); musicInstancesByTag.Add(musicEvent.tag, value); } value.Add(this); } volumeGroup = script.TryGetVolumeGroupOrDefault(musicEvent.tag); volume = volumeGroup.GetVolume(script); } public void Update(float deltaTime) { float num = (isStopping ? 0f : volumeGroup.GetVolume(script)); float num2 = (isStopping ? volumeGroup.stoppingVolumeLerpSpeed : volumeGroup.volumeLerpSpeed); volume = Mathf.Lerp(volume, num, num2 * deltaTime); audioSource.volume = volume * PizzaTowerEscapeMusicManager.Configuration.volumeMaster.Value; if (!audioSource.isPlaying || (isStopping && audioSource.volume < 0.005f)) { StopCompletely(); } } public void FadeStop() { if (!isStopping) { isStopping = true; FadeSpeed = volumeGroup.stoppingVolumeLerpSpeed; } } public void StopCompletely() { audioSource.Stop(); audioSourcePool.Push(audioSource); musicInstances.Remove(this); if (musicEvent.tag != null && musicInstancesByTag.TryGetValue(musicEvent.tag, out List<MusicInstance> value)) { value.Remove(this); } } } private ManualLogSource logger; private static readonly List<MusicInstance> musicInstances = new List<MusicInstance>(); private static readonly Dictionary<string, List<MusicInstance>> musicInstancesByTag = new Dictionary<string, List<MusicInstance>>(); private static readonly Stack<AudioSource> audioSourcePool = new Stack<AudioSource>(); private readonly Dictionary<string, AudioClip> loadedMusic = new Dictionary<string, AudioClip>(); private void Awake() { logger = Logger.CreateLogSource("PizzaTowerEscapeMusic MusicManager"); } private void Update() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } for (int num = musicInstances.Count - 1; num >= 0; num--) { musicInstances[num].Update(Time.deltaTime); } bool flag = false; foreach (MusicInstance musicInstance in musicInstances) { if (musicInstance.musicEvent.silenceGameMusic) { flag = true; break; } } if (flag) { if (SoundManager.Instance.playingOutsideMusic && GetIsMusicPlaying()) { SoundManager.Instance.playingOutsideMusic = false; logger.LogInfo((object)"Silenced the outside music because alternate music is playing"); } if (TimeOfDay.Instance.TimeOfDayMusic.isPlaying && GetIsMusicPlaying()) { TimeOfDay.Instance.TimeOfDayMusic.Stop(); logger.LogInfo((object)"Silenced the time of day music because alternate music is playing"); } } } public bool GetIsMusicPlaying(string? tag = null) { if (tag == null) { return musicInstances.Count > 0; } if (musicInstancesByTag.TryGetValue(tag, out List<MusicInstance> value)) { logger.LogDebug((object)$"GetIsMusicPlaying says there's {value.Count} music instance(s) with the tag \"{tag}\""); return value.Count > 0; } logger.LogDebug((object)("GetIsMusicPlaying says there was no music instance list for tag \"" + tag + "\"")); return false; } public void PlayMusic(Script script, ScriptEvent_PlayMusic musicEvent) { logger.LogDebug((object)("PlayMusic called\nTag: " + musicEvent.tag + $"\nOverlap handling: {musicEvent.overlapHandling}" + $"\nAny music playing?: {GetIsMusicPlaying()}" + $"\nAny music playing with tag?: {GetIsMusicPlaying(musicEvent.tag)}")); if (musicEvent.overlapHandling == ScriptEvent_PlayMusic.OverlapHandling.IgnoreAll && GetIsMusicPlaying()) { logger.LogDebug((object)"PlayMusic canceled because other music was playing"); return; } if (musicEvent.overlapHandling == ScriptEvent_PlayMusic.OverlapHandling.IgnoreTag && GetIsMusicPlaying(musicEvent.tag)) { logger.LogDebug((object)("PlayMusic canceled because other music with the tag \"" + musicEvent.tag + "\" was playing")); return; } switch (musicEvent.overlapHandling) { case ScriptEvent_PlayMusic.OverlapHandling.OverrideAll: StopMusic(); break; case ScriptEvent_PlayMusic.OverlapHandling.OverrideTag: StopMusic(musicEvent.tag); break; case ScriptEvent_PlayMusic.OverlapHandling.OverrideFadeAll: FadeStopMusic(); break; case ScriptEvent_PlayMusic.OverlapHandling.OverrideFadeTag: FadeStopMusic(musicEvent.tag); break; } string text = musicEvent.musicNames[Random.Range(0, musicEvent.musicNames.Length)]; loadedMusic.TryGetValue(text, out AudioClip value); if ((Object)(object)value != (Object)null) { new MusicInstance(script, musicEvent, GetAudioSource(), value); logger.LogInfo((object)("Playing music (" + text + ")")); } else { logger.LogWarning((object)("Music (" + text + ") is null, cannot play. Maybe it wasn't loaded correctly?")); } } public void StopMusic(string? targetTag = null) { foreach (MusicInstance item in new List<MusicInstance>(musicInstances)) { if (targetTag == null || !(item.musicEvent.tag != targetTag)) { item.StopCompletely(); } } } public void FadeStopMusic(string? targetTag = null) { foreach (MusicInstance item in new List<MusicInstance>(musicInstances)) { if (targetTag == null || !(item.musicEvent.tag != targetTag)) { item.FadeStop(); } } } private AudioSource GetAudioSource() { if (!audioSourcePool.TryPop(out AudioSource result)) { return ((Component)this).gameObject.AddComponent<AudioSource>(); } return result; } public async void LoadNecessaryMusicClips() { if (PizzaTowerEscapeMusicManager.ScriptManager.loadedScripts.Count == 0) { logger.LogError((object)"No scripts are loaded, cannot load their music!"); return; } UnloadMusicClips(); foreach (Script loadedScript in PizzaTowerEscapeMusicManager.ScriptManager.loadedScripts) { ScriptEvent[] scriptEvents = loadedScript.scriptEvents; for (int i = 0; i < scriptEvents.Length; i++) { if (!(scriptEvents[i] is ScriptEvent_PlayMusic scriptEvent_PlayMusic)) { continue; } string[] musicNames = scriptEvent_PlayMusic.musicNames; foreach (string musicName in musicNames) { if (!loadedMusic.ContainsKey(musicName)) { AudioClip val = await LoadMusicClip(musicName); if (!((Object)(object)val == (Object)null)) { loadedMusic.Add(musicName, val); } } } } } logger.LogInfo((object)"Music clips done loading"); } public void UnloadMusicClips() { foreach (AudioClip value in loadedMusic.Values) { value.UnloadAudioData(); } loadedMusic.Clear(); logger.LogInfo((object)"All music clips unloaded"); } private async Task<AudioClip?> LoadMusicClip(string musicFileName) { InterpretMusicFileName(musicFileName, out AudioType audioType, out string finalFileName); string path = "file:///" + CustomManager.GetFilePath("Music/" + finalFileName, "DefaultMusic/" + finalFileName); UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(path, audioType); try { request.SendWebRequest(); while (!request.isDone) { await Task.Delay(50); } if ((int)request.result == 1) { logger.LogInfo((object)("Loaded music (" + musicFileName + ") from file")); AudioClip content = DownloadHandlerAudioClip.GetContent(request); ((Object)content).name = musicFileName; return content; } logger.LogError((object)($"Failed to load music ({musicFileName}) from file as audio type {audioType}, if the file extension and the audio type do not match the file extension may not be supported." + "\n- Path: " + path + "\n- Error: " + request.error)); return null; } finally { ((IDisposable)request)?.Dispose(); } } private void InterpretMusicFileName(string musicFileName, out AudioType audioType, out string finalFileName) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected I4, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (!musicFileName.Contains('.')) { audioType = (AudioType)20; finalFileName = musicFileName + ".wav"; return; } string text = musicFileName.Split('.').Last().ToLower(); AudioType val = ((text == "ogg") ? ((AudioType)14) : ((!(text == "mp3")) ? ((AudioType)20) : ((AudioType)13))); audioType = (AudioType)(int)val; finalFileName = musicFileName; } } public class PizzaTowerEscapeMusicManager : MonoBehaviour { private GameEventListener gameEventListener; private ManualLogSource logger; public static Configuration Configuration { get; private set; } public static ScriptManager ScriptManager { get; private set; } public static MusicManager MusicManager { get; private set; } public void Initialise(ManualLogSource logger, ConfigFile config) { this.logger = logger; Configuration = new Configuration(config); MusicManager = ((Component)this).gameObject.AddComponent<MusicManager>(); gameEventListener = ((Component)this).gameObject.AddComponent<GameEventListener>(); GameEventListener obj = gameEventListener; obj.OnSoundManagerCreated = (Action)Delegate.Combine(obj.OnSoundManagerCreated, new Action(MusicManager.LoadNecessaryMusicClips)); GameEventListener obj2 = gameEventListener; obj2.OnSoundManagerDestroyed = (Action)Delegate.Combine(obj2.OnSoundManagerDestroyed, (Action)delegate { MusicManager.StopMusic(); }); GameEventListener obj3 = gameEventListener; obj3.OnSoundManagerDestroyed = (Action)Delegate.Combine(obj3.OnSoundManagerDestroyed, new Action(MusicManager.UnloadMusicClips)); ScriptManager = new ScriptManager(Configuration.scriptingScripts.Value.Split(','), gameEventListener); GameEventListener obj4 = gameEventListener; obj4.OnSoundManagerDestroyed = (Action)Delegate.Combine(obj4.OnSoundManagerDestroyed, new Action(ScriptManager.ClearAllScriptTimers)); ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; logger.LogInfo((object)"Plugin bgn.pizzatowerescapemusic is loaded!"); } private void Update() { ScriptManager.UpdateAllScriptTimers(Time.deltaTime); } } [BepInPlugin("bgn.pizzatowerescapemusic", "PizzaTowerEscapeMusic", "2.4.0")] [BepInProcess("Lethal Company.exe")] public class Plugin : BaseUnityPlugin { public const string GUID = "bgn.pizzatowerescapemusic"; private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PizzaTowerEscapeMusic Manager"); val.AddComponent<PizzaTowerEscapeMusicManager>().Initialise(((BaseUnityPlugin)this).Logger, ((BaseUnityPlugin)this).Config); ((Object)val).hideFlags = (HideFlags)61; } } public static class PluginInfo { public const string PLUGIN_GUID = "PizzaTowerEscapeMusic"; public const string PLUGIN_NAME = "PizzaTowerEscapeMusic"; public const string PLUGIN_VERSION = "2.4.0"; } } namespace PizzaTowerEscapeMusic.Scripting { public class Script { public class VolumeRule { public string comment = string.Empty; [JsonRequired] public float volume; public Condition? condition; } public class VolumeModifier { public string comment = string.Empty; [JsonRequired] public float volumeScale; public Condition? condition; } public class VolumeGroup { public string comment = string.Empty; public string tag = string.Empty; public float volumeLerpSpeed = 1f; public float stoppingVolumeLerpSpeed = 1f; public float masterVolume = 1f; public VolumeRule[] volumeRules = Array.Empty<VolumeRule>(); public VolumeModifier[] volumeModifiers = Array.Empty<VolumeModifier>(); public float GetVolume(Script script) { float num = 1f; VolumeRule[] array = volumeRules; foreach (VolumeRule volumeRule in array) { if (volumeRule.condition == null || volumeRule.condition.Check(script)) { num = volumeRule.volume; break; } } VolumeModifier[] array2 = volumeModifiers; foreach (VolumeModifier volumeModifier in array2) { if (volumeModifier.condition == null || volumeModifier.condition.Check(script)) { num *= volumeModifier.volumeScale; } } return num * masterVolume; } } public class Timer { public string name; public float time; public Timer(string name) { this.name = name; } } public string comment = string.Empty; public bool isAddon; public VolumeGroup[] volumeGroups = Array.Empty<VolumeGroup>(); [JsonRequired] public ScriptEvent[] scriptEvents = Array.Empty<ScriptEvent>(); [JsonIgnore] public readonly Dictionary<ScriptEvent.GameEventType, List<ScriptEvent>> loadedScriptEvents = new Dictionary<ScriptEvent.GameEventType, List<ScriptEvent>>(); [JsonIgnore] public readonly Dictionary<string, VolumeGroup> loadedScriptVolumeGroups = new Dictionary<string, VolumeGroup>(); [JsonIgnore] public readonly Dictionary<string, Timer> activeTimers = new Dictionary<string, Timer>(); [JsonIgnore] public static VolumeGroup DefaultVolumeGroup { get; private set; } = new VolumeGroup(); public void Initialise(ManualLogSource logger) { ScriptEvent[] array = scriptEvents; foreach (ScriptEvent scriptEvent in array) { if (!loadedScriptEvents.TryGetValue(scriptEvent.gameEventType, out List<ScriptEvent> value)) { value = new List<ScriptEvent>(1); loadedScriptEvents.Add(scriptEvent.gameEventType, value); } value.Add(scriptEvent); } VolumeGroup[] array2 = volumeGroups; foreach (VolumeGroup volumeGroup in array2) { if (!loadedScriptVolumeGroups.TryAdd(volumeGroup.tag, volumeGroup)) { logger.LogError((object)("Volume group tag \"" + volumeGroup.tag + "\" was already declared, you cannot have two volume groups with the same tag")); } } } public VolumeGroup TryGetVolumeGroupOrDefault(string? tag) { if (tag == null || !loadedScriptVolumeGroups.ContainsKey(tag)) { return DefaultVolumeGroup; } return loadedScriptVolumeGroups[tag]; } public bool TryGetVolumeGroup(string? tag, [NotNullWhen(true)] out VolumeGroup? volumeGroup) { if (tag == null || !loadedScriptVolumeGroups.ContainsKey(tag)) { volumeGroup = null; return false; } volumeGroup = loadedScriptVolumeGroups[tag]; return true; } public void UpdateTimers(float deltaTime) { foreach (Timer value in activeTimers.Values) { value.time += deltaTime; } } public void ClearTimers() { activeTimers.Clear(); } internal void ClearTimer(string timerName) { activeTimers.Remove(timerName); } } public class ScriptManager { public readonly List<Script> loadedScripts = new List<Script>(); public ManualLogSource Logger { get; private set; } public ScriptManager(string[] scriptNames, GameEventListener gameEventListener) { Logger = Logger.CreateLogSource("PizzaTowerEscapeMusic ScriptManager"); Script script = new Script(); loadedScripts.Add(script); foreach (string text in scriptNames) { Script script2 = DeserializeScript(text); if (script2 != null) { script2.Initialise(Logger); if (script2.isAddon) { List<Script.VolumeGroup> list = script.volumeGroups.ToList(); list.AddRange(script2.volumeGroups); script.volumeGroups = list.ToArray(); List<ScriptEvent> list2 = script.scriptEvents.ToList(); list2.AddRange(script2.scriptEvents); script.scriptEvents = list2.ToArray(); } else { loadedScripts.Add(script2); } if (script2.isAddon) { Logger.LogInfo((object)("Script (" + text + ") loaded as addon")); } else { Logger.LogInfo((object)("Script (" + text + ") loaded")); } } } script.Initialise(Logger); gameEventListener.OnFrameUpdate = (Action)Delegate.Combine(gameEventListener.OnFrameUpdate, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.FrameUpdated); }); gameEventListener.OnShipLanded = (Action)Delegate.Combine(gameEventListener.OnShipLanded, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.ShipLanded); }); gameEventListener.OnShipTakeOff = (Action)Delegate.Combine(gameEventListener.OnShipTakeOff, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.ShipTakeOff); }); gameEventListener.OnShipLeavingAlertCalled = (Action)Delegate.Combine(gameEventListener.OnShipLeavingAlertCalled, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.ShipLeavingAlertCalled); }); gameEventListener.OnPlayerDamaged = (Action)Delegate.Combine(gameEventListener.OnPlayerDamaged, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.PlayerDamaged); }); gameEventListener.OnPlayerDeath = (Action)Delegate.Combine(gameEventListener.OnPlayerDeath, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.PlayerDied); }); gameEventListener.OnPlayerEnteredFacility = (Action)Delegate.Combine(gameEventListener.OnPlayerEnteredFacility, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.PlayerEnteredFacility); }); gameEventListener.OnPlayerExitedFacility = (Action)Delegate.Combine(gameEventListener.OnPlayerExitedFacility, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.PlayerExitedFacility); }); gameEventListener.OnPlayerEnteredShip = (Action)Delegate.Combine(gameEventListener.OnPlayerEnteredShip, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.PlayerEnteredShip); }); gameEventListener.OnPlayerExitedShip = (Action)Delegate.Combine(gameEventListener.OnPlayerExitedShip, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.PlayerExitedShip); }); gameEventListener.OnApparatusTaken = (Action)Delegate.Combine(gameEventListener.OnApparatusTaken, (Action)delegate { CheckScriptEvents(ScriptEvent.GameEventType.ApparatusTaken); }); gameEventListener.OnCurrentMoonChanged = (Action<SelectableLevel>)Delegate.Combine(gameEventListener.OnCurrentMoonChanged, (Action<SelectableLevel>)delegate { CheckScriptEvents(ScriptEvent.GameEventType.CurrentMoonChanged); }); Logger.LogInfo((object)"Done loading scripts"); } private void CheckScriptEvents(ScriptEvent.GameEventType eventType) { foreach (Script loadedScript in loadedScripts) { if (!loadedScript.loadedScriptEvents.TryGetValue(eventType, out List<ScriptEvent> value)) { continue; } foreach (ScriptEvent item in value) { if (item.CheckConditions(loadedScript)) { Logger.LogDebug((object)("Conditions for a script event have been met!\n Script Event Type: " + item.scriptEventType + $"\n Game Event Type: {item.gameEventType}" + "\n Comment: " + item.comment)); item.Run(loadedScript); } } } } private Script? DeserializeScript(string name) { string filePath = CustomManager.GetFilePath("Scripts/" + name + ".json", "DefaultScripts/" + name + ".json"); if (!File.Exists(filePath)) { Logger.LogError((object)("Script \"" + name + "\" does not exist! Make sure you spelt it right the config, and make sure its file extension is \".json\"")); return null; } string text = File.ReadAllText(filePath); try { return JsonConvert.DeserializeObject<Script>(text); } catch (Exception ex) { Logger.LogError((object)("Failed to deserialize script \"" + name + "\":\n" + ex.Message)); return null; } } public void UpdateAllScriptTimers(float deltaTime) { foreach (Script loadedScript in loadedScripts) { loadedScript.UpdateTimers(deltaTime); } } public void ClearAllScriptTimers() { foreach (Script loadedScript in loadedScripts) { loadedScript.ClearTimers(); } } } } namespace PizzaTowerEscapeMusic.Scripting.ScriptEvents { public class ScriptEventConverter : JsonConverter<ScriptEvent> { public override bool CanWrite => false; public override ScriptEvent ReadJson(JsonReader reader, Type objectType, ScriptEvent? existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); JToken val2 = default(JToken); if (!val.TryGetValue("scriptEventType", ref val2)) { throw new Exception("scriptEventType type is null!"); } ScriptEvent scriptEvent = Extensions.Value<string>((IEnumerable<JToken>)val2) switch { "PlayMusic" => new ScriptEvent_PlayMusic(), "StopMusic" => new ScriptEvent_StopMusic(), "ResetTimers" => new ScriptEvent_ResetTimers(), "SetVolumeGroupMasterVolume" => new ScriptEvent_SetVolumeGroupMasterVolume(), _ => throw new Exception($"Condition type \"{val2}\" does not exist"), }; serializer.Populate(((JToken)val).CreateReader(), (object)scriptEvent); return scriptEvent; } public override void WriteJson(JsonWriter writer, ScriptEvent? value, JsonSerializer serializer) { throw new NotImplementedException(); } } [JsonConverter(typeof(ScriptEventConverter))] public abstract class ScriptEvent { public enum GameEventType { FrameUpdated, ShipLanded, ShipTakeOff, ShipLeavingAlertCalled, PlayerDamaged, PlayerDied, PlayerEnteredFacility, PlayerExitedFacility, PlayerEnteredShip, PlayerExitedShip, ApparatusTaken, CurrentMoonChanged } public string comment = string.Empty; [JsonRequired] public string scriptEventType = string.Empty; [JsonRequired] public GameEventType gameEventType; public Condition[] conditions = Array.Empty<Condition>(); public bool CheckConditions(Script script) { Script script2 = script; return !conditions.Any((Condition c) => !c.Check(script2)); } public abstract void Run(Script script); } public class ScriptEvent_PlayMusic : ScriptEvent { public enum OverlapHandling { IgnoreAll, IgnoreTag, OverrideAll, OverrideTag, OverrideFadeAll, OverrideFadeTag, Overlap } public bool loop; public bool silenceGameMusic = true; [JsonRequired] public OverlapHandling overlapHandling; public string? tag; [JsonRequired] public string[] musicNames = Array.Empty<string>(); public override void Run(Script script) { if (musicNames.Length != 0) { PizzaTowerEscapeMusicManager.MusicManager.PlayMusic(script, this); } } } public class ScriptEvent_StopMusic : ScriptEvent { public string[]? targetTags; public bool instant; public override void Run(Script script) { if (targetTags != null) { string[] array = targetTags; foreach (string targetTag in array) { if (instant) { PizzaTowerEscapeMusicManager.MusicManager.StopMusic(targetTag); } else { PizzaTowerEscapeMusicManager.MusicManager.FadeStopMusic(targetTag); } } } else if (instant) { PizzaTowerEscapeMusicManager.MusicManager.StopMusic(); } else { PizzaTowerEscapeMusicManager.MusicManager.FadeStopMusic(); } } } public class ScriptEvent_ResetTimers : ScriptEvent { public string[]? targetTimerNames; public override void Run(Script script) { if (targetTimerNames == null) { script.ClearTimers(); return; } string[] array = targetTimerNames; foreach (string timerName in array) { script.ClearTimer(timerName); } } } public class ScriptEvent_SetVolumeGroupMasterVolume : ScriptEvent { public string[] targetTags = Array.Empty<string>(); [JsonRequired] public float masterVolume; public override void Run(Script script) { if (targetTags.Length == 0) { Script.DefaultVolumeGroup.masterVolume = masterVolume; return; } string[] array = targetTags; foreach (string text in array) { if (!script.loadedScriptVolumeGroups.TryGetValue(text, out Script.VolumeGroup value)) { PizzaTowerEscapeMusicManager.ScriptManager.Logger.LogError((object)("Script Event SetVolumeGroupMasterVolume was called for volume group with tag \"" + text + "\", but there is no volume group of that tag")); } else { value.masterVolume = masterVolume; } } } } } namespace PizzaTowerEscapeMusic.Scripting.Conditions { public class ConditionConverter : JsonConverter<Condition> { public override bool CanWrite => false; public override Condition ReadJson(JsonReader reader, Type objectType, Condition? existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject val = JObject.Load(reader); JToken val2 = default(JToken); if (!val.TryGetValue("conditionType", ref val2)) { throw new Exception("Condition type is null!"); } Condition condition = Extensions.Value<string>((IEnumerable<JToken>)val2) switch { "And" => new Condition_And(), "Or" => new Condition_Or(), "Not" => new Condition_Not(), "Weather" => new Condition_Weather(), "PlayerLocation" => new Condition_PlayerLocation(), "PlayerAlive" => new Condition_PlayerAlive(), "PlayerHealth" => new Condition_PlayerHealth(), "PlayerCrouching" => new Condition_PlayerCrouching(), "PlayerInsanity" => new Condition_PlayerInsanity(), "ShipLanded" => new Condition_ShipLanded(), "ShipLeavingAlertCalled" => new Condition_ShipLeavingAlertCalled(), "MusicWithTagPlaying" => new Condition_MusicWithTagPlaying(), "CurrentMoon" => new Condition_CurrentMoon(), "Timer" => new Condition_Timer(), "Random" => new Condition_Random(), "ApparatusDocked" => new Condition_ApparatusDocked(), "TimeOfDay" => new Condition_TimeOfDay(), _ => throw new Exception($"Condition type \"{val2}\" does not exist"), }; serializer.Populate(((JToken)val).CreateReader(), (object)condition); return condition; } public override void WriteJson(JsonWriter writer, Condition? value, JsonSerializer serializer) { throw new NotImplementedException(); } } [JsonConverter(typeof(ConditionConverter))] public abstract class Condition { [JsonRequired] public string conditionType = string.Empty; public abstract bool Check(Script script); } public abstract class ConditionComparableNumber : Condition { public enum ComparisonType { Equals, NotEquals, GreaterThan, LessThan, GreaterThanOrEquals, LessThanOrEquals } [JsonRequired] public ComparisonType comparisonType; } public class Condition_And : Condition { [JsonRequired] public Condition[] conditions = Array.Empty<Condition>(); public override bool Check(Script script) { Script script2 = script; return !conditions.Any((Condition c) => !c.Check(script2)); } } public class Condition_Or : Condition { [JsonRequired] public Condition[] conditions = Array.Empty<Condition>(); public override bool Check(Script script) { Script script2 = script; return conditions.Any((Condition c) => c.Check(script2)); } } public class Condition_Not : Condition { [JsonRequired] public Condition? condition; public override bool Check(Script script) { if (condition == null) { return true; } return !condition.Check(script); } } public class Condition_Weather : Condition { [JsonRequired] public LevelWeatherType weather; public override bool Check(Script script) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)TimeOfDay.Instance == (Object)null) { return false; } return TimeOfDay.Instance.currentLevelWeather == weather; } } public class Condition_PlayerLocation : Condition { public enum Location { Ship, Facility } [JsonRequired] public Location location; public override bool Check(Script script) { if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return false; } if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return false; } return location switch { Location.Ship => GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom, Location.Facility => GameNetworkManager.Instance.localPlayerController.isInsideFactory, _ => false, }; } } public class Condition_PlayerAlive : Condition { public override bool Check(Script script) { if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return false; } if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return false; } return !GameNetworkManager.Instance.localPlayerController.isPlayerDead; } } public class Condition_PlayerHealth : ConditionComparableNumber { [JsonRequired] public int value; public override bool Check(Script script) { if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return false; } if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return false; } int health = GameNetworkManager.Instance.localPlayerController.health; return comparisonType switch { ComparisonType.Equals => health == value, ComparisonType.NotEquals => health != value, ComparisonType.GreaterThan => health > value, ComparisonType.LessThan => health < value, ComparisonType.GreaterThanOrEquals => health >= value, ComparisonType.LessThanOrEquals => health <= value, _ => false, }; } } public class Condition_PlayerCrouching : Condition { public override bool Check(Script script) { if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return false; } if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return false; } return GameNetworkManager.Instance.localPlayerController.isCrouching; } } public class Condition_PlayerInsanity : ConditionComparableNumber { [JsonRequired] public float level; public override bool Check(Script script) { if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return false; } if ((Object)(object)GameNetworkManager.Instance.localPlayerController == (Object)null) { return false; } float num = GameNetworkManager.Instance.localPlayerController.insanityLevel / GameNetworkManager.Instance.localPlayerController.maxInsanityLevel; return comparisonType switch { ComparisonType.Equals => level == num, ComparisonType.NotEquals => level != num, ComparisonType.GreaterThan => level > num, ComparisonType.LessThan => level < num, ComparisonType.GreaterThanOrEquals => level >= num, ComparisonType.LessThanOrEquals => level <= num, _ => false, }; } } public class Condition_ShipLanded : Condition { public override bool Check(Script script) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return false; } return StartOfRound.Instance.shipHasLanded; } } public class Condition_ShipLeavingAlertCalled : Condition { public override bool Check(Script script) { if ((Object)(object)TimeOfDay.Instance == (Object)null) { return false; } return TimeOfDay.Instance.shipLeavingAlertCalled; } } public class Condition_MusicWithTagPlaying : Condition { [JsonRequired] public string tag = string.Empty; public override bool Check(Script script) { return PizzaTowerEscapeMusicManager.MusicManager.GetIsMusicPlaying(tag); } } public class Condition_CurrentMoon : Condition { private static readonly Dictionary<string, int> moonNameToId = new Dictionary<string, int>(); [JsonRequired] public string moonName = string.Empty; private bool isDisabled; public override bool Check(Script script) { if ((Object)(object)TimeOfDay.Instance == (Object)null) { return false; } if ((Object)(object)StartOfRound.Instance == (Object)null) { return false; } if (isDisabled) { return false; } if (!moonNameToId.TryGetValue(moonName, out var value)) { SelectableLevel[] levels = StartOfRound.Instance.levels; foreach (SelectableLevel val in levels) { moonNameToId.TryAdd(val.PlanetName, val.levelID); } if (!moonNameToId.TryGetValue(moonName, out value)) { PizzaTowerEscapeMusicManager.ScriptManager.Logger.LogError((object)("From CurrentMoon condition: Found no existing level with the name \"" + moonName + "\"")); isDisabled = true; return false; } } return TimeOfDay.Instance.currentLevel.levelID == value; } } public class Condition_Timer : Condition { [JsonRequired] public string timerName = string.Empty; [JsonRequired] public float timeGoal; public bool resetsTimer = true; public override bool Check(Script script) { if (!script.activeTimers.TryGetValue(timerName, out Script.Timer value)) { value = new Script.Timer(timerName); script.activeTimers.Add(timerName, value); } if (value.time >= timeGoal) { if (resetsTimer) { value.time = 0f; } return true; } return false; } } public class Condition_Random : Condition { [JsonRequired] public float chance; public override bool Check(Script script) { return Random.Range(0f, 1f) <= chance; } } public class Condition_ApparatusDocked : Condition { public override bool Check(Script script) { return GameEventListener.IsApparatusDocked(); } } public class Condition_TimeOfDay : ConditionComparableNumber { [JsonRequired] public float time; public override bool Check(Script script) { if ((Object)(object)TimeOfDay.Instance == (Object)null) { return false; } float num = TimeOfDay.Instance.currentDayTime / TimeOfDay.Instance.totalTime; return comparisonType switch { ComparisonType.Equals => num == time, ComparisonType.NotEquals => num != time, ComparisonType.GreaterThan => num > time, ComparisonType.LessThan => num < time, ComparisonType.GreaterThanOrEquals => num >= time, ComparisonType.LessThanOrEquals => num <= time, _ => false, }; } } }
BepInEx/plugins/loaforc-FacilityMeltdownExperimental/FacilityMeltdown/FacilityMeltdown.dll
Decompiled 4 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.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Biodiversity.Util.Assetloading; using FacilityMeltdown.API; using FacilityMeltdown.Behaviours; using FacilityMeltdown.Config; using FacilityMeltdown.Equipment; using FacilityMeltdown.Integrations; using FacilityMeltdown.Lang; using FacilityMeltdown.MeltdownSequence.Behaviours; using FacilityMeltdown.NetcodePatcher; using FacilityMeltdown.Patches; using FacilityMeltdown.Util; using FacilityMeltdown.Util.Attributes; using FacilityMeltdown.Util.Config; using GameNetcodeStuff; using HarmonyLib; using LethalConfig; using LethalConfig.ConfigItems; using LethalConfig.ConfigItems.Options; using LethalLib.Modules; using LethalSettings.UI; using LethalSettings.UI.Components; using LobbyCompatibility.Enums; using LobbyCompatibility.Features; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.Rendering.HighDefinition; [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("WeatherRegistry")] [assembly: AssemblyCompany("FacilityMeltdown")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+74a2b8f0ecd190d1420e40c840c77a124518a3f9")] [assembly: AssemblyProduct("FacilityMeltdown")] [assembly: AssemblyTitle("FacilityMeltdown")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] [module: NetcodePatchedAssembly] 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; } } [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 Biodiversity.Util.Assetloading { [AttributeUsage(AttributeTargets.Property)] internal class LoadFromBundleAttribute : Attribute { public string BundleFile { get; private set; } public LoadFromBundleAttribute(string bundleFile) { BundleFile = bundleFile; base..ctor(); } } } namespace FacilityMeltdown { [BepInPlugin("me.loaforc.facilitymeltdown", "FacilityMeltdown", "2.6.15")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class MeltdownPlugin : BaseUnityPlugin { internal const string modGUID = "me.loaforc.facilitymeltdown"; internal const string modName = "FacilityMeltdown"; internal const string modVersion = "2.6.15"; internal static MeltdownPlugin instance; internal static ManualLogSource logger; internal static Harmony harmony = new Harmony("me.loaforc.facilitymeltdown"); internal static MeltdownAssets assets { get; private set; } public static bool loadedFully { get; private set; } = false; internal static MeltdownConfig config { get; set; } internal static MeltdownClientConfig clientConfig { get; private set; } private void Awake() { if (!((Object)(object)instance == (Object)null)) { return; } instance = this; logger = Logger.CreateLogSource("me.loaforc.facilitymeltdown"); if (RunLoadStep("Assets.Init", "Getting assets", delegate { assets = new MeltdownAssets(); }) && RunLoadStep("LangParser.Init", "Getting possible languages", LangParser.Init) && RunLoadStep("new MeltdownConfig()", "Setting up config", delegate { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown config = new MeltdownConfig(((BaseUnityPlugin)this).Config); clientConfig = new MeltdownClientConfig(new ConfigFile(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "me.loaforc.facilitymeltdown.Client.cfg" }), false, MetadataHelper.GetMetadata((object)this))); logger.LogDebug((object)$"Test Config Value: {config.ApparatusValue}"); ((BaseUnityPlugin)this).Config.ClearOrphans(); clientConfig.configFile.ClearOrphans(); }) && RunLoadStep("LangParser.SetLanguage", "Setting language", delegate { LangParser.SetLanguage(clientConfig.Language); }) && RunLoadStep("RegisterPatches", "Integrating into LethalCompany", RegisterPatches) && RunLoadStep("RegisterNetworking", "Making sure everything is networked", RegisterNetworking)) { if (!RunLoadStep("RegisterItems", "Adding the Geiger Counter", RegisterItems)) { logger.LogWarning((object)"Failed to register the geiger counter."); } if (!RunLoadStep("CompatibleDependency.Init", "Checking for any soft dependencies", delegate { CompatibleDependencyAttribute.Init((BaseUnityPlugin)(object)this); })) { logger.LogWarning((object)"Doing something with soft dependencies broke, meltdown itself should be fine."); } loadedFully = true; logger.LogInfo((object)"FacilityMeltdown:2.6.15 by loaforc has loaded! have fun :3"); logger.LogInfo((object)" .-_; ;_-. "); logger.LogInfo((object)" / / \\ \\ "); logger.LogInfo((object)" | | | | "); logger.LogInfo((object)" \\ \\.---./ / "); logger.LogInfo((object)" .-\\\"\"~ .---. ~\"\"-."); logger.LogInfo((object)" ,`.-~// .'`---`'. \\\\~-.`,"); logger.LogInfo((object)" ' ` | | \\(_)/ | | `' "); logger.LogInfo((object)" , \\ \\ | | / / , "); logger.LogInfo((object)" ;`'.,_\\ `-'-' /_,.'`; "); logger.LogInfo((object)" '-._ _.-'^'-._ _.-' "); } } private bool RunLoadStep(string stepName, string descrption, Action callback) { try { callback(); } catch (Exception ex) { logger.LogError((object)("`" + stepName + "` caused an exception to be thrown, meltdown may or may not work, look for more errors.")); logger.LogError((object)ex); return false; } logger.LogInfo((object)(stepName.PadRight(25) + " == " + descrption)); return true; } private void RegisterItems() { logger.LogInfo((object)"Registering Items"); Items.RegisterShopItem(assets.geigerCounterItemDef, (TerminalNode)null, (TerminalNode)null, assets.geigerCounterNode, 90); } private void OnDisable() { if (!loadedFully) { Harmony.UnpatchID("me.loaforc.facilitymeltdown"); logger.LogInfo((object)"Unpatching as something failed while loading."); } else if (Chainloader.PluginInfos.ContainsKey("den.meltdownchance") || Chainloader.PluginInfos.ContainsKey("PizzaProbability")) { logger.LogInfo((object)"You are using a mod that makes meltdown have a random chance of occuring."); logger.LogInfo((object)"Keep in mind this goes against meltdown's core design, but your choice."); logger.LogWarning((object)"However; BY DESIGN these mods need to mess with the internals of meltdown"); logger.LogWarning((object)"so I personally will be offering low to no support with these mods installed."); } } private void RegisterNetworking() { Type[] array = new Type[2] { typeof(MeltdownHandler), typeof(GeigerCounterItem) }; Type[] array2 = array; foreach (Type type in array2) { try { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array3 = methods; foreach (MethodInfo methodInfo in array3) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } catch (Exception) { logger.LogWarning((object)"supressed an error from netcode patcher, probably fine but should still log that something happened."); } } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void RegisterPatches() { foreach (Type item in from t in Assembly.GetExecutingAssembly().GetLoadableTypes() where t.IsClass && t.Namespace == "FacilityMeltdown.Patches" select t) { logger.LogDebug((object)("Registering Patch handler: " + item.Name)); harmony.PatchAll(item); } } } internal static class ExtensionMethods { private static Random rng = new Random(); public static void Shuffle<T>(this IList<T> list) { int num = list.Count; while (num > 1) { num--; int index = rng.Next(num + 1); T value = list[index]; list[index] = list[num]; list[num] = value; } } public static float Remap(this float value, float from1, float to1, float from2, float to2) { return (value - from1) / (to1 - from1) * (to2 - from2) + from2; } public static List<PlayerControllerB> GetConnectedPlayers(this StartOfRound startOfRound) { return startOfRound.allPlayerScripts.Where((PlayerControllerB player) => player.isPlayerControlled).ToList(); } public static void SpawnEnemy(this EnemyVent vent, SpawnableEnemyWithRarity enemy) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) Vector3 position = vent.floorNode.position; float y = vent.floorNode.eulerAngles.y; GameObject val = Object.Instantiate<GameObject>(enemy.enemyType.enemyPrefab, position, Quaternion.Euler(new Vector3(0f, y, 0f))); EnemyAI component = val.GetComponent<EnemyAI>(); ((NetworkBehaviour)component).NetworkObject.Spawn(true); RoundManager.Instance.SpawnedEnemies.Add(component); vent.OpenVentClientRpc(); vent.occupied = false; } internal static string Translate(this string text) { return LangParser.GetTranslation(text); } internal static void ClearOrphans(this ConfigFile config) { PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic); Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null); dictionary.Clear(); config.Save(); } internal static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) { if (assembly == null) { throw new ArgumentNullException("assembly"); } try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type t) => t != null); } } internal static (int hours, int minutes) GetCurrentTime(this TimeOfDay timeOfDay) { int num = Mathf.FloorToInt(timeOfDay.normalizedTimeOfDay * 60f * (float)timeOfDay.numberOfHours + 360f); int item = Mathf.FloorToInt((float)(num / 60)); return (item, num % 60); } } internal class MeltdownAssets : AssetBundleLoader<MeltdownAssets> { [LoadFromBundle("meltdownmusic.mp3")] public AudioClip defaultMusic { get; private set; } [LoadFromBundle("shockwave.mp3")] public AudioClip shockwave { get; private set; } [LoadFromBundle("FacilityExplosion.prefab")] public GameObject facilityExplosionPrefab { get; private set; } [LoadFromBundle("MeltdownHandler.prefab")] public GameObject meltdownHandlerPrefab { get; private set; } [LoadFromBundle("Shockwave.prefab")] public GameObject shockwavePrefab { get; private set; } [LoadFromBundle("GeigerCounterItemDef.asset")] public Item geigerCounterItemDef { get; private set; } [LoadFromBundle("GeigerCounterNode.asset")] public TerminalNode geigerCounterNode { get; private set; } [LoadFromBundle("HealthKeyword.asset")] public TerminalKeyword healthKeyword { get; private set; } [LoadFromBundle("ReactorKeyword.asset")] public TerminalKeyword reactorKeyword { get; private set; } [LoadFromBundle("ReactorHealthReport.asset")] public TerminalNode reactorHealthNode { get; private set; } public GameObject[] facilityEffects { get; private set; } public AudioClip[] warnings { get; private set; } public MeltdownAssets() : base("facilitymeltdown") { } protected override void FinishLoadingAssets(AssetBundle bundle) { warnings = (AudioClip[])(object)new AudioClip[4] { LoadAsset<AudioClip>(bundle, "warning1.mp3"), LoadAsset<AudioClip>(bundle, "warning2.mp3"), LoadAsset<AudioClip>(bundle, "warning3.mp3"), LoadAsset<AudioClip>(bundle, "warning4.mp3") }; facilityEffects = (GameObject[])(object)new GameObject[2] { LoadAsset<GameObject>(bundle, "Dust.prefab"), LoadAsset<GameObject>(bundle, "Waterstream.prefab") }; TerminalPatch.terminalKeywordsToRegister.Add(healthKeyword); TerminalPatch.terminalKeywordsToRegister.Add(reactorKeyword); TerminalPatch.terminalNodesToRegister.Add(reactorHealthNode); } } } namespace FacilityMeltdown.Util { internal abstract class AssetBundleLoader<T> where T : AssetBundleLoader<T> { public AssetBundleLoader(string filePath) { AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), filePath)); MeltdownPlugin.logger.LogDebug((object)("[Assets] AssetBundle `" + filePath + "` contains these objects: \n" + string.Join("\n", val.GetAllAssetNames()))); Type typeFromHandle = typeof(T); PropertyInfo[] properties = typeFromHandle.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { LoadFromBundleAttribute loadFromBundleAttribute = (LoadFromBundleAttribute)propertyInfo.GetCustomAttribute(typeof(LoadFromBundleAttribute)); if (loadFromBundleAttribute != null) { MeltdownPlugin.logger.LogDebug((object)("[Assets] Got LoadFromBundle attribute on `" + propertyInfo.Name + "`. Loading asset: `" + loadFromBundleAttribute.BundleFile + "` into the [roperty.")); propertyInfo.SetValue(this, LoadAsset<Object>(val, loadFromBundleAttribute.BundleFile.ToLower(CultureInfo.GetCultureInfo("en-GB")))); } } GameObject[] array = val.LoadAllAssets<GameObject>(); foreach (GameObject val2 in array) { if (!((Object)(object)val2.GetComponent<NetworkObject>() == (Object)null) && !GameNetworkManagerPatch.networkPrefabsToRegister.Contains(val2)) { GameNetworkManagerPatch.networkPrefabsToRegister.Add(val2); } } FinishLoadingAssets(val); } protected virtual void FinishLoadingAssets(AssetBundle bundle) { } protected AssetType LoadAsset<AssetType>(AssetBundle bundle, string path) where AssetType : Object { AssetType val = bundle.LoadAsset<AssetType>(path); if ((Object)(object)val == (Object)null) { throw new ArgumentException(path + " is not valid in the assetbundle!"); } return val; } } } namespace FacilityMeltdown.Util.Config { [AttributeUsage(AttributeTargets.Property)] internal class ConfigDescAttribute : Attribute { public string Description { get; private set; } public ConfigDescAttribute(string desc) { Description = desc; base..ctor(); } } [AttributeUsage(AttributeTargets.Property)] internal class ConfigGroupAttribute : Attribute { public string Group { get; private set; } public ConfigGroupAttribute(string Group) { this.Group = Group; base..ctor(); } } [AttributeUsage(AttributeTargets.Property)] internal class ConfigIgnoreAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property)] internal class ConfigRangeAttribute : Attribute { internal float Min { get; private set; } internal float Max { get; private set; } internal ConfigRangeAttribute(float min, float max) { Min = min; Max = max; } } [Serializable] internal abstract class LoafConfig<T> where T : LoafConfig<T> { internal List<(PropertyInfo, object)> configEntries = new List<(PropertyInfo, object)>(); internal ConfigFile configFile { get; private set; } public LoafConfig(ConfigFile configFile) { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Expected O, but got Unknown if (configFile == null) { return; } this.configFile = configFile; string header = "Misc"; Type typeFromHandle = typeof(T); PropertyInfo[] properties = typeFromHandle.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.GetCustomAttribute(typeof(ConfigIgnoreAttribute)) == null) { ConfigGroupAttribute configGroupAttribute = (ConfigGroupAttribute)propertyInfo.GetCustomAttribute(typeof(ConfigGroupAttribute)); if (configGroupAttribute != null) { header = configGroupAttribute.Group.Replace(" ", ""); } string text = "no description here :pensive:"; ConfigDescAttribute configDescAttribute = (ConfigDescAttribute)propertyInfo.GetCustomAttribute(typeof(ConfigDescAttribute)); if (configDescAttribute != null) { text = configDescAttribute.Description; } ConfigDescription val = new ConfigDescription(text, (AcceptableValueBase)null, Array.Empty<object>()); ConfigRangeAttribute configRangeAttribute = (ConfigRangeAttribute)propertyInfo.GetCustomAttribute(typeof(ConfigRangeAttribute)); val = ((configRangeAttribute == null) ? new ConfigDescription(text, (AcceptableValueBase)null, Array.Empty<object>()) : ((!(propertyInfo.PropertyType == typeof(int))) ? new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueRange<float>(configRangeAttribute.Min, configRangeAttribute.Max), Array.Empty<object>()) : new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueRange<int>((int)configRangeAttribute.Min, (int)configRangeAttribute.Max), Array.Empty<object>()))); if (propertyInfo.PropertyType == typeof(float)) { BindProperty<float>(propertyInfo, header, val); } if (propertyInfo.PropertyType == typeof(int)) { BindProperty<int>(propertyInfo, header, val); } if (propertyInfo.PropertyType == typeof(string)) { BindProperty<string>(propertyInfo, header, val); } if (propertyInfo.PropertyType == typeof(bool)) { BindProperty<bool>(propertyInfo, header, val); } } } } protected void BindProperty<V>(PropertyInfo property, string header, ConfigDescription description) { ConfigEntry<V> val = configFile.Bind<V>(header, property.Name, (V)property.GetValue(this), description); configEntries.Add((property, val)); property.SetValue(this, val.Value); } } internal abstract class LoafSyncedConfig<T> : LoafConfig<T> where T : LoafSyncedConfig<T> { internal static T Default { get; private set; } internal LoafSyncedConfig(ConfigFile file) : base(file) { if (Default == null) { Default = (T)this; } } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)] internal class RequiresRestartAttribute : Attribute { public bool RequiresRestart { get; private set; } public RequiresRestartAttribute(bool requiresRestart = true) { RequiresRestart = requiresRestart; base..ctor(); } } } namespace FacilityMeltdown.Util.Attributes { internal class CompatibleDependencyAttribute : BepInDependency { public Type Handler; public CompatibleDependencyAttribute(string guid, Type handlerType) : base(guid, (DependencyFlags)2) { Handler = handlerType; } public static void Init(BaseUnityPlugin source) { IEnumerable<CompatibleDependencyAttribute> customAttributes = ((MemberInfo)((object)source).GetType()).GetCustomAttributes<CompatibleDependencyAttribute>(); foreach (CompatibleDependencyAttribute item in customAttributes) { if (Chainloader.PluginInfos.ContainsKey(((BepInDependency)item).DependencyGUID)) { item.Handler.GetMethod("Initialize", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, null); item.Handler = null; } } } } } namespace FacilityMeltdown.Patches { [HarmonyPatch(typeof(LungProp))] internal static class ApparaticePatch { [HarmonyPrefix] [HarmonyPatch("EquipItem")] internal static void BeginMeltdownSequence(LungProp __instance, ref bool ___isLungDocked) { if (!((NetworkBehaviour)__instance).IsHost || !___isLungDocked || MeltdownAPI.MeltdownStarted) { return; } try { if (MeltdownPlugin.config.OverrideApparatusValue) { ((GrabbableObject)__instance).scrapValue = Mathf.RoundToInt((float)MeltdownPlugin.config.ApparatusValue * WeatherRegistryIntegration.GetWeatherMultiplier()); } GameObject val = Object.Instantiate<GameObject>(MeltdownPlugin.assets.meltdownHandlerPrefab); val.GetComponent<NetworkObject>().Spawn(false); } catch (Exception ex) { MeltdownPlugin.logger.LogError((object)ex); } } [HarmonyPrefix] [HarmonyPatch("Start")] internal static void AddRadiationSource(LungProp __instance) { MeltdownMoonMapper.EnsureMeltdownMoonMapper(); MeltdownInteriorMapper.EnsureMeltdownInteriorMapper(); try { RadiationSource radiationSource = ((Component)__instance).gameObject.AddComponent<RadiationSource>(); radiationSource.radiationAmount = 80f; radiationSource.radiationDistance = 60f; MeltdownMoonMapper.EnsureMeltdownMoonMapper(); if (MeltdownPlugin.config.OverrideApparatusValue) { ((GrabbableObject)__instance).scrapValue = Mathf.RoundToInt((float)MeltdownPlugin.config.ApparatusValue * WeatherRegistryIntegration.GetWeatherMultiplier()); } MeltdownPlugin.logger.LogDebug((object)((GrabbableObject)__instance).scrapValue); } catch (Exception ex) { MeltdownPlugin.logger.LogError((object)ex); } } } [HarmonyPatch(typeof(BlobAI))] internal class BlobAIPatch { [HarmonyPrefix] [HarmonyPatch("Start")] internal static void AddRadiationSource(BlobAI __instance) { RadiationSource radiationSource = ((Component)__instance).gameObject.AddComponent<RadiationSource>(); radiationSource.radiationAmount = 30f; radiationSource.radiationDistance = 25f; } } [HarmonyPatch(typeof(EntranceTeleport))] internal static class EntranceTeleportPatch { [HarmonyPrefix] [HarmonyPatch("FindExitPoint")] private static bool dontAllowReneter(ref bool __result) { if ((Object)(object)MeltdownHandler.Instance != (Object)null && MeltdownHandler.Instance.HasExplosionOccured()) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { internal static List<GameObject> networkPrefabsToRegister = new List<GameObject>(); [HarmonyPatch("Start")] [HarmonyPrefix] private static void AddNetworkPrefabs() { foreach (GameObject item in networkPrefabsToRegister) { NetworkManager.Singleton.AddNetworkPrefab(item); MeltdownPlugin.logger.LogDebug((object)("Registered " + ((Object)item).name + " as a network prefab.")); } MeltdownPlugin.logger.LogInfo((object)$"Succesfully registered {networkPrefabsToRegister.Count} network prefabs."); } [HarmonyPostfix] [HarmonyPatch("StartDisconnect")] public static void PlayerLeave() { MeltdownPlugin.config = LoafSyncedConfig<MeltdownConfig>.Default; } } [HarmonyPatch(typeof(GrabbableObject))] public class GrabbableObjectPatch { [HarmonyPrefix] [HarmonyPatch("Update")] internal static void ApplyMinPeople(GrabbableObject __instance) { LungProp apparatus = (LungProp)(object)((__instance is LungProp) ? __instance : null); if (apparatus == null) { return; } if (!apparatus.isLungDocked) { if (!((GrabbableObject)apparatus).grabbable) { ((GrabbableObject)apparatus).customGrabTooltip = ""; ((GrabbableObject)apparatus).grabbable = true; } return; } int num = StartOfRound.Instance.GetConnectedPlayers().Count((PlayerControllerB player) => Vector3.Distance(((Component)player).transform.position, ((Component)apparatus).transform.position) < 15f); int num2 = Mathf.Min(MeltdownPlugin.config.MinPeopleToPullApparatus, StartOfRound.Instance.livingPlayers); if (num < num2 && TimeOfDay.Instance.GetCurrentTime().hours < 21) { ((GrabbableObject)apparatus).customGrabTooltip = $"[ NEEDS {num2} PEOPLE ]"; ((GrabbableObject)apparatus).grabbable = false; } else { ((GrabbableObject)apparatus).customGrabTooltip = ""; ((GrabbableObject)apparatus).grabbable = true; } } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerControllerPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnReceiveSync; } private const string MESSAGE_REQUEST = "meltdown_OnRequestConfigSync"; private const string MESSAGE_RECIEVE = "meltdown_OnRecieveConfigSync"; private const int IntSize = 4; [HarmonyPostfix] [HarmonyPatch("ConnectClientToPlayerObject")] private static void SyncConfig() { //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_0066: Expected O, but got Unknown //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_0036: Expected O, but got Unknown if (NetworkManager.Singleton.IsHost) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("meltdown_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); return; } CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveSync; <>O.<1>__OnReceiveSync = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("meltdown_OnRecieveConfigSync", (HandleNamedMessageDelegate)obj2); RequestSync(); } public static void RequestSync() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsHost) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("meltdown_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsHost) { return; } MeltdownPlugin.logger.LogInfo((object)$"Config sync request received from client: {clientId}"); byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject((object)MeltdownPlugin.config)); int num = bytes.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + 4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(bytes, -1, 0); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("meltdown_OnRecieveConfigSync", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { MeltdownPlugin.logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0078: 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_008d: Expected O, but got Unknown if (!((FastBufferReader)(ref reader)).TryBeginRead(4)) { MeltdownPlugin.logger.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { MeltdownPlugin.logger.LogError((object)"Config sync error: Host could not sync."); return; } byte[] bytes = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref bytes, num, 0); MeltdownPlugin.logger.LogDebug((object)Encoding.UTF8.GetString(bytes)); MeltdownPlugin.config = JsonConvert.DeserializeObject<MeltdownConfig>(Encoding.UTF8.GetString(bytes), new JsonSerializerSettings { ContractResolver = (IContractResolver)(object)new IncludePrivateSetterContractResolver() }); MeltdownPlugin.logger.LogDebug((object)"Deserialized values are: "); PropertyInfo[] properties = MeltdownPlugin.config.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in properties) { MeltdownPlugin.logger.LogDebug((object)$"{propertyInfo.Name} => {propertyInfo.GetValue(MeltdownPlugin.config)}"); } MeltdownPlugin.logger.LogInfo((object)"Successfully synced config with host."); } } internal class IncludePrivateSetterContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) JsonProperty val = ((DefaultContractResolver)this).CreateProperty(member, memberSerialization); if (!val.Writable && member is PropertyInfo propertyInfo) { val.Writable = propertyInfo.GetSetMethod(nonPublic: true) != null; } return val; } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatches { [HarmonyPrefix] [HarmonyPatch("EndOfGame")] internal static void UnloadMeltdownHandler() { if (Object.op_Implicit((Object)(object)MeltdownHandler.Instance)) { Object.Destroy((Object)(object)((Component)MeltdownHandler.Instance).gameObject); } if (Object.op_Implicit((Object)(object)MeltdownMoonMapper.Instance)) { Object.Destroy((Object)(object)((Component)MeltdownMoonMapper.Instance).gameObject); } if (Object.op_Implicit((Object)(object)MeltdownInteriorMapper.Instance)) { Object.Destroy((Object)(object)((Component)MeltdownInteriorMapper.Instance).gameObject); } } } [HarmonyPatch(typeof(Terminal))] internal class TerminalPatch { internal class ReactorHealthReport { public float reactorInstability; public float timeRemaining; public float generatedAt = Time.time; public string GetFlavourText() { if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.75f) { return "reactorscan.result.flavour.start"; } if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.5f) { return "reactorscan.result.flavour.low"; } if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.33f) { return "reactorscan.result.flavour.medium"; } if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.15f) { return "reactorscan.result.flavour.high"; } return ""; } public string GetTeminalOutput() { string text = "reactorscan.result.unstable".Translate(); text = SubstituteVariables(text); return text + "\n\n" + SubstituteVariables(GetFlavourText().Translate()) + "\n\n"; } } internal static float lastHealthCheck = 0f; internal static ReactorHealthReport lastReport = null; internal static List<TerminalKeyword> terminalKeywordsToRegister = new List<TerminalKeyword>(); internal static List<TerminalNode> terminalNodesToRegister = new List<TerminalNode>(); internal static string SubstituteVariables(string text) { StringBuilder stringBuilder = new StringBuilder(text); stringBuilder.Replace("<cooldown>", MeltdownPlugin.config.ShipScanCooldown.ToString()); stringBuilder.Replace("<instability>", lastReport.reactorInstability.ToString()); stringBuilder.Replace("<time_left>", lastReport.timeRemaining.ToString()); return stringBuilder.ToString(); } internal static string GetTextForNode() { if (Object.op_Implicit((Object)(object)MeltdownHandler.Instance)) { string text = "reactorscan.error.overheat"; if (ReactorHealthCheckReady()) { lastHealthCheck = Time.time; lastReport = GetNewReactorHealthReport(); text = "reactorscan.success"; } return SubstituteVariables(text.Translate()) + lastReport.GetTeminalOutput(); } return "reactorscan.result.stable".Translate(); } internal static bool ReactorHealthCheckReady() { return Time.time >= lastHealthCheck + MeltdownPlugin.config.ShipScanCooldown; } internal static ReactorHealthReport GetNewReactorHealthReport() { float num = ((float)MeltdownPlugin.config.MeltdownTime - MeltdownHandler.Instance.meltdownTimer) / (float)MeltdownPlugin.config.MeltdownTime * 100f; num = Mathf.Round(num / MeltdownPlugin.config.ShipScanAccuracy) * MeltdownPlugin.config.ShipScanAccuracy; float timeRemaining = (1f - num / 100f) * (float)MeltdownPlugin.config.MeltdownTime; return new ReactorHealthReport { reactorInstability = num, timeRemaining = timeRemaining }; } [HarmonyPostfix] [HarmonyPatch("Awake")] internal static void RegisterNodes(Terminal __instance) { __instance.terminalNodes.allKeywords = CollectionExtensions.AddRangeToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, terminalKeywordsToRegister.ToArray()); __instance.terminalNodes.terminalNodes.AddRange(terminalNodesToRegister); } [HarmonyPostfix] [HarmonyPatch("TextPostProcess")] internal static void ProcessReactorText(TerminalNode node, ref string __result) { if ((Object)(object)node == (Object)(object)MeltdownPlugin.assets.reactorHealthNode) { __result = "\n\n\n" + GetTextForNode(); } } [HarmonyPostfix] [HarmonyPatch(typeof(StormyWeather), "GetMetalObjectsAfterDelay")] internal static void CancelCoroutine(StormyWeather __instance, ref IEnumerator __result) { ((MonoBehaviour)__instance).StopCoroutine(__result); } } } namespace FacilityMeltdown.MeltdownSequence { public static class MeltdownEffects { [CompilerGenerated] private sealed class <AtProgress>d__6 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float progress; public IEnumerator enumerator; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AtProgress>d__6(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; goto IL_003b; case 1: <>1__state = -1; goto IL_003b; case 2: { <>1__state = -1; return false; } IL_003b: if (MeltdownAPI.MeltdownStarted && MeltdownHandler.Instance.Progress > progress) { <>2__current = null; <>1__state = 1; return true; } <>2__current = enumerator; <>1__state = 2; 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 <AtProgress>d__7 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float progress; public Action callback; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AtProgress>d__7(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (MeltdownAPI.MeltdownStarted && MeltdownHandler.Instance.Progress > progress) { <>2__current = null; <>1__state = 1; return true; } callback(); 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 <EmergencyLights>d__8 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float onTime; public List<(Light light, Color originalColour)> originalLightColours; public float offTime; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <EmergencyLights>d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_007f: 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) //IL_00b0: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012b: 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_015c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; MeltdownPlugin.logger.LogDebug((object)"Switching lights ON"); for (int j = 0; j < RoundManager.Instance.allPoweredLightsAnimators.Count; j++) { RoundManager.Instance.allPoweredLightsAnimators[j].SetBool("on", true); } for (int k = 0; k < MeltdownMoonMapper.Instance.outsideEmergencyLights.Count; k++) { MeltdownMoonMapper.Instance.outsideEmergencyLights[k].color = MeltdownMoonMapper.Instance.outsideEmergencyLightColour; } <>2__current = (object)new WaitForSeconds(onTime); <>1__state = 1; return true; } case 1: { <>1__state = -1; MeltdownPlugin.logger.LogDebug((object)"Switching lights OFF"); for (int i = 0; i < RoundManager.Instance.allPoweredLightsAnimators.Count; i++) { RoundManager.Instance.allPoweredLightsAnimators[i].SetBool("on", false); } foreach (var (val, color) in originalLightColours) { val.color = color; } <>2__current = (object)new WaitForSeconds(offTime); <>1__state = 2; return true; } case 2: <>1__state = -1; 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 <RepeatUntilEndOfMeltdown>d__1 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func<IEnumerator> enumerator; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <RepeatUntilEndOfMeltdown>d__1(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(Random.Range(0f, 1f)); <>1__state = 1; return true; case 1: <>1__state = -1; break; case 2: <>1__state = -1; break; } MeltdownPlugin.logger.LogDebug((object)"looping effect"); <>2__current = enumerator(); <>1__state = 2; 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 <WarningAnnouncer>d__10 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public AudioSource source; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WarningAnnouncer>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: { <>1__state = -1; source.volume = MeltdownPlugin.clientConfig.MusicVolume; AudioClip clip = MeltdownPlugin.assets.warnings[Random.Range(0, MeltdownPlugin.assets.warnings.Length)]; source.clip = clip; source.Play(); <>2__current = (object)new WaitForSeconds(source.clip.length); <>1__state = 1; return true; } case 1: <>1__state = -1; 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 <WithDelay>d__2 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public IEnumerator enumerator; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WithDelay>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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; <>2__current = enumerator; <>1__state = 2; return true; case 2: <>1__state = -1; 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 <WithDelay>d__3 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public Action callback; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WithDelay>d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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; callback(); 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 <WithRandomDelay>d__4 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Func<IEnumerator> enumerator; public float min; public float max; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WithRandomDelay>d__4(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = WithDelay(enumerator(), Random.Range(min, max)); <>1__state = 1; return true; case 1: <>1__state = -1; 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 <WithRandomDelay>d__5 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Action callback; public float min; public float max; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <WithRandomDelay>d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = WithDelay(callback, Random.Range(min, max)); <>1__state = 1; return true; case 1: <>1__state = -1; 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(); } } public static List<(Light light, Color originalColour)> SetupEmergencyLights() { //IL_0019: 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) for (int i = 0; i < RoundManager.Instance.allPoweredLights.Count; i++) { RoundManager.Instance.allPoweredLights[i].color = MeltdownInteriorMapper.Instance.outsideEmergencyLightColour; } List<(Light, Color)> list = new List<(Light, Color)>(); for (int j = 0; j < MeltdownMoonMapper.Instance.outsideEmergencyLights.Count; j++) { list.Add((MeltdownMoonMapper.Instance.outsideEmergencyLights[j], MeltdownMoonMapper.Instance.outsideEmergencyLights[j].color)); } return list; } [IteratorStateMachine(typeof(<RepeatUntilEndOfMeltdown>d__1))] public static IEnumerator RepeatUntilEndOfMeltdown(Func<IEnumerator> enumerator) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <RepeatUntilEndOfMeltdown>d__1(0) { enumerator = enumerator }; } [IteratorStateMachine(typeof(<WithDelay>d__2))] public static IEnumerator WithDelay(IEnumerator enumerator, float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WithDelay>d__2(0) { enumerator = enumerator, delay = delay }; } [IteratorStateMachine(typeof(<WithDelay>d__3))] public static IEnumerator WithDelay(Action callback, float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WithDelay>d__3(0) { callback = callback, delay = delay }; } [IteratorStateMachine(typeof(<WithRandomDelay>d__4))] public static IEnumerator WithRandomDelay(Func<IEnumerator> enumerator, float min, float max) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WithRandomDelay>d__4(0) { enumerator = enumerator, min = min, max = max }; } [IteratorStateMachine(typeof(<WithRandomDelay>d__5))] public static IEnumerator WithRandomDelay(Action callback, float min, float max) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WithRandomDelay>d__5(0) { callback = callback, min = min, max = max }; } [IteratorStateMachine(typeof(<AtProgress>d__6))] public static IEnumerator AtProgress(IEnumerator enumerator, float progress) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AtProgress>d__6(0) { enumerator = enumerator, progress = progress }; } [IteratorStateMachine(typeof(<AtProgress>d__7))] public static IEnumerator AtProgress(Action callback, float progress) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AtProgress>d__7(0) { callback = callback, progress = progress }; } [IteratorStateMachine(typeof(<EmergencyLights>d__8))] public static IEnumerator EmergencyLights(float onTime, float offTime, List<(Light light, Color originalColour)> originalLightColours) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <EmergencyLights>d__8(0) { onTime = onTime, offTime = offTime, originalLightColours = originalLightColours }; } public static void InsideParticleEffects() { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (MeltdownPlugin.clientConfig.ScreenShake) { RaycastHit val2 = default(RaycastHit); for (int i = 0; i < Random.Range(5, 15); i++) { Vector3 val = GetRandomPositionInsideFacility() + Vector3.up; if (Physics.Raycast(new Ray(val, Vector3.up), ref val2, 20f, 256)) { GameObject val3 = MeltdownPlugin.assets.facilityEffects[Random.Range(0, MeltdownPlugin.assets.facilityEffects.Length)]; GameObject val4 = Object.Instantiate<GameObject>(val3); val3.transform.position = ((RaycastHit)(ref val2)).point; val4.transform.parent = ((Component)MeltdownHandler.Instance).transform; } } } if (GameNetworkManager.Instance.localPlayerController.isInsideFactory) { Object.Instantiate<GameObject>(StartOfRound.Instance.explosionPrefab, GetRandomPositionNearPlayer(), Quaternion.Euler(-90f, 0f, 0f), RoundManager.Instance.mapPropsContainer.transform); } if (MeltdownPlugin.clientConfig.ScreenShake) { if (MeltdownHandler.Instance.Progress > 0.5f) { HUDManager.Instance.ShakeCamera((ScreenShakeType)1); } else { HUDManager.Instance.ShakeCamera((ScreenShakeType)3); } } } [IteratorStateMachine(typeof(<WarningAnnouncer>d__10))] public static IEnumerator WarningAnnouncer(AudioSource source) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <WarningAnnouncer>d__10(0) { source = source }; } private static Vector3 PlacePositionInsideFacility(Vector3 position, float radius = 10f) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) return RoundManager.Instance.GetRandomNavMeshPositionInRadius(position, radius, default(NavMeshHit)); } private static Vector3 GetRandomPositionNearPlayer(float radius = 15f) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) return PlacePositionInsideFacility(((Component)GameNetworkManager.Instance.localPlayerController).transform.position + Random.insideUnitSphere * radius); } private static Vector3 GetRandomPositionInsideFacility() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) return PlacePositionInsideFacility(RoundManager.Instance.insideAINodes[Random.Range(0, RoundManager.Instance.insideAINodes.Length)].transform.position); } } } namespace FacilityMeltdown.MeltdownSequence.Behaviours { internal class FacilityExplosionHandler : MonoBehaviour { private PlayerControllerB player; private float size; private float time; private LocalVolumetricFog internalFog; private void Awake() { player = GameNetworkManager.Instance.localPlayerController; internalFog = ((Component)this).GetComponent<LocalVolumetricFog>(); if ((Object)(object)internalFog == (Object)null) { MeltdownPlugin.logger.LogError((object)"Failed to get volumetric fog!"); } if (MeltdownPlugin.clientConfig.ScreenShake) { HUDManager.Instance.ShakeCamera((ScreenShakeType)0); HUDManager.Instance.ShakeCamera((ScreenShakeType)1); HUDManager.Instance.ShakeCamera((ScreenShakeType)2); HUDManager.Instance.ShakeCamera((ScreenShakeType)3); } if (!player.isPlayerDead && player.isInsideFactory) { if (player.isInElevator) { MeltdownPlugin.logger.LogWarning((object)"Player is inside ship and facility at the same time!! Did you teleport out? Aborting kill"); } else { KillPlayer(); } } } private void Update() { //IL_0030: 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_005e: 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) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00a3: Unknown result type (might be due to invalid IL or missing references) time += Time.deltaTime * 10f; size = TimeToSize(time); ((Component)this).transform.localScale = Vector3.one * size; if ((Object)(object)internalFog != (Object)null) { internalFog.parameters.size = Vector3.one * size * 1.25f; } if (!ShouldIgnorePlayer() && PlayerIsInsideFireball()) { player.KillPlayer(Vector3.zero, false, (CauseOfDeath)3, 0, default(Vector3)); } } private void KillPlayer() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) player.KillPlayer(Vector3.zero, false, (CauseOfDeath)3, 0, default(Vector3)); } private bool PlayerIsInsideFireball() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) < size; } private bool ShouldIgnorePlayer() { if (!player.isPlayerDead) { if (player.isInElevator) { return StartOfRound.Instance.shipIsLeaving; } return false; } return true; } private float TimeToSize(float time) { return Mathf.Log(time) + 3f + 2f * time; } } public class MeltdownHandler : NetworkBehaviour { [CompilerGenerated] private sealed class <ShipTakeOff>d__25 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private StartOfRound <shipManager>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ShipTakeOff>d__25(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <shipManager>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <shipManager>5__2 = StartOfRound.Instance; <shipManager>5__2.shipLeftAutomatically = true; <shipManager>5__2.shipIsLeaving = true; HUDManager.Instance.ReadDialogue(GetDialogue("meltdown.dialogue.shiptakeoff")); <>2__current = (object)new WaitForSeconds(3f); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSeconds(3f); <>1__state = 2; return true; case 2: { <>1__state = -1; ((Behaviour)HUDManager.Instance.shipLeavingEarlyIcon).enabled = false; StartMatchLever val = Object.FindObjectOfType<StartMatchLever>(); val.triggerScript.animationString = "SA_PushLeverBack"; val.leverHasBeenPulled = false; val.triggerScript.interactable = false; val.leverAnimatorObject.SetBool("pullLever", false); <shipManager>5__2.ShipLeave(); <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 3; return true; } case 3: <>1__state = -1; <shipManager>5__2.SetSpectateCameraToGameOverMode(true, (PlayerControllerB)null); if (GameNetworkManager.Instance.localPlayerController.isPlayerDead) { GameNetworkManager.Instance.localPlayerController.SetSpectatedPlayerEffects(true); } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 4; return true; case 4: <>1__state = -1; <>2__current = (object)new WaitForSeconds(9.5f); <>1__state = 5; return true; case 5: <>1__state = -1; 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(); } } internal float meltdownTimer; private bool meltdownStarted; private GameObject explosion; private GameObject shockwave; [SerializeField] private AudioSource meltdownMusic; [SerializeField] private AudioSource warningSource; public float TimeLeftUntilMeltdown => meltdownTimer; public float Progress => 1f - TimeLeftUntilMeltdown / (float)MeltdownPlugin.config.MeltdownTime; private static PlayerControllerB Player => GameNetworkManager.Instance.localPlayerController; internal static MeltdownHandler Instance { get; private set; } private Vector3 effectOrigin => MeltdownMoonMapper.Instance.EffectOrigin; [ClientRpc] private void StartMeltdownClientRpc() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Invalid comparison between Unknown and I4 //IL_005f: 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_006d: 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_00c1: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3631067672u, val, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3631067672u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } base.__rpc_exec_stage = (__RpcExecStage)0; if ((Object)(object)Instance != (Object)null) { return; } Instance = this; Stopwatch stopwatch = new Stopwatch(); MeltdownPlugin.logger.LogInfo((object)"Beginning Meltdown Sequence! I'd run if I were you!"); stopwatch.Start(); MeltdownMoonMapper.EnsureMeltdownMoonMapper(); MeltdownInteriorMapper.EnsureMeltdownInteriorMapper(); if ((Object)(object)MeltdownInteriorMapper.Instance == (Object)null) { MeltdownPlugin.logger.LogError((object)"WHAT. Just ensured that the interior mapper exists and it doesnt?!?"); } if ((Object)(object)MeltdownMoonMapper.Instance == (Object)null) { MeltdownPlugin.logger.LogError((object)"WHAT. Just ensured that the moon mapper exists and it doesnt?!?"); } stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Ensuring data objects exist: {stopwatch.ElapsedMilliseconds}ms"); meltdownTimer = MeltdownPlugin.config.MeltdownTime; stopwatch.Restart(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Creating audio: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.WithDelay(delegate { HUDManager.Instance.ReadDialogue(GetDialogue("meltdown.dialogue.start")); }, 5f)); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.WithDelay(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.WithRandomDelay(() => MeltdownEffects.WarningAnnouncer(warningSource), 10f, 15f)), 10f)); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.WithRandomDelay((Action)MeltdownEffects.InsideParticleEffects, 10f, 15f))); if (MeltdownPlugin.config.EmergencyLights) { try { List<(Light, Color)> originalLightColours = MeltdownEffects.SetupEmergencyLights(); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.EmergencyLights(2f, 5f, originalLightColours))); } catch (Exception arg) { MeltdownPlugin.logger.LogError((object)$"Failed to set the emergency light colour: {arg}"); } } ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.WithRandomDelay(delegate { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shockwave != (Object)null) { Object.Destroy((Object)(object)shockwave); } shockwave = Object.Instantiate<GameObject>(MeltdownPlugin.assets.shockwavePrefab); shockwave.transform.position = effectOrigin; }, 25f, 35f))); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.AtProgress((Action)HUDManager.Instance.RadiationWarningHUD, 0.5f)); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Starting effects: {stopwatch.ElapsedMilliseconds}ms"); if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer) { SpawnEnemies(); } stopwatch.Restart(); if (effectOrigin == Vector3.zero) { MeltdownPlugin.logger.LogError((object)"Effect Origin is Vector3.Zero! We couldn't find the effect origin"); HUDManager.Instance.DisplayGlobalNotification("Failed to find effect origin... Things will look broken."); } if (MeltdownPlugin.clientConfig.ScreenShake) { HUDManager.Instance.ShakeCamera((ScreenShakeType)3); HUDManager.Instance.ShakeCamera((ScreenShakeType)2); } stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Getting effect origin: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); MeltdownAPI.OnMeltdownStart(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"MeltdownAPI.OnMeltdownStart(): {stopwatch.ElapsedMilliseconds}ms"); meltdownStarted = true; } private void SpawnEnemies() { Stopwatch stopwatch = Stopwatch.StartNew(); List<string> disallowed = MeltdownPlugin.config.GetDisallowedEnemies(); List<SpawnableEnemyWithRarity> list = RoundManager.Instance.currentLevel.Enemies.Where((SpawnableEnemyWithRarity enemy) => !EnemyCannotBeSpawned(enemy.enemyType) && !disallowed.Contains(enemy.enemyType.enemyName)).ToList(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Filtering enemies: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); List<EnemyVent> list2 = RoundManager.Instance.allEnemyVents.Where((EnemyVent vent) => !vent.occupied).ToList(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Filtering vents: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); for (int i = 0; i < Mathf.Min(MeltdownPlugin.config.MonsterSpawnAmount, list2.Count); i++) { EnemyVent val = list2[Random.Range(0, list2.Count)]; list2.Remove(val); SpawnableEnemyWithRarity val2 = list[Random.Range(0, list2.Count)]; RoundManager instance = RoundManager.Instance; instance.currentEnemyPower += val2.enemyType.PowerLevel; MeltdownPlugin.logger.LogInfo((object)("Spawning a " + val2.enemyType.enemyName + " during the meltdown sequence")); val.SpawnEnemy(val2); } stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Spawning enemies: {stopwatch.ElapsedMilliseconds}ms"); } public override void OnNetworkSpawn() { if (MeltdownPlugin.loadedFully && ((NetworkBehaviour)this).IsHost) { StartMeltdownClientRpc(); } } internal bool EnemyCannotBeSpawned(EnemyType type) { if (!type.spawningDisabled) { return type.numberSpawned >= type.MaxCount; } return true; } internal static DialogueSegment[] GetDialogue(string translation) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown JArray translationSet = LangParser.GetTranslationSet(translation); DialogueSegment[] array = (DialogueSegment[])(object)new DialogueSegment[((JContainer)translationSet).Count]; for (int i = 0; i < ((JContainer)translationSet).Count; i++) { array[i] = new DialogueSegment { bodyText = ((string)translationSet[i]).Replace("<meltdown_time>", Math.Round((float)MeltdownPlugin.config.MeltdownTime / 60f).ToString()), speakerText = "meltdown.dialogue.speaker".Translate() }; } return array; } private void OnDisable() { if (!((Object)(object)Instance != (Object)(object)this)) { MeltdownPlugin.logger.LogInfo((object)"Cleaning up MeltdownHandler."); Instance = null; if ((Object)(object)explosion != (Object)null) { Object.Destroy((Object)(object)explosion); } if ((Object)(object)shockwave != (Object)null) { Object.Destroy((Object)(object)shockwave); } if (!meltdownStarted) { MeltdownPlugin.logger.LogError((object)"MeltdownHandler was disabled without starting a meltdown, a client most likely failed the MeltdownReadyCheck. If you are going to report this make sure to provide ALL client logs."); } } } private void Update() { //IL_00df: Unknown result type (might be due to invalid IL or missing references) if (!meltdownStarted || HasExplosionOccured()) { return; } StartOfRound instance = StartOfRound.Instance; meltdownMusic.volume = (float)MeltdownPlugin.clientConfig.MusicVolume / 100f; if (!Player.isInsideFactory && !MeltdownPlugin.clientConfig.MusicPlaysOutside) { meltdownMusic.volume = 0f; } meltdownTimer -= Time.deltaTime; if (meltdownTimer <= 3f && !instance.shipIsLeaving) { ((MonoBehaviour)this).StartCoroutine(ShipTakeOff()); } if (meltdownTimer <= 0f) { meltdownMusic.Stop(); GameObject val = MeltdownMoonMapper.Instance.explosionPrefab; if ((Object)(object)val == (Object)null) { val = MeltdownPlugin.assets.facilityExplosionPrefab; } explosion = Object.Instantiate<GameObject>(val); explosion.transform.position = effectOrigin; FacilityExplosionHandler facilityExplosionHandler = default(FacilityExplosionHandler); if (!explosion.TryGetComponent<FacilityExplosionHandler>(ref facilityExplosionHandler)) { explosion.AddComponent<FacilityExplosionHandler>(); } } } [IteratorStateMachine(typeof(<ShipTakeOff>d__25))] private IEnumerator ShipTakeOff() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ShipTakeOff>d__25(0); } public bool HasExplosionOccured() { return (Object)(object)explosion != (Object)null; } protected override void __initializeVariables() { ((NetworkBehaviour)this).__initializeVariables(); } protected override void __initializeRpcs() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown ((NetworkBehaviour)this).__registerRpc(3631067672u, new RpcReceiveHandler(__rpc_handler_3631067672), "StartMeltdownClientRpc"); ((NetworkBehaviour)this).__initializeRpcs(); } private static void __rpc_handler_3631067672(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0029: 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) NetworkManager networkManager = target.NetworkManager; if (networkManager != null && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)1; ((MeltdownHandler)(object)target).StartMeltdownClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } [MethodImpl(MethodImplOptions.NoInlining)] protected internal override string __getTypeName() { return "MeltdownHandler"; } } public class Shockwave : MonoBehaviour { private bool localPlayerCameraShake; private float size; private AudioSource sound; private Renderer renderer; private void Awake() { sound = ((Component)this).gameObject.AddComponent<AudioSource>(); sound.clip = MeltdownPlugin.assets.shockwave; sound.spatialBlend = 0f; sound.loop = false; renderer = ((Component)this).GetComponent<Renderer>(); } private void Update() { //IL_0029: 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) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; size += Time.deltaTime * 50f; ((Component)this).transform.localScale = Vector3.one * size; if (localPlayerController.isInsideFactory) { renderer.enabled = false; return; } renderer.enabled = true; if (PlayerIsInsideShockwave() && !localPlayerCameraShake && MeltdownPlugin.clientConfig.ScreenShake) { ScreenShake(); localPlayerCameraShake = true; sound.Play(); } } private void ScreenShake() { HUDManager.Instance.ShakeCamera((ScreenShakeType)1); } internal bool PlayerIsInsideShockwave() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) return Vector3.Distance(((Component)this).transform.position, ((Component)GameNetworkManager.Instance.localPlayerController).transform.position) <= size; } } } namespace FacilityMeltdown.Lang { internal static class LangParser { internal static Dictionary<string, string> languages { get; private set; } internal static Dictionary<string, object> loadedLanguage { get; private set; } internal static Dictionary<string, object> defaultLanguage { get; private set; } internal static void Init() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FacilityMeltdown.Lang.defs.json"); using StreamReader streamReader = new StreamReader(stream); string text = streamReader.ReadToEnd(); languages = JsonConvert.DeserializeObject<Dictionary<string, string>>(text); } internal static Dictionary<string, object> LoadLanguage(string id) { using Stream stream = File.Open(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lang", id + ".json"), FileMode.Open); using StreamReader streamReader = new StreamReader(stream); string text = streamReader.ReadToEnd(); return JsonConvert.DeserializeObject<Dictionary<string, object>>(text); } internal static void SetLanguage(string id) { MeltdownPlugin.logger.LogInfo((object)("Loading language: " + languages[id] + " (" + id + ")")); loadedLanguage = LoadLanguage(id); MeltdownPlugin.logger.LogInfo((object)("Loaded " + languages[id])); } internal static string GetTranslation(string translation) { if (loadedLanguage.TryGetValue(translation, out var value)) { return (string)value; } if (defaultLanguage.TryGetValue(translation, out value)) { MeltdownPlugin.logger.LogError((object)("Falling back to english. for translation: " + translation)); return (string)value; } if (translation == "lang.missing") { MeltdownPlugin.logger.LogError((object)"LANG.MISSING IS MISSING!!!!! THIS IS BAD!! VERY BAD!!"); return "lang.missing; <translation_id>"; } return GetTranslation("lang.missing").Replace("<translation_id>", translation); } internal static JArray GetTranslationSet(string translation) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown if (loadedLanguage.TryGetValue(translation, out var value)) { MeltdownPlugin.logger.LogInfo((object)value.GetType()); return (JArray)((value is JArray) ? value : null); } if (defaultLanguage.TryGetValue(translation, out value)) { MeltdownPlugin.logger.LogError((object)("Falling back to english. for translation (dialogue): " + translation)); return (JArray)((value is JArray) ? value : null); } JArray val = new JArray(); val.Add(JToken.op_Implicit(GetTranslation("lang.missing").Replace("<translation_id>", translation))); return val; } } } namespace FacilityMeltdown.Integrations { internal class LethalConfigIntergration { public static bool Enabled { get; private set; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void Initialize() { Enabled = true; LethalConfigManager.SetModDescription("Maybe taking the appartus isn't such a great idea..."); HandleConfig(MeltdownPlugin.config); HandleConfig(MeltdownPlugin.clientConfig); } private static void HandleConfig<T>(LoafConfig<T> config) where T : LoafConfig<T> { //IL_00d2: 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) //IL_00e5: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Expected O, but got Unknown //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Expected O, but got Unknown bool flag = true; if (config.GetType().GetCustomAttribute<RequiresRestartAttribute>() != null) { flag = config.GetType().GetCustomAttribute<RequiresRestartAttribute>().RequiresRestart; } foreach (var configEntry in config.configEntries) { PropertyInfo property = configEntry.Item1; object uncastedEntry = configEntry.Item2; bool flag2 = flag; RequiresRestartAttribute customAttribute = property.GetCustomAttribute<RequiresRestartAttribute>(); if (customAttribute != null) { flag2 = customAttribute.RequiresRestart; } ConfigRangeAttribute customAttribute2 = property.GetCustomAttribute<ConfigRangeAttribute>(); if (property.PropertyType == typeof(int)) { if (customAttribute2 == null) { throw new NotImplementedException(property.Name + ": config entry of type: int, must have a range attribute, because i was too lazy lmao"); } ConfigEntry<int> obj2 = (ConfigEntry<int>)uncastedEntry; IntSliderOptions val = new IntSliderOptions(); ((BaseRangeOptions<int>)val).Min = (int)customAttribute2.Min; ((BaseRangeOptions<int>)val).Max = (int)customAttribute2.Max; ((BaseOptions)val).RequiresRestart = flag2; LethalConfigManager.AddConfigItem((BaseConfigItem)new IntSliderConfigItem(obj2, val)); if (!flag2) { ((ConfigEntry<int>)uncastedEntry).SettingChanged += delegate { property.SetValue(config, ((ConfigEntry<int>)uncastedEntry).Value); }; } } if (property.PropertyType == typeof(float)) { if (customAttribute2 == null) { throw new NotImplementedException(property.Name + ": config entry of type: float, must have a range attribute, because i was too lazy lmao"); } ConfigEntry<float> obj3 = (ConfigEntry<float>)uncastedEntry; FloatSliderOptions val2 = new FloatSliderOptions(); ((BaseRangeOptions<float>)val2).Min = customAttribute2.Min; ((BaseRangeOptions<float>)val2).Max = customAttribute2.Max; ((BaseOptions)val2).RequiresRestart = flag2; LethalConfigManager.AddConfigItem((BaseConfigItem)new FloatSliderConfigItem(obj3, val2)); if (!flag2) { ((ConfigEntry<float>)uncastedEntry).SettingChanged += delegate { property.SetValue(config, ((ConfigEntry<float>)uncastedEntry).Value); }; } } if (property.PropertyType == typeof(bool)) { LethalConfigManager.AddConfigItem((BaseConfigItem)new BoolCheckBoxConfigItem((ConfigEntry<bool>)uncastedEntry, flag2)); if (!flag2) { ((ConfigEntry<bool>)uncastedEntry).SettingChanged += delegate { property.SetValue(config, ((ConfigEntry<bool>)uncastedEntry).Value); }; } } if (!(property.PropertyType == typeof(string))) { continue; } LethalConfigManager.AddConfigItem((BaseConfigItem)new TextInputFieldConfigItem((ConfigEntry<string>)uncastedEntry, flag2)); if (!flag2) { ((ConfigEntry<string>)uncastedEntry).SettingChanged += delegate { property.SetValue(config, ((ConfigEntry<string>)uncastedEntry).Value); }; } } } } internal class LethalSettingsIntegration { public static bool Enabled { get; private set; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void Initialize() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown Enabled = true; VerticalComponent val = BuildConfig(MeltdownPlugin.clientConfig); ModSettingsConfig val2 = new ModSettingsConfig(); val2.Name = "FacilityMeltdown"; val2.Id = "me.loaforc.facilitymeltdown"; val2.Version = "2.6.15"; val2.Description = "Maybe taking the appartus isn't such a great idea..."; val2.MenuComponents = (MenuComponent[])(object)new MenuComponent[2] { (MenuComponent)BuildConfig(MeltdownPlugin.config), (MenuComponent)val }; ModMenu.RegisterMod(val2); val2 = new ModSettingsConfig(); val2.Name = "FacilityMeltdown"; val2.Id = "me.loaforc.facilitymeltdown"; val2.Version = "2.6.15"; val2.Description = "Maybe taking the appartus isn't such a great idea... (GameSettings are hidden in game)"; val2.MenuComponents = (MenuComponent[])(object)new MenuComponent[1] { (MenuComponent)val }; ModMenu.RegisterMod(val2, false, true); } private static VerticalComponent BuildConfig<T>(LoafConfig<T> config) where T : LoafConfig<T> { //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016e: 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_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Expected O, but got Unknown //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Expected O, but got Unknown //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02cf: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Expected O, but got Unknown bool flag = true; if (config.GetType().GetCustomAttribute<RequiresRestartAttribute>() != null) { flag = config.GetType().GetCustomAttribute<RequiresRestartAttribute>().RequiresRestart; } List<MenuComponent> list = new List<MenuComponent>(); string text = "Misc"; foreach (var configEntry in config.configEntries) { PropertyInfo property = configEntry.Item1; object uncastedEntry = configEntry.Item2; bool requiresRestart = flag; RequiresRestartAttribute customAttribute = property.GetCustomAttribute<RequiresRestartAttribute>(); if (customAttribute != null) { requiresRestart = customAttribute.RequiresRestart; } ConfigGroupAttribute configGroupAttribute = (ConfigGroupAttribute)property.GetCustomAttribute(typeof(ConfigGroupAttribute)); if (configGroupAttribute != null) { text = configGroupAttribute.Group; list.Add((MenuComponent)new LabelComponent { Text = text }); } else if (text == "Misc") { list.Add((MenuComponent)new LabelComponent { Text = text }); } ConfigRangeAttribute customAttribute2 = property.GetCustomAttribute<ConfigRangeAttribute>(); if (property.PropertyType == typeof(int)) { list.Add((MenuComponent)new SliderComponent { Value = (int)property.GetValue(config), WholeNumbers = true, MinValue = customAttribute2.Min, MaxValue = customAttribute2.Max, Text = property.Name, OnValueChanged = delegate(SliderComponent self, float value) { ((ConfigEntry<int>)uncastedEntry).Value = (int)value; if (!requiresRestart) { property.SetValue(config, value); } } }); } if (property.PropertyType == typeof(float)) { list.Add((MenuComponent)new SliderComponent { Value = (float)property.GetValue(config), MinValue = customAttribute2.Min, MaxValue = customAttribute2.Max, Text = property.Name, OnValueChanged = delegate(SliderComponent self, float value) { ((ConfigEntry<float>)uncastedEntry).Value = value; if (!requiresRestart) { property.SetValue(config, value); } } }); } if (property.PropertyType == typeof(bool)) { list.Add((MenuComponent)new ToggleComponent { Text = property.Name, Value = (bool)property.GetValue(config), OnValueChanged = delegate(ToggleComponent self, bool value) { ((ConfigEntry<bool>)uncastedEntry).Value = value; if (!requiresRestart) { property.SetValue(config, value); } } }); } if (!(property.PropertyType == typeof(string))) { continue; } list.Add((MenuComponent)new InputComponent { Placeholder = property.Name, Value = (string)property.GetValue(config), OnValueChanged = delegate(InputComponent self, string value) { ((ConfigEntry<string>)uncastedEntry).Value = value; if (!requiresRestart) { property.SetValue(config, value); } } }); } return null; } } internal class LobbyCompatibilityIntegration { public static bool Enabled { get; private set; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void Initialize() { Enabled = true; PluginHelper.RegisterPlugin("me.loaforc.facilitymeltdown", Version.Parse("2.6.15"), (CompatibilityLevel)2, (VersionStrictness)3); } } internal class WeatherRegistryIntegration { public static bool Enabled { get; private set; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void Initialize() { Enabled = true; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static float GetWeatherMultiplier() { return 1f; } } } namespace FacilityMeltdown.Equipment { public class GeigerCounterItem : GrabbableObject { [Space(15f)] [Header("Audio")] public AudioSource generalAudioSource; public AudioSource lowRadiation; public AudioSource mediumRadiation; public AudioSource highRadiation; public AudioClip toggle; public AudioClip outOfBattery; public GameObject needle; public float maxRotation = 25f; public float maxDetection = 50f; public override void ItemActivate(bool used, bool buttonDown = true) { ((GrabbableObject)this).ItemActivate(used, buttonDown); MeltdownPlugin.logger.LogInfo((object)"ACTIVATED GEIGER COUNTER"); SwitchPoweredState(used); generalAudioSource.clip = toggle; generalAudioSource.Play(); } public override void UseUpBatteries() { ((GrabbableObject)this).UseUpBatteries(); SwitchPoweredState(on: false); generalAudioSource.clip = outOfBattery; generalAudioSource.Play(); } public void SwitchPoweredState(bool on) { MeltdownPlugin.logger.LogInfo((object)$"me when the on value is {on}. :rofl::rofl::rofl:"); if (base.isBeingUsed) { lowRadiation.Play(); mediumRadiation.Play(); highRadiation.Play(); } else { lowRadiation.Stop(); mediumRadiation.Stop(); highRadiation.Stop(); } } public override void Update() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) ((GrabbableObject)this).Update(); if (base.isBeingUsed) { float num = RadiationSource.CollectRadiationFromPoint(((Component)this).transform.position); lowRadiation.volume = 0f; mediumRadiation.volume = 0f; highRadiation.volume = 0f; if (num > maxDetection) { highRadiation.volume = 1f; } else if (num > maxDetection / 2f) { mediumRadiation.volume = 1f; } else { lowRadiation.volume = 1f; } float num2 = Mathf.Clamp01(num / maxDetection) * (maxRotation * 2f); num2 -= maxRotation; needle.transform.localEulerAngles = new Vector3(-90f, num2, 0f); } } protected override void __initializeVariables() { ((GrabbableObject)this).__initializeVariables(); } protected override void __initializeRpcs() { ((GrabbableObject)this).__initializeRpcs(); } [MethodImpl(MethodImplOptions.NoInlining)] protected internal override string __getTypeName() { return "GeigerCounterItem"; } } } namespace FacilityMeltdown.Config { [RequiresRestart(false)] internal class MeltdownClientConfig : LoafConfig<MeltdownClientConfig> { [ConfigGroup("Audio")] [ConfigDesc("What volume the music plays at. Also controls the volume of the random voicelines that play")] [ConfigRange(0f, 100f)] public int MusicVolume { get; private set; } = 100; [ConfigDesc("Does the music play outside the facility?")] public bool MusicPlaysOutside { get; private set; } = true; [ConfigGroup("Visuals")] [ConfigDesc("Whether or not to shake the screen during the meltdown sequence. Doesn't control other places of screen shake in the game.")] public bool ScreenShake { get; private set; } = true; [ConfigDesc("Should meltdown sequence contain particle effects? Doesn't include particle effects on the fireball.")] public bool ParticleEffects { get; private set; } = true; [ConfigIgnore] [RequiresRestart(true)] public string Language { get; private set; } = "en"; internal MeltdownClientConfig(ConfigFile file) : base(file) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown BindProperty<string>(typeof(MeltdownClientConfig).GetProperty("Language"), "Language", new ConfigDescription("What language should FacilityMeltdown use? NOTE: This only affects facility meltdown and won't change the rest of the games langauge\nSome Languages may also need FontPatcher(https://thunderstore.io/c/lethal-company/p/LeKAKiD/FontPatcher/)\nLanguages Available: " + string.Join(", ", LangParser.languages.Keys), (AcceptableValueBase)null, Array.Empty<object>())); } } internal class MeltdownConfig : LoafSyncedConfig<MeltdownConfig> { [ConfigGroup("GameBalance")] [ConfigDesc("Whether or not FacilityMeltdown should override appartus value. Only disable for compatibility reasons.")] public bool OverrideApparatusValue { get; private set; } = true; [ConfigDesc("When overriding the apparatus value what should it's base value be?")] [ConfigRange(80f, 500f)] public int ApparatusValue { get; private set; } = 240; [ConfigDesc("How many monsters should spawn during the meltdown sequence? Set to 0 to disable.")] [ConfigRange(0f, 10f)] public int MonsterSpawnAmount { get; private set; } = 5; [ConfigDesc("Should the lights turn on periodically? Disabling this option makes them permanently off. (Matches Vanilla Behaviour)")] public bool EmergencyLights { get; private set; } = true; [ConfigDesc("How many people need to be nearby to the apparatus for it to be collectable? Will go UP TO the value, e.g. if it's set to 3 and there are only 2 people in the lobby, everyone will need to be there.\nThis value is ignored and anybody can grab it from 9PM")] [ConfigRange(1f, 10f)] public int MinPeopleToPullApparatus { get; private set; } = 2; [ConfigDesc("What enemies to exclude from spawning in the meltdown sequence. Comma seperated list. Supports modded entities.")] public string DisallowedEnemies { get; private set; } = "Centipede,Hoarding bug"; [ConfigDesc("How long until the ship's scanner can scan the reactor. (Doesn't affect the vanilla `scan` command)")] [ConfigRange(0f, 20f)] public float ShipScanCooldown { get; private set; } = 15f; [ConfigDesc("How accurate is the ship's scanner when scanning the reactor. Higher values mean it is more uncertain, and lower values is more accurate. (Doesn't affect the vanilla `scan` command)")] [ConfigRange(0f, 100f)] public float ShipScanAccuracy { get; private set; } = 15f; [ConfigGroup("Integrations")] [ConfigDesc("Should the apparatus value be multiplied by the current weather. Requires WeatherRegistry to work.")] public bool WeatherRegistryIntegration { get; private set; } = true; [ConfigGroup("UNSUPPORTED")] [ConfigDesc("ABSOLUETLY NOT SUPPORTED OR RECOMMENDED! Change the length of the meltdown sequence. If this breaks I am not fixing it, you have been warned.")] [ConfigRange(60f, 300f)] public int MeltdownTime { get; private set; } = 120; public MeltdownConfig(ConfigFile file) : base(file) { } public List<string> GetDisallowedEnemies() { return DisallowedEnemies.Split(',').ToList(); } } } namespace FacilityMeltdown.Behaviours { public class MeltdownEvents : MonoBehaviour { [Serializable] public class Marker { internal bool Triggered; [field: SerializeField] public float Progress { get; private set; } = 0.5f; [field: SerializeField] public UnityEvent OnMarker { get; private set; } } [SerializeField] private UnityEvent OnMeltdownStart; [SerializeField] private List<Marker> markers = new List<Marker>(); private void OnEnable() { MeltdownAPI.OnMeltdownStart = (Action)Delegate.Combine(MeltdownAPI.OnMeltdownStart, new Action(OnMeltdownStart.Invoke)); } private void On