using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using REPOLib; using REPOLib.Modules; using UnityEngine; using UnityEngine.AI; using UnityEngine.SceneManagement; [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("Empress")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("HospitalCompatPatch")] [assembly: AssemblyTitle("HospitalCompatPatch")] [assembly: AssemblyVersion("1.0.2.0")] [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 HospitalCompatPatch { [BepInPlugin("empress.repo.hospitalcompatpatch", "Empress Hospital Compat Patch", "1.0.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class HospitalCompatPatchPlugin : BaseUnityPlugin { private sealed class HospitalPrefabBuckets { private readonly HashSet _startRoomNames = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _normalNames = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _passageNames = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _deadEndNames = new HashSet(StringComparer.OrdinalIgnoreCase); private readonly HashSet _extractionNames = new HashSet(StringComparer.OrdinalIgnoreCase); public List StartRooms { get; } = new List(); public List Normal1 { get; } = new List(); public List Passage1 { get; } = new List(); public List DeadEnd1 { get; } = new List(); public List Extraction1 { get; } = new List(); public List Normal2 { get; } = new List(); public List Passage2 { get; } = new List(); public List DeadEnd2 { get; } = new List(); public List Extraction2 { get; } = new List(); public List Normal3 { get; } = new List(); public List Passage3 { get; } = new List(); public List DeadEnd3 { get; } = new List(); public List Extraction3 { get; } = new List(); public int TotalModuleCount => Normal1.Count + Passage1.Count + DeadEnd1.Count + Extraction1.Count + Normal2.Count + Passage2.Count + DeadEnd2.Count + Extraction2.Count + Normal3.Count + Passage3.Count + DeadEnd3.Count + Extraction3.Count; public void AddStartRoom(GameObject prefab) { AddUnique(StartRooms, _startRoomNames, prefab); } public void AddNormal(int tier, GameObject prefab) { AddByTier(tier, prefab, _normalNames, Normal1, Normal2, Normal3); } public void AddPassage(int tier, GameObject prefab) { AddByTier(tier, prefab, _passageNames, Passage1, Passage2, Passage3); } public void AddDeadEnd(int tier, GameObject prefab) { AddByTier(tier, prefab, _deadEndNames, DeadEnd1, DeadEnd2, DeadEnd3); } public void AddExtraction(int tier, GameObject prefab) { AddByTier(tier, prefab, _extractionNames, Extraction1, Extraction2, Extraction3); } private static void AddByTier(int tier, GameObject prefab, HashSet names, List tierOne, List tierTwo, List tierThree) { switch (tier) { case 1: AddUnique(tierOne, names, prefab); break; case 2: AddUnique(tierTwo, names, prefab); break; case 3: AddUnique(tierThree, names, prefab); break; } } private static void AddUnique(List list, HashSet names, GameObject prefab) { if (!((Object)(object)prefab == (Object)null) && !string.IsNullOrWhiteSpace(((Object)prefab).name) && names.Add(((Object)prefab).name)) { list.Add(prefab); } } } internal const string PluginGuid = "empress.repo.hospitalcompatpatch"; internal const string PluginName = "Empress Hospital Compat Patch"; internal const string PluginVersion = "1.0.2"; private const string HospitalBundleFileName = "Hospital_Level.repobundle"; private const string HospitalLevelName = "Level - Hospital"; private const string HospitalLevelResourcePath = "HospitalMod"; private const float HospitalLevelPointCheckRadius = 0.5f; private const float HospitalLevelPointRepairRadius = 2f; private const int HospitalVehicleVolumeCount = 4; private const float HospitalVehicleVolumeSideOffset = 2f; private const float HospitalVehicleVolumeForwardOffset = 2.5f; private const float HospitalVehicleVolumeForwardSpacing = 2f; private const float HospitalChargingStationForwardOffset = 6.5f; private static readonly Regex HospitalModuleNamePattern = new Regex("^Module\\s*-\\s*Hospital\\s*-\\s*(?N|P|DE|E)\\s*-\\s*(?[123])\\b", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant); private readonly Harmony _hospitalHarmony = new Harmony("empress.repo.hospitalcompatpatch"); private AssetBundle? _hospitalBundle; private bool _hospitalRepairApplied; private bool _hospitalRepairQueued; private bool _hospitalLoggedMissingBundle; private bool _hospitalLoggedMissingPrefabs; private bool _hospitalLoggedDoorMapFallback; internal static HospitalCompatPatchPlugin? Instance { get; private set; } private void Awake() { //IL_000d: 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) Instance = this; GameObject gameObject = ((Component)this).gameObject; ((Object)gameObject).hideFlags = (HideFlags)(((Object)gameObject).hideFlags | 0x23); BundleLoader.OnAllBundlesLoaded += HospitalHandleBundlesLoaded; _hospitalHarmony.PatchAll(); if ((Object)(object)RunManager.instance != (Object)null) { ((MonoBehaviour)this).StartCoroutine(HospitalRepairWhenReady()); } } private void HospitalHandleBundlesLoaded() { if (!_hospitalRepairQueued && !_hospitalRepairApplied) { _hospitalRepairQueued = true; ((MonoBehaviour)this).StartCoroutine(HospitalRepairWhenReady()); } } private IEnumerator HospitalRepairWhenReady() { yield return null; for (int attempt = 0; attempt < 120; attempt++) { if (_hospitalRepairApplied) { break; } if (HospitalTryRepairLevel()) { break; } yield return null; } _hospitalRepairQueued = false; } internal bool HospitalTryRepairCurrentLevel() { List list = new List(); if ((Object)(object)LevelGenerator.Instance != (Object)null && (Object)(object)LevelGenerator.Instance.Level != (Object)null) { list.Add(LevelGenerator.Instance.Level); } if ((Object)(object)RunManager.instance != (Object)null && (Object)(object)RunManager.instance.levelCurrent != (Object)null) { list.Add(RunManager.instance.levelCurrent); } return HospitalTryRepairLevel(list); } private bool HospitalTryRepairLevel(IEnumerable? candidates = null) { if (_hospitalRepairApplied) { return true; } Level val = HospitalFindLevel(candidates) ?? HospitalFindLevel(Levels.AllLevels); if ((Object)(object)val == (Object)null) { return false; } AssetBundle val2 = HospitalGetBundle(); if ((Object)(object)val2 == (Object)null) { if (!_hospitalLoggedMissingBundle) { _hospitalLoggedMissingBundle = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"Empress Hospital Compat Patch could not locate the Hospital bundle."); } return false; } _hospitalLoggedMissingBundle = false; HospitalPrefabBuckets hospitalPrefabBuckets = HospitalCollectPrefabs(val2); if (hospitalPrefabBuckets.StartRooms.Count == 0 || hospitalPrefabBuckets.TotalModuleCount == 0) { if (!_hospitalLoggedMissingPrefabs) { _hospitalLoggedMissingPrefabs = true; ((BaseUnityPlugin)this).Logger.LogError((object)"Empress Hospital Compat Patch could not rebuild the Hospital prefab lists from the original bundle."); } return false; } _hospitalLoggedMissingPrefabs = false; HospitalApplyHideFlags((Object)(object)val2); HospitalApplyHideFlags((Object)(object)val); HospitalEnsureLevelFallbackData(val); HospitalRegisterLevelObjects(val); val.StartRooms = HospitalRegisterPrefabs(val, "StartRoom", hospitalPrefabBuckets.StartRooms); val.ModulesNormal1 = HospitalRegisterPrefabs(val, "Normal", hospitalPrefabBuckets.Normal1); val.ModulesPassage1 = HospitalRegisterPrefabs(val, "Passage", hospitalPrefabBuckets.Passage1); val.ModulesDeadEnd1 = HospitalRegisterPrefabs(val, "DeadEnd", hospitalPrefabBuckets.DeadEnd1); val.ModulesExtraction1 = HospitalRegisterPrefabs(val, "Extraction", hospitalPrefabBuckets.Extraction1); val.ModulesNormal2 = HospitalRegisterPrefabs(val, "Normal", hospitalPrefabBuckets.Normal2); val.ModulesPassage2 = HospitalRegisterPrefabs(val, "Passage", hospitalPrefabBuckets.Passage2); val.ModulesDeadEnd2 = HospitalRegisterPrefabs(val, "DeadEnd", hospitalPrefabBuckets.DeadEnd2); val.ModulesExtraction2 = HospitalRegisterPrefabs(val, "Extraction", hospitalPrefabBuckets.Extraction2); val.ModulesNormal3 = HospitalRegisterPrefabs(val, "Normal", hospitalPrefabBuckets.Normal3); val.ModulesPassage3 = HospitalRegisterPrefabs(val, "Passage", hospitalPrefabBuckets.Passage3); val.ModulesDeadEnd3 = HospitalRegisterPrefabs(val, "DeadEnd", hospitalPrefabBuckets.DeadEnd3); val.ModulesExtraction3 = HospitalRegisterPrefabs(val, "Extraction", hospitalPrefabBuckets.Extraction3); _hospitalRepairApplied = val.StartRooms.Count > 0 && HospitalCountModules(val) > 0; if (_hospitalRepairApplied) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Empress Hospital Compat Patch repaired {((Object)val).name} with {val.StartRooms.Count} start rooms and {HospitalCountModules(val)} modules."); } return _hospitalRepairApplied; } private static Level? HospitalFindLevel(IEnumerable? candidates) { if (candidates == null) { return null; } foreach (Level candidate in candidates) { if (HospitalIsHospitalLevel(candidate)) { return candidate; } } return null; } private AssetBundle? HospitalGetBundle() { if ((Object)(object)_hospitalBundle != (Object)null) { return _hospitalBundle; } foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { try { if (allLoadedAssetBundle.GetAllAssetNames().Any((string assetName) => assetName.EndsWith("level - hospital.asset", StringComparison.OrdinalIgnoreCase) || assetName.EndsWith("hospitallevelcontent.asset", StringComparison.OrdinalIgnoreCase))) { _hospitalBundle = allLoadedAssetBundle; return _hospitalBundle; } } catch { } } string text = Directory.GetFiles(Paths.PluginPath, "Hospital_Level.repobundle", SearchOption.AllDirectories).FirstOrDefault(); if (string.IsNullOrWhiteSpace(text)) { return null; } _hospitalBundle = AssetBundle.LoadFromFile(text); return _hospitalBundle; } private static HospitalPrefabBuckets HospitalCollectPrefabs(AssetBundle bundle) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) HospitalPrefabBuckets hospitalPrefabBuckets = new HospitalPrefabBuckets(); StartRoom[] array = bundle.LoadAllAssets(); foreach (StartRoom val in array) { HospitalTryBucketPrefab(hospitalPrefabBuckets, ((Object)(object)val != (Object)null) ? ((Component)val).gameObject : null); } Module[] array2 = bundle.LoadAllAssets(); foreach (Module val2 in array2) { HospitalTryBucketPrefab(hospitalPrefabBuckets, ((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null); } GameObject[] array3 = bundle.LoadAllAssets(); foreach (GameObject prefab in array3) { HospitalTryBucketPrefab(hospitalPrefabBuckets, prefab); } if (hospitalPrefabBuckets.StartRooms.Count == 0 || hospitalPrefabBuckets.TotalModuleCount == 0) { array = Resources.FindObjectsOfTypeAll(); Scene scene; foreach (StartRoom val3 in array) { if (!((Object)(object)val3 == (Object)null)) { scene = ((Component)val3).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { HospitalTryBucketPrefab(hospitalPrefabBuckets, ((Component)val3).gameObject); } } } array2 = Resources.FindObjectsOfTypeAll(); foreach (Module val4 in array2) { if (!((Object)(object)val4 == (Object)null)) { scene = ((Component)val4).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { HospitalTryBucketPrefab(hospitalPrefabBuckets, ((Component)val4).gameObject); } } } } return hospitalPrefabBuckets; } private static void HospitalTryBucketPrefab(HospitalPrefabBuckets buckets, GameObject? prefab) { if ((Object)(object)prefab == (Object)null) { return; } string text = ((Object)prefab).name ?? string.Empty; if (text.StartsWith("Start Room - Hospital -", StringComparison.OrdinalIgnoreCase)) { buckets.AddStartRoom(prefab); return; } Match match = HospitalModuleNamePattern.Match(text); if (match.Success && int.TryParse(match.Groups["tier"].Value, out var result)) { switch (match.Groups["type"].Value.ToUpperInvariant()) { case "N": buckets.AddNormal(result, prefab); break; case "P": buckets.AddPassage(result, prefab); break; case "DE": buckets.AddDeadEnd(result, prefab); break; case "E": buckets.AddExtraction(result, prefab); break; } } } private static void HospitalRegisterLevelObjects(Level level) { if (level.ConnectObject != null) { GameObject val = HospitalResolvePrefab(level.ConnectObject); if ((Object)(object)val != (Object)null) { HospitalApplyHideFlags((Object)(object)val); Utilities.FixAudioMixerGroups(val); NetworkPrefabs.RegisterNetworkPrefab("Level/" + HospitalGetLevelPath(level) + "/Other/" + HospitalGetPrefabName(level.ConnectObject, val), val); } } if (level.BlockObject != null) { GameObject val2 = HospitalResolvePrefab(level.BlockObject); if ((Object)(object)val2 != (Object)null) { HospitalApplyHideFlags((Object)(object)val2); Utilities.FixAudioMixerGroups(val2); NetworkPrefabs.RegisterNetworkPrefab("Level/" + HospitalGetLevelPath(level) + "/Other/" + HospitalGetPrefabName(level.BlockObject, val2), val2); } } } private static string HospitalGetLevelPath(Level level) { if (!string.IsNullOrWhiteSpace(((Object)level).name)) { return ((Object)level).name; } return "HospitalMod"; } private static string HospitalGetPrefabName(PrefabRef prefabRef, GameObject prefab) { if (!string.IsNullOrWhiteSpace(prefabRef.PrefabName)) { return prefabRef.PrefabName; } return ((Object)prefab).name; } private static GameObject? HospitalResolvePrefab(PrefabRef? prefabRef) { if (prefabRef == null) { return null; } if (prefabRef.IsValid()) { return prefabRef.Prefab; } AssetBundle bundle = prefabRef.Bundle; if ((Object)(object)bundle == (Object)null || string.IsNullOrWhiteSpace(prefabRef.PrefabName)) { return null; } GameObject[] array = bundle.LoadAllAssets(); foreach (GameObject val in array) { if ((Object)(object)val != (Object)null && string.Equals(((Object)val).name, prefabRef.PrefabName, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static List HospitalRegisterPrefabs(Level level, string moduleTypeName, IEnumerable prefabs) { List list = new List(); foreach (GameObject item in prefabs.OrderBy((GameObject gameObject) => ((Object)gameObject).name, StringComparer.OrdinalIgnoreCase)) { HospitalEnsureVehicleSupport(item); HospitalApplyHideFlags((Object)(object)item); Utilities.FixAudioMixerGroups(item); PrefabRef val = NetworkPrefabs.RegisterNetworkPrefab("Level/" + ((Object)level).name + "/" + moduleTypeName + "/" + ((Object)item).name, item); if (val != null) { list.Add(val); } } return list; } private static void HospitalEnsureVehicleSupport(GameObject prefab) { if (!((Object)(object)prefab == (Object)null) && HospitalIsStartRoomPrefab(prefab)) { HospitalEnsureVehicleItemVolumes(prefab); HospitalEnsureVehicleChargingStation(prefab); } } private static bool HospitalIsStartRoomPrefab(GameObject prefab) { if (!((Object)(object)prefab.GetComponentInChildren(true) != (Object)null)) { return ((Object)prefab).name.StartsWith("Start Room - Hospital -", StringComparison.OrdinalIgnoreCase); } return true; } private static void HospitalEnsureVehicleItemVolumes(GameObject prefab) { int num = prefab.GetComponentsInChildren(true).Count(HospitalIsVehicleItemVolume); if (num < 4) { Transform parent = HospitalFindOrCreateVehicleSupportRoot(prefab); Transform anchor = HospitalFindTruckAnchor(prefab); for (int i = num; i < 4; i++) { HospitalCreateVehicleItemVolume(parent, anchor, i); } } } private static bool HospitalIsVehicleItemVolume(ItemVolume itemVolume) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 return (int)HospitalGetComponentField((Component)(object)itemVolume, "itemVolume", (itemVolume)0) == 9; } private static void HospitalCreateVehicleItemVolume(Transform parent, Transform anchor, int index) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject((index == 0) ? "Item Volume vehicle" : $"Item Volume vehicle ({index})"); val.SetActive(false); val.transform.SetParent(parent, false); val.transform.SetPositionAndRotation(HospitalGetVehicleVolumePosition(anchor, index), anchor.rotation); ItemVolume target = val.AddComponent(); HospitalSetComponentField((Component)(object)target, "itemVolume", (itemVolume)9); GameObject val2 = new GameObject("Vehicle"); val2.transform.SetParent(val.transform, false); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; val2.transform.localScale = new Vector3(2.6f, 1.4f, 4f); HospitalSetComponentField((Component)(object)target, "volumes", new List { val2 }); HospitalApplyHideFlags((Object)(object)val); } private static Vector3 HospitalGetVehicleVolumePosition(Transform anchor, int index) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0035: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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) float num = ((index % 2 == 0) ? (-2f) : 2f); float num2 = 2.5f + (float)(index / 2) * 2f; return anchor.position + anchor.right * num + anchor.forward * num2 + Vector3.up * 0.25f; } private static Transform HospitalFindTruckAnchor(GameObject prefab) { LevelPoint[] componentsInChildren = prefab.GetComponentsInChildren(true); foreach (LevelPoint val in componentsInChildren) { if ((Object)(object)val != (Object)null && HospitalGetComponentField((Component)(object)val, "Truck", fallback: false)) { return ((Component)val).transform; } } RoomVolume[] componentsInChildren2 = prefab.GetComponentsInChildren(true); foreach (RoomVolume val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null && HospitalGetComponentField((Component)(object)val2, "Truck", fallback: false)) { return ((Component)val2).transform; } } return prefab.transform; } private static Transform HospitalFindOrCreateVehicleSupportRoot(GameObject prefab) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown Transform val = ((IEnumerable)prefab.GetComponentsInChildren(true)).FirstOrDefault((Func)((Transform child) => (Object)(object)child != (Object)null && string.Equals(((Object)child).name, "Empress Vehicle Support", StringComparison.OrdinalIgnoreCase))); if ((Object)(object)val != (Object)null) { return val; } GameObject val2 = new GameObject("Empress Vehicle Support"); val2.transform.SetParent(prefab.transform, false); HospitalApplyHideFlags((Object)val2); return val2.transform; } private static void HospitalEnsureVehicleChargingStation(GameObject prefab) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) if (prefab.GetComponentsInChildren(true).Any(HospitalIsVehicleChargingStation)) { return; } ChargingStation val = HospitalFindFallbackChargingStationTemplate(); if (!((Object)(object)val == (Object)null) && HospitalIsVehicleChargingStation(val)) { ChargingStation val2 = HospitalFindLegacyChargingStation(prefab); Transform val3 = HospitalFindOrCreateVehicleSupportRoot(prefab); Transform val4 = HospitalFindTruckAnchor(prefab); GameObject val5 = HospitalCloneInactiveChargingStationTemplate(val); ((Object)val5).name = "Charging Station New"; val5.transform.SetParent(val3, false); if ((Object)(object)val2 != (Object)null) { val5.transform.SetPositionAndRotation(((Component)val2).transform.position, ((Component)val2).transform.rotation); ((Component)val2).gameObject.SetActive(false); } else { val5.transform.SetPositionAndRotation(val4.position + val4.forward * 6.5f + Vector3.up * 0.05f, Quaternion.LookRotation(-val4.forward, Vector3.up)); } Transform val6 = HospitalFindChildByExactName(val5.transform, "Charge Area"); if ((Object)(object)val6 != (Object)null) { val6.localScale = new Vector3(Mathf.Max(val6.localScale.x, 4f), Mathf.Max(val6.localScale.y, 2f), Mathf.Max(val6.localScale.z, 4f)); } HospitalApplyHideFlags((Object)(object)val5); Utilities.FixAudioMixerGroups(val5); } } private static GameObject HospitalCloneInactiveChargingStationTemplate(ChargingStation template) { GameObject gameObject = ((Component)template).gameObject; bool activeSelf = gameObject.activeSelf; try { if (activeSelf) { gameObject.SetActive(false); } GameObject obj = Object.Instantiate(gameObject); obj.SetActive(false); return obj; } finally { if ((Object)(object)gameObject != (Object)null && activeSelf) { gameObject.SetActive(true); } } } internal static void HospitalActivateVehicleChargingStation(StartRoom? startRoom) { if ((Object)(object)startRoom == (Object)null || !HospitalIsCurrentLevel() || !HospitalIsStartRoomPrefab(((Component)startRoom).gameObject)) { return; } ChargingStation[] componentsInChildren = ((Component)startRoom).GetComponentsInChildren(true); foreach (ChargingStation val in componentsInChildren) { if ((Object)(object)val != (Object)null && HospitalIsVehicleChargingStation(val) && string.Equals(((Object)((Component)val).gameObject).name, "Charging Station New", StringComparison.OrdinalIgnoreCase) && !((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(true); } } ItemVolume[] componentsInChildren2 = ((Component)startRoom).GetComponentsInChildren(true); foreach (ItemVolume val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null && HospitalIsVehicleItemVolume(val2) && !((Component)val2).gameObject.activeSelf) { ((Component)val2).gameObject.SetActive(true); } } } private static ChargingStation? HospitalFindFallbackChargingStationTemplate() { ChargingStation val = HospitalFindChargingStationTemplateFromLevels(); if ((Object)(object)val != (Object)null && HospitalIsVehicleChargingStation(val)) { return val; } return Resources.FindObjectsOfTypeAll().Where(delegate(ChargingStation candidate) { //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) if ((Object)(object)candidate != (Object)null) { Scene scene = ((Component)candidate).gameObject.scene; return !((Scene)(ref scene)).IsValid(); } return false; }).OrderByDescending(HospitalIsVehicleChargingStation) .FirstOrDefault() ?? val; } private static ChargingStation? HospitalFindChargingStationTemplateFromLevels() { ChargingStation val = null; if (RunManager.instance?.levels == null) { return val; } foreach (Level level in RunManager.instance.levels) { if ((Object)(object)level == (Object)null || HospitalIsHospitalLevel(level) || level.StartRooms == null) { continue; } foreach (PrefabRef startRoom in level.StartRooms) { GameObject val2 = null; try { val2 = HospitalResolvePrefab(startRoom); } catch { } if ((Object)(object)val2 == (Object)null) { continue; } ChargingStation[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (ChargingStation val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null)) { if (HospitalIsVehicleChargingStation(val3)) { return val3; } if (val == null) { val = val3; } } } } } return val; } private static ChargingStation? HospitalFindLegacyChargingStation(GameObject prefab) { return ((IEnumerable)prefab.GetComponentsInChildren(true)).FirstOrDefault((Func)((ChargingStation candidate) => (Object)(object)candidate != (Object)null && !HospitalIsVehicleChargingStation(candidate))); } private static bool HospitalIsVehicleChargingStation(ChargingStation? chargingStation) { if ((Object)(object)chargingStation == (Object)null) { return false; } Transform transform = ((Component)chargingStation).transform; if ((Object)(object)HospitalFindChildByExactName(transform, "Charge Area") != (Object)null) { return (Object)(object)HospitalFindChildByExactName(transform, "Line Between Two Points") != (Object)null; } return false; } private static Transform? HospitalFindChildByExactName(Transform root, string name) { string name2 = name; return ((IEnumerable)((Component)root).GetComponentsInChildren(true)).FirstOrDefault((Func)((Transform child) => (Object)(object)child != (Object)null && string.Equals(((Object)child).name, name2, StringComparison.OrdinalIgnoreCase))); } private static T HospitalGetComponentField(Component target, string fieldName, T fallback) { if ((Object)(object)target == (Object)null) { return fallback; } try { if (AccessTools.Field(((object)target).GetType(), fieldName) == null) { return fallback; } return (T)((Traverse.Create((object)target).Field(fieldName).GetValue() is T val) ? ((object)val) : ((object)fallback)); } catch { return fallback; } } private static void HospitalSetComponentField(Component target, string fieldName, T value) { if ((Object)(object)target == (Object)null) { return; } try { if (!(AccessTools.Field(((object)target).GetType(), fieldName) == null)) { Traverse.Create((object)target).Field(fieldName).SetValue((object)value); } } catch { } } private static int HospitalCountModules(Level level) { return (level.ModulesNormal1?.Count ?? 0) + (level.ModulesPassage1?.Count ?? 0) + (level.ModulesDeadEnd1?.Count ?? 0) + (level.ModulesExtraction1?.Count ?? 0) + (level.ModulesNormal2?.Count ?? 0) + (level.ModulesPassage2?.Count ?? 0) + (level.ModulesDeadEnd2?.Count ?? 0) + (level.ModulesExtraction2?.Count ?? 0) + (level.ModulesNormal3?.Count ?? 0) + (level.ModulesPassage3?.Count ?? 0) + (level.ModulesDeadEnd3?.Count ?? 0) + (level.ModulesExtraction3?.Count ?? 0); } internal static bool HospitalIsCurrentLevel() { if (!HospitalIsHospitalLevel(((Object)(object)LevelGenerator.Instance != (Object)null) ? LevelGenerator.Instance.Level : null)) { return HospitalIsHospitalLevel(((Object)(object)RunManager.instance != (Object)null) ? RunManager.instance.levelCurrent : null); } return true; } private static bool HospitalIsHospitalLevel(Level? level) { if ((Object)(object)level == (Object)null) { return false; } if (!string.Equals(((Object)level).name, "Level - Hospital", StringComparison.OrdinalIgnoreCase) && !string.Equals(((Object)level).name, "HospitalMod", StringComparison.OrdinalIgnoreCase) && (string.IsNullOrWhiteSpace(((Object)level).name) || ((Object)level).name.IndexOf("hospital", StringComparison.OrdinalIgnoreCase) < 0)) { if (!string.IsNullOrWhiteSpace(level.NarrativeName)) { return level.NarrativeName.IndexOf("hospital", StringComparison.OrdinalIgnoreCase) >= 0; } return false; } return true; } internal static void HospitalEnsureLevelFallbackData(Level? level) { if (HospitalIsHospitalLevel(level)) { Level val = level; if (val.ValuablePresets == null) { val.ValuablePresets = new List(); } val = level; if (val.AmbiencePresets == null) { val.AmbiencePresets = new List(); } if (level.ValuablePresets.Count == 0 && (Object)(object)ValuablePresets.GenericValuablePreset != (Object)null) { level.ValuablePresets.Add(ValuablePresets.GenericValuablePreset); } if (level.AmbiencePresets.Count == 0 && HospitalTryGetFallbackAmbience(out LevelAmbience ambience)) { level.AmbiencePresets.Add(ambience); } } } private static bool HospitalTryGetFallbackAmbience(out LevelAmbience ambience) { ambience = null; if ((Object)(object)AudioManager.instance != (Object)null && AudioManager.instance.levelAmbiences != null) { foreach (LevelAmbience levelAmbience in AudioManager.instance.levelAmbiences) { if (!((Object)(object)levelAmbience == (Object)null)) { ambience = levelAmbience; return true; } } } if ((Object)(object)RunManager.instance != (Object)null && RunManager.instance.levels != null) { foreach (Level level in RunManager.instance.levels) { if (level?.AmbiencePresets == null) { continue; } foreach (LevelAmbience ambiencePreset in level.AmbiencePresets) { if (!((Object)(object)ambiencePreset == (Object)null)) { ambience = ambiencePreset; return true; } } } } return false; } internal static void HospitalEnsureExtractionPointCompatibility(ExtractionPoint extractionPoint) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown if ((Object)(object)extractionPoint == (Object)null || !HospitalIsCurrentLevel()) { return; } if ((Object)(object)extractionPoint.extractionArea == (Object)null) { GameObject val = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)val).name = "Hospital Patch Extraction Area"; val.transform.SetParent(((Component)extractionPoint).transform, false); val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; val.transform.localScale = Vector3.one * 0.1f; MeshRenderer component = val.GetComponent(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = false; } Collider component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } val.SetActive(false); HospitalApplyHideFlags((Object)(object)val); extractionPoint.extractionArea = val; } if ((Object)(object)extractionPoint.grossUp == (Object)null) { GameObject val2 = new GameObject("Hospital Patch GrossUp"); val2.transform.SetParent(((Component)extractionPoint).transform, false); val2.SetActive(false); HospitalApplyHideFlags((Object)(object)val2); extractionPoint.grossUp = val2; } } internal void HospitalRepairLevelPoints(LevelGenerator levelGenerator) { if ((Object)(object)levelGenerator == (Object)null || !HospitalIsHospitalLevel(levelGenerator.Level) || levelGenerator.LevelPathPoints == null) { return; } int num = 0; foreach (LevelPoint levelPathPoint in levelGenerator.LevelPathPoints) { if (HospitalRepairLevelPoint(levelPathPoint)) { num++; } } if (num > 0) { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Empress Hospital Compat Patch repaired {num} Hospital level points onto the navmesh."); } } private static bool HospitalRepairLevelPoint(LevelPoint? levelPoint) { //IL_0011: 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_0017: 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) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)levelPoint == (Object)null) { return false; } Vector3 position = ((Component)levelPoint).transform.position; NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val, 0.5f, -1)) { return false; } NavMeshHit val2 = default(NavMeshHit); if (!NavMesh.SamplePosition(position, ref val2, 2f, -1)) { return false; } ((Component)levelPoint).transform.position = ((NavMeshHit)(ref val2)).position; RoomVolume room = default(RoomVolume); Vector3 val3 = default(Vector3); if ((Object)(object)levelPoint.Room == (Object)null && SemiFunc.GetRoomVolumeAtPosition(((NavMeshHit)(ref val2)).position, ref room, ref val3)) { levelPoint.Room = room; } return true; } internal GameObject HospitalCreateFallbackDoorMapObject(Map map, DirtFinderMapDoor door) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) MapLayer layerParent = map.GetLayerParent(((Component)door).transform.position.y); GameObject val = HospitalInstantiateFallbackDoorMapObject(map, ((Component)layerParent).transform); ((Object)val).name = ((Object)((Component)door).gameObject).name; door.Target = val.transform; DirtFinderMapDoorTarget val2 = val.GetComponent() ?? val.AddComponent(); val2.Target = ((Component)door).transform; val2.Layer = layerParent; DirtFinderMapDoorTarget val3 = val2; if (val3.HingeTransform == null) { val3.HingeTransform = val.transform; } map.DoorUpdate(val2.HingeTransform, ((Component)door).transform, layerParent); if (!_hospitalLoggedDoorMapFallback) { _hospitalLoggedDoorMapFallback = true; ((BaseUnityPlugin)this).Logger.LogWarning((object)"Empress Hospital Compat Patch injected fallback minimap door markers for missing Hospital door prefabs."); } return val; } private static GameObject HospitalInstantiateFallbackDoorMapObject(Map map, Transform parent) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) GameObject val; if ((Object)(object)map.Door1x1Object != (Object)null) { val = Object.Instantiate(map.Door1x1Object, parent); Collider[] componentsInChildren = val.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { Object.Destroy((Object)(object)componentsInChildren[i]); } } else { val = GameObject.CreatePrimitive((PrimitiveType)3); val.transform.SetParent(parent, false); val.transform.localScale = new Vector3(0.12f, 0.12f, 0.3f); Collider component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } val.transform.localPosition = Vector3.zero; val.transform.localRotation = Quaternion.identity; DirtFinderMapDoorTarget val2 = val.GetComponent() ?? val.AddComponent(); if (val2.HingeTransform == null) { val2.HingeTransform = val.transform; } HospitalApplyHideFlags((Object)(object)val); return val; } private static void HospitalApplyHideFlags(Object obj) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (obj == (Object)null) { return; } obj.hideFlags = (HideFlags)(obj.hideFlags | 0x23); GameObject val = (GameObject)(object)((obj is GameObject) ? obj : null); if (val == null) { return; } Transform[] componentsInChildren = val.GetComponentsInChildren(true); foreach (Transform obj2 in componentsInChildren) { ((Object)obj2).hideFlags = (HideFlags)(((Object)obj2).hideFlags | 0x23); GameObject gameObject = ((Component)obj2).gameObject; ((Object)gameObject).hideFlags = (HideFlags)(((Object)gameObject).hideFlags | 0x23); Component[] components = ((Component)obj2).GetComponents(); foreach (Component val2 in components) { if ((Object)(object)val2 != (Object)null) { ((Object)val2).hideFlags = (HideFlags)(((Object)val2).hideFlags | 0x23); } } } } } [HarmonyPatch(typeof(LevelGenerator), "StartRoomGeneration")] internal static class HospitalCompatPatchStartRoomGenerationPatch { [HarmonyPrefix] private static void HospitalPrefix() { HospitalCompatPatchPlugin.Instance?.HospitalTryRepairCurrentLevel(); } } [HarmonyPatch(typeof(ExtractionPoint), "Start")] internal static class HospitalCompatPatchExtractionPointStartPatch { [HarmonyPostfix] private static void HospitalPostfix(ExtractionPoint __instance) { HospitalCompatPatchPlugin.HospitalEnsureExtractionPointCompatibility(__instance); } } [HarmonyPatch(typeof(StartRoom), "Start")] internal static class HospitalCompatPatchStartRoomStartPatch { [HarmonyPostfix] private static void HospitalPostfix(StartRoom __instance) { HospitalCompatPatchPlugin.HospitalActivateVehicleChargingStation(__instance); } } [HarmonyPatch(typeof(Levels), "RegisterLevelWithGame")] internal static class HospitalCompatPatchRegisterLevelPatch { [HarmonyPrefix] private static void HospitalPrefix(Level level) { HospitalCompatPatchPlugin.HospitalEnsureLevelFallbackData(level); } } [HarmonyPatch(typeof(Map), "AddDoor")] internal static class HospitalCompatPatchMapAddDoorPatch { [HarmonyPrefix] private static bool HospitalPrefix(Map __instance, DirtFinderMapDoor door, GameObject doorPrefab, ref GameObject __result) { if (!HospitalCompatPatchPlugin.HospitalIsCurrentLevel() || (Object)(object)door == (Object)null || (Object)(object)doorPrefab != (Object)null) { return true; } HospitalCompatPatchPlugin instance = HospitalCompatPatchPlugin.Instance; if ((Object)(object)instance == (Object)null) { return true; } __result = instance.HospitalCreateFallbackDoorMapObject(__instance, door); return false; } } [HarmonyPatch(typeof(LevelGenerator), "NavMeshSetupRPC")] internal static class HospitalCompatPatchNavMeshSetupPatch { [HarmonyPostfix] private static void HospitalPostfix(LevelGenerator __instance) { HospitalCompatPatchPlugin.Instance?.HospitalRepairLevelPoints(__instance); } } }