Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Elias Hadi Modpack v1.0.0
BepInEx/plugins/BGN-PizzaTowerEscapeMusic/PizzaTowerEscapeMusic.dll
Decompiled 8 months 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 8 months 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