Decompiled source of Oxygen v1.6.3

BepInEx/plugins/Oxygen.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CSync.Extensions;
using CSync.Lib;
using DunGen;
using GameNetcodeStuff;
using HarmonyLib;
using LCVR;
using LCVR.Player;
using LethalLib.Modules;
using Microsoft.CodeAnalysis;
using Oxygen.Configuration;
using Oxygen.Extras;
using Oxygen.GameObjects;
using Oxygen.General;
using Oxygen.Items;
using Oxygen.NetcodePatcher;
using Oxygen.Patches;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;
using Woecust.ImmersiveVisor;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: IgnoresAccessChecksTo("ImmersiveVisor")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Oxygen")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Don't forget to refill oxygen canisters!")]
[assembly: AssemblyFileVersion("1.5.6.0")]
[assembly: AssemblyInformationalVersion("1.5.6+311aba3c039150939ab12debe31c51f70a8da212")]
[assembly: AssemblyProduct("Oxygen")]
[assembly: AssemblyTitle("Oxygen")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.5.6.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<float>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<float>();
	}
}
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 Oxygen
{
	public class OxygenInit : MonoBehaviour
	{
		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > OxygenInit");

		private const float AccurateMinValue = 0.2978f;

		private const float AccurateMaxValue = 0.9101f;

		private const float AccurateValueRange = 0.6123f;

		private static Image sprintMeterImage;

		private static Image oxygenHUD;

		private static TextMeshProUGUI eladsUIText;

		public static bool IsOxygenHUDInitialized => (Object)(object)oxygenHUD != (Object)null;

		public static float StaminaFillAmount => sprintMeterImage.fillAmount;

		public static float Percent
		{
			get
			{
				if ((Object)(object)oxygenHUD == (Object)null)
				{
					return 0f;
				}
				return OxygenBase.Instance.IsEladsHUDFound ? oxygenHUD.fillAmount : InvAdjustFillAmount(oxygenHUD.fillAmount);
			}
			internal set
			{
				if ((Object)(object)oxygenHUD == (Object)null)
				{
					return;
				}
				float num = Mathf.Clamp01(OxygenBase.Instance.IsEladsHUDFound ? value : AdjustFillAmount(value));
				if (oxygenHUD.fillAmount != num)
				{
					oxygenHUD.fillAmount = num;
					if ((Object)(object)eladsUIText != (Object)null)
					{
						float num2 = (float)Math.Round(Percent, 2);
						int num3 = (int)(num2 * 100f);
						((TMP_Text)eladsUIText).text = $"{num3}<size=75%><voffset=1>%</voffset></size>";
					}
					if ((OxygenBase.Instance.IsShyHUDFound && OxygenBase.OxygenConfig.autoHideHUD.Value) || OxygenBase.OxygenConfig.autoHideHUD.Value)
					{
						float num4 = ((OxygenBase.OxygenConfig.autoHideHUD_value.Value > 1f) ? 1f : OxygenBase.OxygenConfig.autoHideHUD_value.Value);
						bool flag = value >= num4;
						((Graphic)oxygenHUD).CrossFadeAlpha(flag ? 0f : 1f, flag ? 3f : 0.5f, false);
					}
				}
			}
		}

		private static float AdjustFillAmount(float value)
		{
			return OxygenBase.OxygenConfig.accurateMeter.Value ? (value * 0.6123f + 0.2978f) : value;
		}

		private static float InvAdjustFillAmount(float value)
		{
			return OxygenBase.OxygenConfig.accurateMeter.Value ? ((value - 0.2978f) / 0.6123f) : value;
		}

		internal static void Init()
		{
			GameObject val = (OxygenBase.Instance.IsEladsHUDFound ? GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/PlayerInfo(Clone)/Stamina") : GameObject.Find("Systems/UI/Canvas/IngamePlayerHUD/TopLeftCorner/SprintMeter"));
			if ((Object)(object)val == (Object)null)
			{
				mls.LogError((object)"sprintMeter is null");
				return;
			}
			sprintMeterImage = (OxygenBase.Instance.IsEladsHUDFound ? ((Component)val.transform.Find("Bar/StaminaBar")).GetComponent<Image>() : val.GetComponent<Image>());
			if (!OxygenBase.Instance.IsEladsHUDFound)
			{
				Init_vanilla(val);
				if (OxygenBase.Instance.IsLCVRFound)
				{
					CoroutineHelper.Start(Init_LCVR(val));
				}
			}
			else
			{
				Init_EladsHUD(val);
			}
			OxygenLogic.ResetAllNotifications();
			Percent = 1f;
			mls.LogInfo((object)"Oxygen is initialized");
		}

		private static void Init_vanilla(GameObject sprintMeter)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = sprintMeter.transform.parent;
			GameObject val = Object.Instantiate<GameObject>(sprintMeter, parent);
			((Object)val).name = "OxygenMeter";
			oxygenHUD = val.GetComponent<Image>();
			((Graphic)oxygenHUD).color = new Color(0.593f, 0.667f, 1f, 1f);
			RectTransform component = val.GetComponent<RectTransform>();
			component.anchorMin = new Vector2(0f, 1f);
			component.anchorMax = new Vector2(0f, 1f);
			component.pivot = new Vector2(0.5f, 0.5f);
			int value = OxygenBase.OxygenConfig.XOffset.Value;
			int value2 = OxygenBase.OxygenConfig.YOffset.Value;
			component.anchoredPosition = new Vector2((float)(131.6 + (double)value), (float)(-127.3715 + (double)value2));
			((Transform)component).localScale = new Vector3(2.0392f, 2.0392f, 1.6892f);
			((Transform)component).rotation = Quaternion.Euler(0f, 323.3253f, 0f);
			parent.Find("StatusEffects").localPosition = new Vector3(20.1763f, -4.0355f, 0.0046f);
			parent.Find("WeightUI").localPosition = new Vector3(-270f, 83f, 17f);
			mls.LogInfo((object)OxygenBase.OxygenConfig.autoFillingOnShip_increasingOxygen);
		}

		private static void Init_EladsHUD(GameObject sprintMeter)
		{
			//IL_0036: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = sprintMeter.transform.parent;
			GameObject val = Object.Instantiate<GameObject>(sprintMeter, parent);
			((Object)val).name = "OxygenMeter";
			val.transform.localPosition = new Vector3(135f, -91.2254f, 0f);
			oxygenHUD = ((Component)val.transform.Find("Bar/StaminaBar")).GetComponent<Image>();
			((Graphic)oxygenHUD).color = new Color(0.593f, 0.667f, 1f, 1f);
			GameObject gameObject = ((Component)val.transform.Find("StaminaInfo")).gameObject;
			gameObject.transform.localPosition = new Vector3(45.4834f, -6.4f, 2.8f);
			eladsUIText = gameObject.GetComponent<TextMeshProUGUI>();
			((Graphic)eladsUIText).color = new Color(0.593f, 0.667f, 1f, 1f);
			GameObject val2 = Object.Instantiate<GameObject>(gameObject, val.transform);
			val2.transform.localPosition = new Vector3(39.2f, -6.4f, 2.8f);
			TextMeshProUGUI component = val2.GetComponent<TextMeshProUGUI>();
			((TMP_Text)component).text = "<size=50%><voffset=-3>•</voffset></size>";
			((Graphic)component).color = new Color(1f, 1f, 1f, 0.37f);
			Object.Destroy((Object)(object)((Component)val.transform.Find("CarryInfo")).gameObject);
			Object.Destroy((Object)(object)((Component)val.transform.Find("Bar/Stamina Change FG")).gameObject);
			sprintMeter.transform.Find("StaminaInfo").localPosition = new Vector3(0f, -15.4f, 0f);
			sprintMeter.transform.Find("CarryInfo").localPosition = new Vector3(0f, -15.4f, 0f);
			parent.Find("Health").localPosition = new Vector3(135f, -160f, 0f);
		}

		private static IEnumerator Init_LCVR(GameObject sprintMeter)
		{
			if (!VRSession.InVR)
			{
				yield break;
			}
			if ((Object)(object)oxygenHUD == (Object)null)
			{
				mls.LogError((object)"Init_LCVR: oxygenHUD is null, WTF...");
				yield break;
			}
			yield return (object)new WaitUntil((Func<bool>)(() => (Object)(object)VRSession.Instance != (Object)null));
			((Component)oxygenHUD).transform.SetParent(sprintMeter.transform.parent, false);
			if (Plugin.Config.DisableArmHUD.Value)
			{
				((Component)oxygenHUD).transform.localPosition = new Vector3(-279.0514f, 74.9563f, 0f);
				((Component)oxygenHUD).transform.localRotation = Quaternion.Euler(0f, 0f, 0f);
				((Component)oxygenHUD).transform.localScale = new Vector3(2.55f, 2.5f, 2.5f);
				sprintMeter.transform.parent.Find("WeightUI").localPosition = new Vector3(-171f, 25f, 0f);
			}
			else
			{
				((Component)oxygenHUD).transform.localPosition = new Vector3(-45f, 95f, 70f);
				((Component)oxygenHUD).transform.localRotation = Quaternion.Euler(0f, 90f, 0f);
				((Component)oxygenHUD).transform.localScale = new Vector3(1.35f, 1.25f, 1f);
				sprintMeter.transform.parent.Find("WeightUI").localPosition = new Vector3(-50f, 60f, 67f);
			}
			mls.LogInfo((object)"OxygenHUD initialized (VR)");
		}

		internal static void Init_OxyCharger()
		{
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GameObject.Find("Environment/HangarShip/ScavengerModelSuitParts");
			if ((Object)(object)val == (Object)null)
			{
				mls.LogError((object)"suitParts are null");
				return;
			}
			GameObject gameObject = ((Component)val.transform.Find("Circle.002")).gameObject;
			GameObject val2 = Object.Instantiate<GameObject>(OxygenBase.Instance.oxyCharger, val.transform);
			val2.transform.rotation = gameObject.transform.rotation;
			val2.transform.position = new Vector3(5.9905f, 0.7598f, -11.2452f);
			Object.Destroy((Object)(object)gameObject);
		}
	}
	[BepInPlugin("consequential.Oxygen", "Oxygen", "1.6.3")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class OxygenBase : BaseUnityPlugin
	{
		private readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen");

		public const string modName = "Oxygen";

		public const string modGUID = "consequential.Oxygen";

		public const string modVersion = "1.6.3";

		private readonly Harmony harmony = new Harmony("consequential.Oxygen");

		private const string immersiveVisorGUID = "ImmersiveVisor";

		private const string shyHUDGUID = "ShyHUD";

		private const string eladsHUDGUID = "me.eladnlg.customhud";

		private const string LCVRGUID = "io.daxcess.lcvr";

		internal AudioClip[] inhalesSFX = Array.Empty<AudioClip>();

		internal AudioClip[] heavyInhalesSFX = Array.Empty<AudioClip>();

		internal GameObject oxyAudioExample;

		internal GameObject oxyCharger;

		internal AudioClip[] oxyChargerSFX;

		internal Item oxyBoost;

		public static OxygenConfig OxygenConfig { get; private set; }

		public bool IsShyHUDFound { get; private set; } = false;


		public bool IsImmersiveVisorFound { get; private set; } = false;


		public bool IsEladsHUDFound { get; private set; } = false;


		public bool IsLCVRFound { get; private set; } = false;


		public static OxygenBase Instance { get; private set; }

		internal static void UpdateCustomItemPrice(Item item, int price)
		{
			Items.UpdateShopItemPrice(item, price);
		}

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			mls.LogInfo((object)"Oxygen is loading...");
			NetworkPatcher();
			IsShyHUDFound = CheckForDependency("ShyHUD");
			IsImmersiveVisorFound = CheckForDependency("ImmersiveVisor");
			IsEladsHUDFound = CheckForDependency("me.eladnlg.customhud");
			IsLCVRFound = CheckForDependency("io.daxcess.lcvr");
			AssetBundle val = Utilities.LoadAssetFromStream("Oxygen.Assets.oxygenaudio");
			if (!((Object)(object)val == (Object)null))
			{
				inhalesSFX = Utilities.LoadAudioClips(val, "Assets/OxygenAudio/Inhale_1.wav", "Assets/OxygenAudio/Inhale_2.wav", "Assets/OxygenAudio/Inhale_3.wav");
				heavyInhalesSFX = Utilities.LoadAudioClips(val, "Assets/OxygenAudio/heavy_Inhale_1.wav", "Assets/OxygenAudio/heavy_Inhale_2.wav", "Assets/OxygenAudio/heavy_Inhale_end.wav");
				oxyChargerSFX = Utilities.LoadAudioClips(val, "Assets/OxyCharger/Audio/OxyChargeSFX.wav", "Assets/OxyCharger/Audio/OxyChargeSFX2.wav", "Assets/OxyCharger/Audio/OxyChargeSFX3.wav");
				AssetBundle val2 = Utilities.LoadAssetFromStream("Oxygen.Assets.oxygenprefabs");
				if (!((Object)(object)val2 == (Object)null))
				{
					oxyAudioExample = val2.LoadAsset<GameObject>("Assets/OxygenAudio/OxygenAudio.prefab");
					oxyCharger = val2.LoadAsset<GameObject>("Assets/OxyCharger/OxyCharger.prefab");
					oxyBoost = val2.LoadAsset<Item>("Assets/OxyBoost/OxyBoostItem.asset");
					mls.LogInfo((object)"Assets are loaded!");
					OxygenConfig = new OxygenConfig(((BaseUnityPlugin)this).Config);
					mls.LogInfo((object)"Config is loaded.");
					harmony.PatchAll(typeof(HUDPatch));
					harmony.PatchAll(typeof(OxygenConfig));
					harmony.PatchAll(typeof(StartOfRoundPatch));
					harmony.PatchAll(typeof(RoundManagerPatch));
					harmony.PatchAll(typeof(GameNetworkManagerParch));
					harmony.PatchAll(typeof(PlayerControllerBPatch));
					RegisterItems();
					mls.LogInfo((object)"Oxygen is loaded. Don't forget to refill oxygen canisters!");
				}
			}
		}

		private void NetworkPatcher()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic);
				MethodInfo[] array2 = methods;
				foreach (MethodInfo methodInfo in array2)
				{
					object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false);
					if (customAttributes.Length != 0)
					{
						methodInfo.Invoke(null, null);
					}
				}
			}
		}

		private bool CheckForDependency(string guid)
		{
			mls.LogDebug((object)("Checking for " + guid + "..."));
			if (Chainloader.PluginInfos.ContainsKey(guid))
			{
				Chainloader.PluginInfos.TryGetValue(guid, out var value);
				if (value != null)
				{
					mls.LogDebug((object)$"{guid}:{value.Metadata.Version} is present!");
					return true;
				}
				mls.LogError((object)("Detected " + guid + ", but could not get plugin info..."));
			}
			return false;
		}

		private void RegisterItems()
		{
			NetworkPrefabs.RegisterNetworkPrefab(oxyBoost.spawnPrefab);
			Utilities.FixMixerGroups(oxyBoost.spawnPrefab);
			TerminalNode val = ScriptableObject.CreateInstance<TerminalNode>();
			val.clearPreviousText = true;
			val.displayText = "Limited air supply, useful in situations when you cannot quickly refill oxygen canisters!";
			Items.RegisterShopItem(oxyBoost, (TerminalNode)null, (TerminalNode)null, val, OxygenConfig.oxyBoost_price.Value);
			mls.LogInfo((object)"Custom items are loaded!");
		}
	}
}
namespace Oxygen.Patches
{
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerParch
	{
		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix(ref GameNetworkManager __instance)
		{
			((Component)__instance).GetComponent<NetworkManager>().AddNetworkPrefab(OxygenBase.Instance.oxyCharger);
		}
	}
	[HarmonyPatch(typeof(HUDManager))]
	internal class HUDPatch
	{
		public static ManualLogSource mls = Logger.CreateLogSource("Oxygen > HUDPatch");

		[HarmonyPostfix]
		[HarmonyPatch("Start")]
		public static void BuildHUD()
		{
			mls.LogInfo((object)"Initializing HUD");
			OxygenInit.Init();
		}

		[HarmonyPostfix]
		[HarmonyPatch("Update")]
		public static void UpdatePatch()
		{
			OxygenLogic.RunLogic();
		}
	}
	[HarmonyPatch(typeof(PlayerControllerB))]
	internal class PlayerControllerBPatch
	{
		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > PlayerControllerBPatch");

		[HarmonyPostfix]
		[HarmonyPatch("ConnectClientToPlayerObject")]
		public static void ConnectClientToPlayerObject_Postfix(PlayerControllerB __instance)
		{
			AudioController.Init_AudioSource(__instance.playersManager.thisClientPlayerId);
		}

		[HarmonyPostfix]
		[HarmonyPatch("KillPlayer")]
		private static void KillPlayer_Postfix(PlayerControllerB __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && __instance.isPlayerDead)
			{
				OxygenInit.Percent = 1f;
				__instance.drunkness = 0f;
				mls.LogInfo((object)"Player is dead. Oxygen level was recovered");
				OxygenLogic.ResetAllNotifications();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch("LateUpdate")]
		private static void LateUpdate_Prefix(PlayerControllerB __instance)
		{
			if (((NetworkBehaviour)__instance).IsOwner && (!((NetworkBehaviour)__instance).IsServer || __instance.isHostPlayerObject) && !__instance.isPlayerDead)
			{
				OxygenLogic.ShowNotifications(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager))]
	internal class RoundManagerPatch
	{
		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > RoundManagerPatch");

		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Awake_Postfix()
		{
			MoonsDicts.UpdateMoonsValues();
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		[HarmonyPatch("Start")]
		private static void Start_Postfix(RoundManager __instance)
		{
			string text = "\nUse these moons names in the config:\n\n";
			SelectableLevel[] levels = __instance.playersManager.levels;
			foreach (SelectableLevel val in levels)
			{
				text = text + Utilities.GetNumberlessPlanetName(val.PlanetName) + "\n";
			}
			mls.LogInfo((object)text);
		}

		[HarmonyPostfix]
		[HarmonyPatch("FinishGeneratingLevel")]
		private static void FinishGeneratingLevel_Postfix(RoundManager __instance)
		{
			WeatherHandler.UpdateWeatherType(__instance.currentLevel);
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatch
	{
		public static ManualLogSource mls = Logger.CreateLogSource("Oxygen > StartOfRoundPatch");

		[HarmonyPostfix]
		[HarmonyPatch("ShipHasLeft")]
		private static void ShipHasLeft_Patch()
		{
			if (OxygenBase.OxygenConfig.recoverOxygen_ShipLeft.Value)
			{
				OxygenInit.Percent = 1f;
				mls.LogInfo((object)"Ship has left, oxygen was recovered.");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OpenShipDoors")]
		private static void OpenShipDoors_PostFix()
		{
			if (OxygenBase.OxygenConfig.recoverOxygen_StartOfRound.Value)
			{
				OxygenInit.Percent = 1f;
				mls.LogInfo((object)"Round just started, oxygen was recovered.");
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Patch_RoundAwake()
		{
			OxygenInit.Init_OxyCharger();
		}
	}
}
namespace Oxygen.Items
{
	internal class OxyBoost : TetraChemicalItem
	{
		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > OxyBoost");

		public IEnumerator UseTZPAnimation()
		{
			base.thisAudioSource.PlayOneShot(base.holdCanSFX);
			WalkieTalkie.TransmitOneShotAudio(base.previousPlayerHeldBy.itemAudio, base.holdCanSFX, 1f);
			yield return (object)new WaitForSeconds(0.75f);
			base.emittingGas = true;
			if (((NetworkBehaviour)this).IsOwner)
			{
				base.localHelmetSFX.Play();
				base.localHelmetSFX.PlayOneShot(base.twistCanSFX);
			}
			else
			{
				base.thisAudioSource.clip = base.releaseGasSFX;
				base.thisAudioSource.Play();
				base.thisAudioSource.PlayOneShot(base.twistCanSFX);
			}
		}

		public override void Update()
		{
			if ((Object)(object)base.previousPlayerHeldBy != (Object)null)
			{
				float drunknessInertia = base.previousPlayerHeldBy.drunknessInertia;
				((TetraChemicalItem)this).Update();
				base.previousPlayerHeldBy.drunknessInertia = drunknessInertia;
				base.previousPlayerHeldBy.increasingDrunknessThisFrame = false;
			}
			else
			{
				((TetraChemicalItem)this).Update();
			}
			if (base.emittingGas && (Object)(object)base.previousPlayerHeldBy == (Object)(object)GameNetworkManager.Instance.localPlayerController)
			{
				float percent = OxygenInit.Percent;
				OxygenInit.Percent = Mathf.Clamp(OxygenInit.Percent + OxygenBase.OxygenConfig.oxyBoost_increasingValue.Value, 0f, 1f);
				mls.LogDebug((object)$"Player's oxygen: {OxygenInit.Percent}");
				mls.LogDebug((object)$"OxyBoost fuel: {base.fuel}");
				if (percent <= 0.3f && StartOfRound.Instance.drowningTimer > 0.3f)
				{
					StartOfRound.Instance.playedDrowningSFX = false;
				}
			}
		}

		protected override void __initializeVariables()
		{
			((TetraChemicalItem)this).__initializeVariables();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "OxyBoost";
		}
	}
	internal class OxyCharger : NetworkBehaviour
	{
		private readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > OxyCharger");

		private AudioSource audioSource;

		private NetworkVariable<float> _remainedOxygenAmount = new NetworkVariable<float>(0f, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		private float IncreasingOxygen => OxygenBase.OxygenConfig.autoFillingOnShip_increasingOxygen.Value;

		private float Volume => OxygenBase.OxygenConfig.oxyCharger_SFXVolume.Value;

		private AudioClip[] OxyChargerSFX => OxygenBase.Instance.oxyChargerSFX;

		public float RemainedOxygenAmount
		{
			get
			{
				if (_remainedOxygenAmount == null)
				{
					return 0f;
				}
				return _remainedOxygenAmount.Value;
			}
			internal set
			{
				if (_remainedOxygenAmount == null)
				{
					return;
				}
				mls.LogDebug((object)("RemainedOxygenAmount before: " + RemainedOxygenAmount));
				float num = ((value < 0f) ? 0f : value);
				if (_remainedOxygenAmount.Value != num)
				{
					if (((NetworkBehaviour)this).IsHost || ((NetworkBehaviour)this).IsServer)
					{
						_remainedOxygenAmount.Value = num;
					}
					else
					{
						UpdateRemainedOxygenAmountServerRpc(num);
					}
				}
				mls.LogDebug((object)("RemainedOxygenAmount after: " + RemainedOxygenAmount));
				if (((NetworkBehaviour)this).IsClient && !((NetworkBehaviour)this).IsHost && !((NetworkBehaviour)this).IsServer)
				{
					mls.LogDebug((object)"RemainedOxygenAmount (after) value will be displayed without updating on the client-side, but actually it should be updated");
				}
			}
		}

		public static OxyCharger Instance { get; private set; }

		private void Awake()
		{
			Instance = this;
			audioSource = ((Component)this).GetComponent<AudioSource>();
			if (!SyncedEntry<bool>.op_Implicit(OxygenBase.OxygenConfig.oxyCharger_Enabled))
			{
				for (int num = ((Component)this).transform.childCount - 1; num >= 0; num--)
				{
					mls.LogDebug((object)(((Component)((Component)this).transform.GetChild(num)).gameObject.tag ?? ""));
					if (((Component)((Component)this).transform.GetChild(num)).gameObject.tag == "InteractTrigger")
					{
						Object.Destroy((Object)(object)((Component)((Component)this).transform.GetChild(num)).gameObject);
						mls.LogInfo((object)"InteractTrigger was deleted");
					}
				}
			}
			else
			{
				mls.LogInfo((object)"Oxygen cylinders were replaced");
			}
		}

		public void FillOxygen(bool playSound = true)
		{
			if (OxygenInit.Percent < 1f)
			{
				if (WeatherHandler.IsOxygenOnShipLimited)
				{
					mls.LogDebug((object)"Oxygen is limited.");
					if (RemainedOxygenAmount <= 0f)
					{
						return;
					}
					float num = 1f - OxygenInit.Percent;
					if (RemainedOxygenAmount >= num)
					{
						OxygenInit.Percent = 1f;
						RemainedOxygenAmount -= num;
					}
					else
					{
						OxygenInit.Percent += RemainedOxygenAmount;
						RemainedOxygenAmount = 0f;
					}
				}
				else
				{
					OxygenInit.Percent = 1f;
				}
			}
			if (playSound)
			{
				PlaySFX();
			}
			mls.LogInfo((object)"Oxygen was recovered");
		}

		public void AutoRefillOxygen()
		{
			if (!(OxygenInit.Percent < 1f))
			{
				return;
			}
			if (WeatherHandler.IsOxygenOnShipLimited)
			{
				mls.LogDebug((object)"Oxygen is limited.");
				if (!(RemainedOxygenAmount <= 0f))
				{
					if (RemainedOxygenAmount >= IncreasingOxygen)
					{
						OxygenInit.Percent += IncreasingOxygen;
						RemainedOxygenAmount -= IncreasingOxygen;
					}
					else
					{
						OxygenInit.Percent += RemainedOxygenAmount;
						RemainedOxygenAmount = 0f;
					}
				}
			}
			else
			{
				OxygenInit.Percent += IncreasingOxygen;
			}
		}

		private void PlaySFX()
		{
			if (((NetworkBehaviour)this).IsHost || ((NetworkBehaviour)this).IsServer)
			{
				PlaySFXClientRpc();
			}
			else
			{
				PlaySFXServerRpc();
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void PlaySFXServerRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(1243737812u, val, (RpcDelivery)0);
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 1243737812u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					PlaySFXClientRpc();
				}
			}
		}

		[ClientRpc]
		private void PlaySFXClientRpc()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//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)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager == null || !networkManager.IsListening)
			{
				return;
			}
			if ((int)base.__rpc_exec_stage != 2 && (networkManager.IsServer || networkManager.IsHost))
			{
				ClientRpcParams val = default(ClientRpcParams);
				FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(3475112299u, val, (RpcDelivery)0);
				((NetworkBehaviour)this).__endSendClientRpc(ref val2, 3475112299u, val, (RpcDelivery)0);
			}
			if ((int)base.__rpc_exec_stage == 2 && (networkManager.IsClient || networkManager.IsHost))
			{
				if ((Object)(object)audioSource == (Object)null)
				{
					mls.LogError((object)"Audio source was not found");
				}
				if (audioSource.isPlaying)
				{
					audioSource.Stop();
				}
				AudioClip val3 = OxyChargerSFX[Random.Range(0, OxyChargerSFX.Length)];
				audioSource.PlayOneShot(val3, Volume);
				mls.LogDebug((object)"Playing sound");
			}
		}

		[ServerRpc(RequireOwnership = false)]
		private void UpdateRemainedOxygenAmountServerRpc(float newValue)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsClient || networkManager.IsHost))
				{
					ServerRpcParams val = default(ServerRpcParams);
					FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendServerRpc(4039431233u, val, (RpcDelivery)0);
					((FastBufferWriter)(ref val2)).WriteValueSafe<float>(ref newValue, default(ForPrimitives));
					((NetworkBehaviour)this).__endSendServerRpc(ref val2, 4039431233u, val, (RpcDelivery)0);
				}
				if ((int)base.__rpc_exec_stage == 1 && (networkManager.IsServer || networkManager.IsHost))
				{
					RemainedOxygenAmount = newValue;
				}
			}
		}

		protected override void __initializeVariables()
		{
			if (_remainedOxygenAmount == null)
			{
				throw new Exception("OxyCharger._remainedOxygenAmount cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)_remainedOxygenAmount).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)_remainedOxygenAmount, "_remainedOxygenAmount");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)_remainedOxygenAmount);
			((NetworkBehaviour)this).__initializeVariables();
		}

		[RuntimeInitializeOnLoadMethod]
		internal static void InitializeRPCS_OxyCharger()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			NetworkManager.__rpc_func_table.Add(1243737812u, new RpcReceiveHandler(__rpc_handler_1243737812));
			NetworkManager.__rpc_func_table.Add(3475112299u, new RpcReceiveHandler(__rpc_handler_3475112299));
			NetworkManager.__rpc_func_table.Add(4039431233u, new RpcReceiveHandler(__rpc_handler_4039431233));
		}

		private static void __rpc_handler_1243737812(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;
				((OxyCharger)(object)target).PlaySFXServerRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_3475112299(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)2;
				((OxyCharger)(object)target).PlaySFXClientRpc();
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		private static void __rpc_handler_4039431233(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams)
		{
			//IL_002f: 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_0044: 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)
			NetworkManager networkManager = target.NetworkManager;
			if (networkManager != null && networkManager.IsListening)
			{
				float newValue = default(float);
				((FastBufferReader)(ref reader)).ReadValueSafe<float>(ref newValue, default(ForPrimitives));
				target.__rpc_exec_stage = (__RpcExecStage)1;
				((OxyCharger)(object)target).UpdateRemainedOxygenAmountServerRpc(newValue);
				target.__rpc_exec_stage = (__RpcExecStage)0;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		protected internal override string __getTypeName()
		{
			return "OxyCharger";
		}
	}
}
namespace Oxygen.General
{
	internal class WeatherHandler
	{
		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > WeatherHandler");

		internal static LevelWeatherType weatherType = (LevelWeatherType)(-1);

		private static bool _isOxygenOnShipLimited;

		public static bool IsOxygenOnShipLimited
		{
			get
			{
				StartOfRound instance = StartOfRound.Instance;
				if ((Object)(object)instance != (Object)null && instance.shipIsLeaving)
				{
					return false;
				}
				return _isOxygenOnShipLimited;
			}
			private set
			{
				_isOxygenOnShipLimited = value;
			}
		}

		internal static void UpdateWeatherType(SelectableLevel level)
		{
			//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_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Invalid comparison between Unknown and I4
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			IsOxygenOnShipLimited = false;
			if ((Object)(object)level == (Object)null)
			{
				mls.LogError((object)"Current level is null. WeatherType was setted to None.");
				weatherType = (LevelWeatherType)(-1);
				return;
			}
			weatherType = level.currentWeather;
			string text = "\nCurrent level report:\n";
			text = text + "Current level name: " + ((Object)level).name;
			text = text + "\nPlanet name: " + Utilities.GetLLLNameOfLevel(level.PlanetName);
			text = text + "\nCurrent weather: " + ((object)(LevelWeatherType)(ref level.currentWeather)).ToString();
			text += "\n\n";
			mls.LogInfo((object)text);
			if ((int)weatherType == 5 && OxygenBase.OxygenConfig.eclipsed_LimitOxygen.Value)
			{
				mls.LogInfo((object)"The weather on the planet is \"Eclipsed\", the oxygen on the ship has\u00a0now\u00a0become\u00a0limited.");
				OxyCharger.Instance.RemainedOxygenAmount = OxygenBase.OxygenConfig.eclipsed_LimitedOxygenAmount.Value;
				IsOxygenOnShipLimited = true;
			}
		}
	}
}
namespace Oxygen.GameObjects
{
	internal class OxygenLogic : MonoBehaviour
	{
		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > OxygenLogic");

		public const float low_OxygenAmount = 0.2f;

		public const float critical_OxygenAmount = 0.1f;

		public const float damage_OxygenAmount = 0f;

		private static float secTimerInFear = 2f;

		private static float secTimerForAudio = 5f;

		private static float timeSinceLastAction = 0f;

		private static float timeSinceLastFear = 0f;

		private static float timeSinceLastPlayedAudio = 0f;

		private static bool breathablePlace_Notification = false;

		private static bool immersiveVisor_Notification = false;

		private static bool lowLevel_Notification = false;

		private static bool criticalLevel_Notification = false;

		private static bool wasInFearOrExhaustedLastFrame = false;

		private static bool wasRunningLastFrame = false;

		private static float runTime = 0f;

		private static float OxygenAmount
		{
			get
			{
				return OxygenInit.Percent;
			}
			set
			{
				OxygenInit.Percent = value;
			}
		}

		private static bool InfinityOxygenInModsPlaces => OxygenBase.OxygenConfig.infinityOxygenInModsPlaces.Value;

		private static bool ImmersiveVisorSupport => OxygenBase.OxygenConfig.immersiveVisorSupport.Value;

		private static float ImmersiveVisor_OxygenDecreasing => OxygenBase.OxygenConfig.immersiveVisor_OxygenDecreasing.Value;

		private static OxygenConfig.AutoFillingOnShip AutoFillingOnShip => OxygenBase.OxygenConfig.autoFillingOnShip.Value;

		private static int PlayerDamage => OxygenBase.OxygenConfig.playerDamage.Value;

		private static bool IsgreenPlanet => MoonsDicts.GreenPlanetsValue;

		private static float IncreasingOxygen => OxygenBase.OxygenConfig.autoFillingOnShip_increasingOxygen.Value;

		private static float DecreasingOxygenOutside => MoonsDicts.DecreasingOxygenOutsideMoonsValue;

		private static float DecreasingOxygenInFactory => MoonsDicts.DecreasingOxygenInFactoryMoonsValue;

		private static float RunningMultiplier => MoonsDicts.RunningMultiplierMoonsValue;

		private static float OxygenDepletionInWater => MoonsDicts.OxygenDepletionInWaterMoonsValue;

		private static float DecreasingInFear => OxygenBase.OxygenConfig.decreasingInFear.Value;

		private static float OxygenDeficiency => OxygenBase.OxygenConfig.oxygenDeficiency.Value;

		private static float SecTimer => OxygenBase.OxygenConfig.secTimer.Value;

		private static bool EnableOxygenSFX => OxygenBase.OxygenConfig.enableOxygenSFX.Value;

		private static bool EnableInhaleSFXWhileWalking => OxygenBase.OxygenConfig.enableInhaleSFXWhileWalking.Value;

		private static bool EnableOxygenSFXInShip => OxygenBase.OxygenConfig.enableOxygenSFXInShip.Value;

		private static bool EnableOxygenSFXOnTheCompany => OxygenBase.OxygenConfig.enableOxygenSFXOnTheCompany.Value;

		private static bool IsNotification => OxygenBase.OxygenConfig.notifications.Value;

		private static void SFX_Logic(PlayerControllerB pc, StartOfRound sor)
		{
			if (!EnableOxygenSFX)
			{
				return;
			}
			if (timeSinceLastPlayedAudio >= secTimerForAudio)
			{
				bool flag = false;
				if (EnableOxygenSFXOnTheCompany && StartOfRound.Instance.currentLevel.levelID == 3 && !pc.isInHangarShipRoom)
				{
					flag = true;
				}
				else if (IsgreenPlanet && pc.isInsideFactory)
				{
					flag = true;
				}
				else if (pc.isInHangarShipRoom && EnableOxygenSFXInShip)
				{
					flag = true;
				}
				else if (!pc.isInHangarShipRoom && StartOfRound.Instance.currentLevel.levelID != 3 && !IsgreenPlanet)
				{
					flag = true;
				}
				if (flag)
				{
					AudioController.State state = AudioController.State.standing;
					float volume = 1f;
					if (sor.fearLevel > 0f)
					{
						if (!pc.isInHangarShipRoom || (pc.isInHangarShipRoom && EnableOxygenSFXInShip))
						{
							state = AudioController.State.scared;
							volume = OxygenBase.OxygenConfig.scaredSFX_volume.Value;
							wasInFearOrExhaustedLastFrame = true;
						}
					}
					else if (pc.isSprinting && !breathablePlace_Notification)
					{
						state = AudioController.State.running;
						volume = OxygenBase.OxygenConfig.runningSFX_volume.Value;
					}
					else if (pc.isExhausted && !breathablePlace_Notification)
					{
						state = AudioController.State.exhausted;
						volume = OxygenBase.OxygenConfig.exhaustedSFX_volume.Value;
						wasInFearOrExhaustedLastFrame = true;
					}
					else if (pc.isWalking && EnableInhaleSFXWhileWalking && !breathablePlace_Notification)
					{
						state = AudioController.State.walking;
						volume = OxygenBase.OxygenConfig.walkingSFX_volume.Value;
					}
					bool isEndOfFearOrExhausted = false;
					if (wasInFearOrExhaustedLastFrame && sor.fearLevel <= 0f && state != AudioController.State.scared && !pc.isExhausted && state != AudioController.State.exhausted)
					{
						wasInFearOrExhaustedLastFrame = false;
						isEndOfFearOrExhausted = true;
						state = AudioController.State.scared;
					}
					if (state != 0)
					{
						AudioController.PlaySFX(state, volume, isEndOfFearOrExhausted);
					}
					secTimerForAudio = (float)state;
				}
				timeSinceLastPlayedAudio = 0f;
			}
			timeSinceLastPlayedAudio += Time.deltaTime;
		}

		internal static void ShowNotifications(PlayerControllerB pc)
		{
			if (!IsNotification)
			{
				return;
			}
			if (OxygenAmount < 0.2f)
			{
				if (!lowLevel_Notification)
				{
					HUDManager.Instance.DisplayTip("System...", "The oxygen tanks are running low.", false, false, "LC_Tip1");
					lowLevel_Notification = true;
				}
			}
			else
			{
				lowLevel_Notification = false;
			}
			if (OxygenAmount < 0.1f)
			{
				if (!criticalLevel_Notification)
				{
					HUDManager.Instance.DisplayTip("System...", "Oxygen tanks have a critical level of oxygen, fill them up immediately!", true, false, "LC_Tip1");
					criticalLevel_Notification = true;
				}
			}
			else
			{
				criticalLevel_Notification = false;
			}
			if (InfinityOxygenInModsPlaces && pc.serverPlayerPosition.y <= -480f)
			{
				if (!breathablePlace_Notification)
				{
					HUDManager.Instance.DisplayTip("System...", "Oxygen outside is breathable, oxygen supply through cylinders is turned off", false, false, "LC_Tip1");
					breathablePlace_Notification = true;
				}
			}
			else
			{
				breathablePlace_Notification = false;
			}
			if (OxygenBase.Instance.IsImmersiveVisorFound && ImmersiveVisorSupport)
			{
				Notification_ImmersiveVisor();
			}
		}

		internal static void ResetAllNotifications()
		{
			breathablePlace_Notification = false;
			immersiveVisor_Notification = false;
			lowLevel_Notification = false;
			criticalLevel_Notification = false;
		}

		private static void Notification_ImmersiveVisor()
		{
			if (((VolumeParameter<int>)(object)Visor.Instance.visorCrack.crackLevel).value == 2)
			{
				if (!immersiveVisor_Notification)
				{
					HUDManager.Instance.DisplayTip("System...", "The helmet is experiencing oxygen leakage due to substantial damage", true, false, "LC_Tip1");
					immersiveVisor_Notification = true;
				}
			}
			else
			{
				immersiveVisor_Notification = false;
			}
		}

		internal static void RunLogic()
		{
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_033a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0349: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
			if (!OxygenInit.IsOxygenHUDInitialized)
			{
				mls.LogError((object)"oxygenUI is null, lol...");
				return;
			}
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null)
			{
				mls.LogError((object)"StartOfRound is null");
				return;
			}
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if ((Object)(object)localPlayerController == (Object)null)
			{
				mls.LogError((object)"PlayerControllerB is null");
			}
			else
			{
				if (localPlayerController.isPlayerDead)
				{
					return;
				}
				float num = 0f;
				instance.drowningTimer = OxygenAmount;
				SFX_Logic(localPlayerController, instance);
				if (!localPlayerController.isInHangarShipRoom)
				{
					if (localPlayerController.isSprinting)
					{
						wasRunningLastFrame = true;
						runTime += Time.deltaTime;
					}
					else if (!localPlayerController.isSprinting && wasRunningLastFrame && (double)runTime > 0.4)
					{
						float staminaFillAmount = OxygenInit.StaminaFillAmount;
						float num2 = RunningMultiplier * localPlayerController.movementSpeed * runTime * (1f - staminaFillAmount) / 1000f;
						if (staminaFillAmount > 0.8f)
						{
							num2 *= 0.5f;
						}
						mls.LogDebug((object)$"player was running for {runTime}");
						mls.LogDebug((object)$"player's current stamina amount is {staminaFillAmount}");
						mls.LogDebug((object)$"total oxygen consumption: {num2}");
						num += num2;
						wasRunningLastFrame = false;
						runTime = 0f;
					}
					if (timeSinceLastFear >= secTimerInFear && instance.fearLevel > 0f)
					{
						mls.LogDebug((object)$"Oxygen consumption is increased by {DecreasingInFear}");
						num += DecreasingInFear;
						timeSinceLastFear = 0f;
					}
					timeSinceLastFear += Time.deltaTime;
					if (timeSinceLastAction >= SecTimer)
					{
						if (IsgreenPlanet && !localPlayerController.isInsideFactory)
						{
							mls.LogDebug((object)"It's a green planet and you're outside, oxygen consumption is omitted!");
							num = 0f;
						}
						else if (!localPlayerController.isInsideFactory)
						{
							num += DecreasingOxygenOutside;
						}
						else if (localPlayerController.isInsideFactory)
						{
							num += DecreasingOxygenInFactory;
						}
						if (OxygenBase.Instance.IsImmersiveVisorFound && ImmersiveVisorSupport)
						{
							num += LogicForImmersiveVisor();
						}
						if (OxygenAmount < 0.1f)
						{
							localPlayerController.drunkness = Mathf.Clamp01(localPlayerController.drunkness + OxygenDeficiency);
							mls.LogDebug((object)$"current oxygen deficiency level: {localPlayerController.drunkness}");
						}
						if (localPlayerController.isUnderwater && (Object)(object)localPlayerController.underwaterCollider != (Object)null)
						{
							Bounds bounds = localPlayerController.underwaterCollider.bounds;
							if (((Bounds)(ref bounds)).Contains(((Component)localPlayerController.gameplayCamera).transform.position))
							{
								mls.LogDebug((object)$"The player is underwater, oxygen consumption is increased by {OxygenDepletionInWater}");
								num += OxygenDepletionInWater;
							}
						}
						if (OxygenAmount <= 0f)
						{
							localPlayerController.DamagePlayer(PlayerDamage, true, true, (CauseOfDeath)0, 0, false, default(Vector3));
						}
						if (InfinityOxygenInModsPlaces && localPlayerController.serverPlayerPosition.y <= -480f)
						{
							localPlayerController.drunkness = Mathf.Clamp01(localPlayerController.drunkness - OxygenDeficiency);
						}
						else
						{
							OxygenAmount -= num;
							mls.LogDebug((object)$"current oxygen level: {OxygenAmount}");
						}
						timeSinceLastAction = 0f;
					}
					timeSinceLastAction += Time.deltaTime;
				}
				else
				{
					if (((AutoFillingOnShip == OxygenConfig.AutoFillingOnShip.WhenDoorsClosed && instance.hangarDoorsClosed) || AutoFillingOnShip == OxygenConfig.AutoFillingOnShip.WhenPlayerOnShip) && OxygenAmount < 1f)
					{
						OxyCharger.Instance.AutoRefillOxygen();
						mls.LogDebug((object)$"Oxygen is recovering: {OxygenAmount}");
					}
					localPlayerController.drunkness = Mathf.Clamp01(localPlayerController.drunkness - IncreasingOxygen);
				}
			}
		}

		private static float LogicForImmersiveVisor()
		{
			if (((VolumeParameter<int>)(object)Visor.Instance.visorCrack.crackLevel).value == 2)
			{
				mls.LogDebug((object)$"The helmet is fucked, oxygen consumption is increased by {ImmersiveVisor_OxygenDecreasing}");
				return ImmersiveVisor_OxygenDecreasing;
			}
			return 0f;
		}
	}
}
namespace Oxygen.Extras
{
	internal class AudioController : MonoBehaviour
	{
		public enum State
		{
			standing = 0,
			walking = 5,
			running = 4,
			exhausted = 3,
			scared = 2
		}

		private static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > AudioController");

		private static AudioSource oxygenDefault;

		private static AudioClip[] InhalesSFX => OxygenBase.Instance.inhalesSFX;

		private static AudioClip[] HeavyInhalesSFX => OxygenBase.Instance.heavyInhalesSFX;

		internal static void Init_AudioSource(int id)
		{
			mls.LogWarning((object)$"Client id: {id}");
			string text = ((id == 0) ? "PlayersContainer/Player/Audios/" : $"PlayersContainer/Player ({id})/Audios/");
			GameObject val = GameObject.Find(text);
			GameObject val2 = Object.Instantiate<GameObject>(OxygenBase.Instance.oxyAudioExample, val.transform);
			((Object)val2).name = "OxygenDefault";
			oxygenDefault = val2.GetComponent<AudioSource>();
			mls.LogWarning((object)"Oxygen audio sources are created!");
		}

		internal static void PlaySFX(State stage, float volume, bool isEndOfFearOrExhausted = false)
		{
			AudioSource val = oxygenDefault;
			if (!val.isPlaying)
			{
				AudioClip val2 = FindSFX(stage, isEndOfFearOrExhausted);
				mls.LogDebug((object)"Playing SFX");
				val.PlayOneShot(val2, Random.Range(volume - 0.18f, volume));
			}
		}

		private static AudioClip FindSFX(State stage, bool isEndOfFearOrExhausted)
		{
			mls.LogDebug((object)$"Trying to find SFX for stage: {stage}");
			if (1 == 0)
			{
			}
			AudioClip val = (AudioClip)(stage switch
			{
				State.standing => null, 
				State.walking => InhalesSFX[Random.Range(0, InhalesSFX.Length - 1)], 
				State.running => InhalesSFX[Random.Range(0, InhalesSFX.Length - 1)], 
				State.exhausted => isEndOfFearOrExhausted ? HeavyInhalesSFX[^1] : HeavyInhalesSFX[Random.Range(0, HeavyInhalesSFX.Length - 2)], 
				State.scared => isEndOfFearOrExhausted ? HeavyInhalesSFX[^1] : HeavyInhalesSFX[Random.Range(0, HeavyInhalesSFX.Length - 2)], 
				_ => null, 
			});
			if (1 == 0)
			{
			}
			AudioClip val2 = val;
			mls.LogDebug((object)("clip name: " + ((Object)val2).name));
			return val2;
		}
	}
	internal static class Utilities
	{
		public static ManualLogSource mls = Logger.CreateLogSource("Oxygen > Utils");

		internal static T GetPrivateField<T>(this object obj, string field)
		{
			return (T)obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
		}

		internal static string GetLLLNameOfLevel(string levelName)
		{
			string text = StripSpecialCharacters(GetNumberlessPlanetName(levelName));
			if (!text.EndsWith("Level"))
			{
				text += "Level";
			}
			return text;
		}

		internal static string GetNumberlessPlanetName(string planetName)
		{
			if (planetName != null)
			{
				return new string(planetName.SkipWhile((char c) => !char.IsLetter(c)).ToArray());
			}
			return string.Empty;
		}

		private static string StripSpecialCharacters(string input)
		{
			string text = string.Empty;
			for (int i = 0; i < input.Length; i++)
			{
				char c = input[i];
				if ((!".,?!@#$%^&*()_+-=';:'\"".ToCharArray().Contains(c) && char.IsLetterOrDigit(c)) || c.ToString() == " ")
				{
					text += c;
				}
			}
			return text;
		}

		internal static AssetBundle LoadAssetFromStream(string path)
		{
			try
			{
				Stream manifestResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path);
				if (manifestResourceStream == null)
				{
					mls.LogError((object)"Failed to get stream of resources...");
					return null;
				}
				AssetBundle val = AssetBundle.LoadFromStream(manifestResourceStream);
				if ((Object)(object)val == (Object)null)
				{
					mls.LogError((object)"Failed to load assets...");
					return null;
				}
				return val;
			}
			catch (Exception ex)
			{
				mls.LogError((object)("Exception: " + ex.Message));
				return null;
			}
		}

		internal static AudioClip[] LoadAudioClips(AssetBundle bundle, params string[] paths)
		{
			return (from path in paths
				select bundle.LoadAsset<AudioClip>(path) into clip
				where (Object)(object)clip != (Object)null
				select clip).ToArray();
		}
	}
}
namespace Oxygen.Configuration
{
	internal class MoonsDicts
	{
		private static readonly CultureInfo cultureInfo = CultureInfo.InvariantCulture;

		public static ManualLogSource mls = Logger.CreateLogSource("Oxygen > ConfigHandler");

		internal static Dictionary<string, float> greenPlanets;

		internal static Dictionary<string, float> decreasingOxygenOutsideMoons;

		internal static Dictionary<string, float> decreasingOxygenInFactoryMoons;

		internal static Dictionary<string, float> runningMultiplierMoons;

		internal static Dictionary<string, float> oxygenDepletionInWaterMoons;

		private static string MoonName => Utilities.GetNumberlessPlanetName(StartOfRound.Instance.currentLevel.PlanetName).ToLower();

		internal static bool GreenPlanetsValue => greenPlanets != null && greenPlanets.ContainsKey(MoonName);

		internal static float DecreasingOxygenOutsideMoonsValue => GetValueFromDictionary(decreasingOxygenOutsideMoons, OxygenBase.OxygenConfig.decreasingOxygenOutside.Value);

		internal static float DecreasingOxygenInFactoryMoonsValue => GetValueFromDictionary(decreasingOxygenInFactoryMoons, OxygenBase.OxygenConfig.decreasingOxygenInFactory.Value);

		internal static float RunningMultiplierMoonsValue => GetValueFromDictionary(runningMultiplierMoons, OxygenBase.OxygenConfig.runningMultiplier.Value);

		internal static float OxygenDepletionInWaterMoonsValue => GetValueFromDictionary(oxygenDepletionInWaterMoons, OxygenBase.OxygenConfig.oxygenDepletionInWater.Value);

		private static float GetValueFromDictionary(Dictionary<string, float> dictionary, float defaultValue)
		{
			if (dictionary != null && dictionary.TryGetValue(MoonName, out var value))
			{
				return value;
			}
			return defaultValue;
		}

		internal static void UpdateMoonsValues()
		{
			greenPlanets = GetLevelValue(OxygenBase.OxygenConfig.greenPlanets.Value, 0f, "greenPlanets");
			decreasingOxygenOutsideMoons = GetLevelValue(OxygenBase.OxygenConfig.decreasingOxygenOutsideMoons.Value, OxygenBase.OxygenConfig.decreasingOxygenOutside.Value, "decreasingOxygenOutsideMoons");
			decreasingOxygenInFactoryMoons = GetLevelValue(OxygenBase.OxygenConfig.decreasingOxygenInFactoryMoons.Value, OxygenBase.OxygenConfig.decreasingOxygenInFactory.Value, "decreasingOxygenInFactoryMoons");
			runningMultiplierMoons = GetLevelValue(OxygenBase.OxygenConfig.runningMultiplierMoons.Value, OxygenBase.OxygenConfig.runningMultiplier.Value, "runningMultiplierMoons");
			oxygenDepletionInWaterMoons = GetLevelValue(OxygenBase.OxygenConfig.oxygenDepletionInWaterMoons.Value, OxygenBase.OxygenConfig.oxygenDepletionInWater.Value, "oxygenDepletionInWaterMoons");
		}

		private static Dictionary<string, float> GetLevelValue(string str, float defValue, string nameOfVariable)
		{
			Dictionary<string, float> dictionary = new Dictionary<string, float>();
			dictionary.Add("default", defValue);
			if (string.IsNullOrEmpty(str))
			{
				return dictionary;
			}
			str = str.Replace(" ", string.Empty).ToString(cultureInfo);
			mls.LogInfo((object)("Processing the variable " + nameOfVariable + ":\n" + str));
			string[] array = str.Split(';');
			foreach (string text in array)
			{
				if (!text.Contains("@"))
				{
					dictionary.Add(text.ToLower().Replace(" ", string.Empty), defValue);
					continue;
				}
				string[] array2 = text.Split('@');
				string text2 = array2[0].ToLower().Replace(" ", string.Empty);
				if (array2[1].Contains(","))
				{
					mls.LogWarning((object)("Found a comma in " + nameOfVariable + "! Change it to a period, please."));
					array2[1] = array2[1].Replace(',', '.');
				}
				if (float.TryParse(array2[1], NumberStyles.Float, cultureInfo, out var result))
				{
					mls.LogInfo((object)$"Parsed {result} for {text2}");
					dictionary.Add(text2, result);
					continue;
				}
				mls.LogError((object)$"Failed to parse {result} for {text2}, using default one: {defValue}.\nYou should check the syntax in the variable {nameOfVariable} in the config!");
				dictionary.Add(text2, defValue);
			}
			return dictionary;
		}
	}
	[DataContract]
	public class OxygenConfig : SyncedConfig2<OxygenConfig>
	{
		public enum AutoFillingOnShip
		{
			WhenDoorsClosed,
			WhenPlayerOnShip,
			Off
		}

		public static readonly ManualLogSource mls = Logger.CreateLogSource("Oxygen > OxygenConfig");

		internal ConfigEntry<bool> accurateMeter;

		internal ConfigEntry<bool> autoHideHUD;

		internal ConfigEntry<float> autoHideHUD_value;

		[SyncedEntryField]
		internal SyncedEntry<AutoFillingOnShip> autoFillingOnShip;

		[SyncedEntryField]
		internal SyncedEntry<float> autoFillingOnShip_increasingOxygen;

		[SyncedEntryField]
		internal SyncedEntry<bool> recoverOxygen_ShipLeft;

		[SyncedEntryField]
		internal SyncedEntry<bool> recoverOxygen_StartOfRound;

		[SyncedEntryField]
		internal SyncedEntry<float> secTimer;

		[SyncedEntryField]
		internal SyncedEntry<int> playerDamage;

		[SyncedEntryField]
		internal SyncedEntry<string> greenPlanets;

		[SyncedEntryField]
		internal SyncedEntry<float> decreasingOxygenOutside;

		[SyncedEntryField]
		internal SyncedEntry<float> decreasingOxygenInFactory;

		[SyncedEntryField]
		internal SyncedEntry<string> decreasingOxygenOutsideMoons;

		[SyncedEntryField]
		internal SyncedEntry<string> decreasingOxygenInFactoryMoons;

		[SyncedEntryField]
		internal SyncedEntry<float> runningMultiplier;

		[SyncedEntryField]
		internal SyncedEntry<string> runningMultiplierMoons;

		[SyncedEntryField]
		internal SyncedEntry<float> oxygenDepletionInWater;

		[SyncedEntryField]
		internal SyncedEntry<string> oxygenDepletionInWaterMoons;

		[SyncedEntryField]
		internal SyncedEntry<float> decreasingInFear;

		[SyncedEntryField]
		internal SyncedEntry<float> oxygenDeficiency;

		[SyncedEntryField]
		internal SyncedEntry<bool> infinityOxygenInModsPlaces;

		internal ConfigEntry<bool> shyHUDSupport;

		[SyncedEntryField]
		internal SyncedEntry<bool> immersiveVisorSupport;

		[SyncedEntryField]
		internal SyncedEntry<float> immersiveVisor_OxygenDecreasing;

		[SyncedEntryField]
		internal SyncedEntry<float> oxyBoost_increasingValue;

		[SyncedEntryField]
		internal SyncedEntry<int> oxyBoost_price;

		[SyncedEntryField]
		internal SyncedEntry<bool> oxyCharger_Enabled;

		internal ConfigEntry<float> oxyCharger_SFXVolume;

		internal ConfigEntry<bool> enableOxygenSFX;

		internal ConfigEntry<bool> enableInhaleSFXWhileWalking;

		internal ConfigEntry<bool> enableOxygenSFXInShip;

		internal ConfigEntry<bool> enableOxygenSFXOnTheCompany;

		internal ConfigEntry<float> walkingSFX_volume;

		internal ConfigEntry<float> runningSFX_volume;

		internal ConfigEntry<float> exhaustedSFX_volume;

		internal ConfigEntry<float> scaredSFX_volume;

		[SyncedEntryField]
		internal SyncedEntry<bool> eclipsed_LimitOxygen;

		[SyncedEntryField]
		internal SyncedEntry<float> eclipsed_LimitedOxygenAmount;

		internal ConfigEntry<bool> notifications;

		internal ConfigEntry<int> XOffset;

		internal ConfigEntry<int> YOffset;

		private void BindGeneralEntries(ConfigFile file)
		{
			autoFillingOnShip = SyncedBindingExtensions.BindSyncedEntry<AutoFillingOnShip>(file, "General", "autoFillingOnShip", AutoFillingOnShip.WhenDoorsClosed, "Usually, on the ship, you use oxygen canisters to refill the oxygen, but with this option, you can choose some additional ways.\n\n\"WhenDoorsClosed\" - Auto filling works only if the ship's doors are closed.\n\"WhenPlayerOnShip\" - Works in both situations (doors are open or closed), the player just needs to be on the ship.\n\"Off\" - Disabled.\n\n(syncing with host)");
			autoFillingOnShip_increasingOxygen = SyncedBindingExtensions.BindSyncedEntry<float>(file, "General", "autoFillingOnShip_increasingOxygen", 0.002f, "How fast oxygen should be refilled when 'autoFillingOnShip' is not Off.\n(syncing with host)");
			accurateMeter = file.Bind<bool>("General", "accurateMeter", true, "Whether the oxygen meter ring should be accurate or have vanilla behaviour.");
			autoHideHUD = file.Bind<bool>("General", "autoHideHUD", false, "If true, the oxygen HUD disappears if the oxygen value > 'autoHideHUD_value' setting. \nWorks without installing ShyHUD. If ShyHUD is installed, but this option is not enabled, the HUD won't disappear");
			autoHideHUD_value = file.Bind<float>("General", "autoHideHUD_value", 0.75f, "The oxygen HUD disappears if the oxygen value > 'autoHideHUD_value' setting (value from 0 to 1.0).\nYou can completely hide the oxygen HUD by setting the 'autoHideHUD_value' to 0.\nIf you set the value to 1, this will prevent the oxygen HUD from disappearing.");
			recoverOxygen_ShipLeft = SyncedBindingExtensions.BindSyncedEntry<bool>(file, "General", "recoverOxygen_ShipLeft", true, "If this is set to TRUE, oxygen will be recovered once ship has left.");
			recoverOxygen_StartOfRound = SyncedBindingExtensions.BindSyncedEntry<bool>(file, "General", "recoverOxygen_StartOfRound", true, "If this is set to TRUE, oxygen will be recovered as soon as the round has started.");
			secTimer = SyncedBindingExtensions.BindSyncedEntry<float>(file, "General", "secTimer", 5f, "Every how many seconds should the mod check the player's condition and take away some oxygen.\n(syncing with host)");
			playerDamage = SyncedBindingExtensions.BindSyncedEntry<int>(file, "General", "playerDamage", 15, "Sets how many damage player should get when he has no oxygen.\n(syncing with host)");
		}

		private void BindOxygenEntries(ConfigFile file)
		{
			greenPlanets = SyncedBindingExtensions.BindSyncedEntry<string>(file, "Oxygen", "greenPlanets", "March@0;Vow@0;Gordion@0", "Disables oxygen consumption outside on listed planets. \nOxygen consumption by a player while underwater will still exist. The consumption caused by the damaged helmet (ImmersiveVisor) will be omitted.\nFollow the syntax of the default value.\n(syncing with host)");
			decreasingOxygenOutside = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Oxygen", "decreasingOxygenOutside", 0.0075f, "Indicates how much oxygen is consumed when a player is outside and is triggered every secTimer (config option) seconds.\n(syncing with host)");
			decreasingOxygenOutsideMoons = SyncedBindingExtensions.BindSyncedEntry<string>(file, "Oxygen", "decreasingOxygenOutsideMoons", "[email protected];[email protected];[email protected]", "Indicates how much oxygen is consumed when a player is outside and is triggered every secTimer (config option) seconds.\nThis takes priority over the decreasingOxygenOutside config option.\nNot listed moons will use the decreasingOxygenOutside config option.\n(e.g. [email protected];[email protected];CUSTOM_MOON_NAME@10)\n(syncing with host)");
			decreasingOxygenInFactory = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Oxygen", "decreasingOxygenInFactory", 0.007f, "Indicates how much oxygen is consumed when a player is in the facility and is triggered every secTimer (config option) seconds.\n(syncing with host)");
			decreasingOxygenInFactoryMoons = SyncedBindingExtensions.BindSyncedEntry<string>(file, "Oxygen", "decreasingOxygenInFactoryMoons", "[email protected];[email protected];[email protected]", "Indicates how much oxygen is consumed when a player is in the facility and is triggered every secTimer (config option) seconds.\nThis takes priority over the decreasingOxygenInFactory config option.\nNot listed moons will use the decreasingOxygenInFactory config option.\n(e.g. [email protected];[email protected];CUSTOM_MOON_NAME@10)\n(syncing with host)");
			decreasingInFear = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Oxygen", "decreasingInFear", 0.01f, "Increases oxygen leakage when the player is in fear and is triggered every 2 seconds.\n(syncing with host)");
			runningMultiplier = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Oxygen", "runningMultiplier", 1f, "Multiplies oxygen drain when player is running.\n(syncing with host)");
			runningMultiplierMoons = SyncedBindingExtensions.BindSyncedEntry<string>(file, "Oxygen", "runningMultiplierMoons", "[email protected];[email protected];[email protected]", "Multiplies oxygen drain when player is running.\nThis takes priority over the 'runningMultiplier' config option.\nNot listed moons will use the 'runningMultiplier' config option.\n(e.g. [email protected];[email protected];CUSTOM_MOON_NAME@10)\n(syncing with host)");
			oxygenDepletionInWater = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Oxygen", "oxygenDepletionInWater", 0.018f, "Increases oxygen consumption when the player is underwater and is triggered every secTimer (config option) seconds.\n(syncing with host)");
			oxygenDepletionInWaterMoons = SyncedBindingExtensions.BindSyncedEntry<string>(file, "Oxygen", "oxygenDepletionInWaterMoons", string.Empty, "Increases oxygen consumption when the player is underwater and is triggered every secTimer (config option) seconds.\nThis takes priority over the oxygenDepletionInWater config option.\nNot listed moons will use the oxygenDepletionInWater config option.\n(e.g. [email protected];[email protected];CUSTOM_MOON_NAME@10)\n(syncing with host)");
			oxygenDeficiency = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Oxygen", "oxygenDeficiency", 0.15f, "Increases screen fog when the player runs out of oxygen.\nDepends on the secTimer variable.\n(syncing with host)");
		}

		private void BindCompatibilitiesEntries(ConfigFile file)
		{
			infinityOxygenInModsPlaces = SyncedBindingExtensions.BindSyncedEntry<bool>(file, "Compatibility", "InfinityOxygenInModsPlaces", true, "Oxygen becomes infinite when the player teleports to mod's places to simplificate gameplay.\n(syncing with host)");
			immersiveVisorSupport = SyncedBindingExtensions.BindSyncedEntry<bool>(file, "Compatibility", "ImmersiveVisorSupport", true, "Enables oxygen consumption when the helmet's crack level is 2.\n(syncing with host)");
			immersiveVisor_OxygenDecreasing = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Compatibility", "ImmersiveVisor_OxygenDecreasing", 0.002f, "How much additional oxygen will be consumed if the helmet's crack level is 2?\nDepends on the secTimer variable.\n(syncing with host)");
		}

		private void BindOxyBoostEntries(ConfigFile file)
		{
			oxyBoost_increasingValue = SyncedBindingExtensions.BindSyncedEntry<float>(file, "OxyBoost", "OxyBoost_increasingValue", 0.001f, "How much oxygen does OxyBoost add to the player.\n(syncing with host)");
			oxyBoost_price = SyncedBindingExtensions.BindSyncedEntry<int>(file, "OxyBoost", "OxyBoost_price", 70, "OxyBoost's price.\n(syncing with host)");
		}

		private void BindOxyChargerEntries(ConfigFile file)
		{
			oxyCharger_Enabled = SyncedBindingExtensions.BindSyncedEntry<bool>(file, "OxyCharger", "EnableOxyCharger", true, "Should the oxyCharger be enabled? (oxygen canisters on the ship)\n(syncing with host)");
			oxyCharger_SFXVolume = file.Bind<float>("OxyCharger", "oxyCharger_SFXVolume", 1f, "OxyCharger's SFX volume");
		}

		private void BindSoundsEntries(ConfigFile file)
		{
			enableOxygenSFX = file.Bind<bool>("Sounds", "enableOxygenSFX", true, "Enables oxygen inhalation sounds.");
			enableInhaleSFXWhileWalking = file.Bind<bool>("Sounds", "enableInhaleSFXWhileWalking", true, "Enables oxygen inhalation sounds while walking.");
			enableOxygenSFXInShip = file.Bind<bool>("Sounds", "enableOxygenSFXInShip", false, "Remains oxygen inhalation sounds when player in ship.\nWorks if enableOxygenSFX variable is enabled.");
			enableOxygenSFXOnTheCompany = file.Bind<bool>("Sounds", "enableOxygenSFXOnTheCompany", false, "Remains oxygen inhalation sounds when player on the Gordion (The Company) planet.\nWorks if enableOxygenSFX variable is enabled.");
			walkingSFX_volume = file.Bind<float>("Sounds", "walkingSFX_volume", 0.9f, "volume of walking SFX.");
			runningSFX_volume = file.Bind<float>("Sounds", "runningSFX_volume", 1f, "volume of running SFX.");
			exhaustedSFX_volume = file.Bind<float>("Sounds", "exhaustedSFX_volume", 0.3f, "volume of exhausted SFX.");
			scaredSFX_volume = file.Bind<float>("Sounds", "scaredSFX_volume", 1f, "volume of scared SFX.");
		}

		private void BindWeatherComplicationsEntries(ConfigFile file)
		{
			eclipsed_LimitOxygen = SyncedBindingExtensions.BindSyncedEntry<bool>(file, "Weather Complications", "LimitOxygenOnEclipsed", true, "The oxygen recovery ability will be limited by 'oxyCharger_RemainedOxygenAmount' option if the weather on the current level is eclipsed.\n(syncing with host)");
			eclipsed_LimitedOxygenAmount = SyncedBindingExtensions.BindSyncedEntry<float>(file, "Weather Complications", "LimitedOxygenAmountOnEclipsed", 10f, "How much oxygen you will have in such rounds if \"eclipsed_LimitOxygen\" is enabled.\n(syncing with host)");
		}

		private void BindOtherEntries(ConfigFile file)
		{
			notifications = file.Bind<bool>("Other", "notifications", true, "Should the mod notify you when oxygen is getting low?");
			XOffset = file.Bind<int>("Other", "XOffset", 0, "Horizontal offset for the oxygenHUD position.");
			YOffset = file.Bind<int>("Other", "YOffset", 0, "Vertical offset for the oxygenHUD position.");
		}

		private void RemoveOldConfigEntries(ConfigFile cfg)
		{
			mls.LogInfo((object)"Looking for outdated entries in the config.");
			PropertyInfo property = ((object)cfg).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic);
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(cfg, null);
			foreach (KeyValuePair<ConfigDefinition, string> item in dictionary)
			{
				mls.LogDebug((object)(item.Key.Section + " | " + ((object)item.Key)?.ToString() + " | " + item.Value));
				if (item.Key.Key == "MakeItVanilla" && item.Key.Section == "Oxygen")
				{
					mls.LogWarning((object)"Found old \"MakeItVanilla\". Moving the value to the new entry \"autoFillingOnShip\".");
					if (int.TryParse(item.Value, out var result))
					{
						autoFillingOnShip_increasingOxygen.LocalValue = result;
						switch (result)
						{
						case 0:
							autoFillingOnShip.LocalValue = AutoFillingOnShip.Off;
							break;
						case 1:
							autoFillingOnShip.LocalValue = AutoFillingOnShip.WhenDoorsClosed;
							break;
						default:
							autoFillingOnShip.LocalValue = AutoFillingOnShip.WhenPlayerOnShip;
							break;
						}
					}
				}
				if (item.Key.Key == "increasingOxygen" && item.Key.Section == "Oxygen")
				{
					mls.LogWarning((object)"Found old \"increasingOxygen\". Moving the value to the new entry \"autoFillingOnShip_increasingOxygen\".");
					if (float.TryParse(item.Value, out var result2))
					{
						autoFillingOnShip_increasingOxygen.LocalValue = result2;
					}
				}
				if (item.Key.Key == "recoverOxygenOnceShipLeft" && item.Key.Section == "General")
				{
					mls.LogWarning((object)"Found old \"recoverOxygenOnceShipLeft\". Moving the value to the new entry \"recoverOxygen_ShipLeft\".");
					if (bool.TryParse(item.Value, out var result3))
					{
						recoverOxygen_ShipLeft.LocalValue = result3;
					}
				}
				if (item.Key.Key == "playerDamage" && item.Key.Section == "Player")
				{
					mls.LogWarning((object)"Found old \"playerDamage\". Moving the entry to the new section \"General\".");
					if (int.TryParse(item.Value, out var result4))
					{
						playerDamage.LocalValue = result4;
					}
				}
				if (item.Key.Key == "oxyCharger_SFXVolume" && item.Key.Section == "Sounds")
				{
					mls.LogWarning((object)"Found old \"oxyCharger_SFXVolume\". Moving the entry to the new section \"OxyCharger\".");
					if (int.TryParse(item.Value, out var result5))
					{
						oxyCharger_SFXVolume.Value = result5;
					}
				}
				if (item.Key.Key == "notifications" && item.Key.Section == "Notifications")
				{
					mls.LogWarning((object)"Found old \"notifications\". Moving the entry to the new section \"Other\".");
					if (bool.TryParse(item.Value, out var result6))
					{
						notifications.Value = result6;
					}
				}
				if (item.Key.Key == "XOffset" && item.Key.Section == "Position")
				{
					mls.LogWarning((object)"Found old \"XOffset\". Moving the entry to the new section \"Other\".");
					if (int.TryParse(item.Value, out var result7))
					{
						XOffset.Value = result7;
					}
				}
				if (item.Key.Key == "YOffset" && item.Key.Section == "Position")
				{
					mls.LogWarning((object)"Found old \"YOffset\". Moving the entry to the new section \"Other\".");
					if (int.TryParse(item.Value, out var result8))
					{
						YOffset.Value = result8;
					}
				}
			}
			dictionary.Clear();
			cfg.Save();
		}

		private void DoSomethingAfterSync(object s, EventArgs e)
		{
			mls.LogInfo((object)"Config was synced, updating moons value!");
			MoonsDicts.UpdateMoonsValues();
			if (oxyBoost_price.Value != oxyBoost_price.LocalValue)
			{
				mls.LogInfo((object)"Updating price for OxyBoost");
				OxygenBase.UpdateCustomItemPrice(OxygenBase.Instance.oxyBoost, oxyBoost_price.Value);
			}
		}

		public OxygenConfig(ConfigFile file)
			: base("consequential.Oxygen")
		{
			base.InitialSyncCompleted += DoSomethingAfterSync;
			BindGeneralEntries(file);
			BindOxygenEntries(file);
			BindSoundsEntries(file);
			BindCompatibilitiesEntries(file);
			BindOxyBoostEntries(file);
			BindOxyChargerEntries(file);
			BindWeatherComplicationsEntries(file);
			BindOtherEntries(file);
			RemoveOldConfigEntries(file);
			ConfigManager.Register<OxygenConfig>((SyncedConfig2<OxygenConfig>)this);
		}
	}
}
namespace System.Diagnostics.CodeAnalysis
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ExperimentalAttribute : Attribute
	{
		public string DiagnosticId { get; }

		public string? UrlFormat { get; set; }

		public ExperimentalAttribute(string diagnosticId)
		{
			DiagnosticId = diagnosticId;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullAttribute : Attribute
	{
		public string[] Members { get; }

		public MemberNotNullAttribute(string member)
		{
			Members = new string[1] { member };
		}

		public MemberNotNullAttribute(params string[] members)
		{
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
	[ExcludeFromCodeCoverage]
	internal sealed class MemberNotNullWhenAttribute : Attribute
	{
		public bool ReturnValue { get; }

		public string[] Members { get; }

		public MemberNotNullWhenAttribute(bool returnValue, string member)
		{
			ReturnValue = returnValue;
			Members = new string[1] { member };
		}

		public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
		{
			ReturnValue = returnValue;
			Members = members;
		}
	}
	[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SetsRequiredMembersAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class StringSyntaxAttribute : Attribute
	{
		public const string CompositeFormat = "CompositeFormat";

		public const string DateOnlyFormat = "DateOnlyFormat";

		public const string DateTimeFormat = "DateTimeFormat";

		public const string EnumFormat = "EnumFormat";

		public const string GuidFormat = "GuidFormat";

		public const string Json = "Json";

		public const string NumericFormat = "NumericFormat";

		public const string Regex = "Regex";

		public const string TimeOnlyFormat = "TimeOnlyFormat";

		public const string TimeSpanFormat = "TimeSpanFormat";

		public const string Uri = "Uri";

		public const string Xml = "Xml";

		public string Syntax { get; }

		public object?[] Arguments { get; }

		public StringSyntaxAttribute(string syntax)
		{
			Syntax = syntax;
			Arguments = new object[0];
		}

		public StringSyntaxAttribute(string syntax, params object?[] arguments)
		{
			Syntax = syntax;
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class UnscopedRefAttribute : Attribute
	{
	}
}
namespace System.Runtime.Versioning
{
	[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresPreviewFeaturesAttribute : Attribute
	{
		public string? Message { get; }

		public string? Url { get; set; }

		public RequiresPreviewFeaturesAttribute()
		{
		}

		public RequiresPreviewFeaturesAttribute(string? message)
		{
			Message = message;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CallerArgumentExpressionAttribute : Attribute
	{
		public string ParameterName { get; }

		public CallerArgumentExpressionAttribute(string parameterName)
		{
			ParameterName = parameterName;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CollectionBuilderAttribute : Attribute
	{
		public Type BuilderType { get; }

		public string MethodName { get; }

		public CollectionBuilderAttribute(Type builderType, string methodName)
		{
			BuilderType = builderType;
			MethodName = methodName;
		}
	}
	[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class CompilerFeatureRequiredAttribute : Attribute
	{
		public const string RefStructs = "RefStructs";

		public const string RequiredMembers = "RequiredMembers";

		public string FeatureName { get; }

		public bool IsOptional { get; set; }

		public CompilerFeatureRequiredAttribute(string featureName)
		{
			FeatureName = featureName;
		}
	}
	[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerArgumentAttribute : Attribute
	{
		public string[] Arguments { get; }

		public InterpolatedStringHandlerArgumentAttribute(string argument)
		{
			Arguments = new string[1] { argument };
		}

		public InterpolatedStringHandlerArgumentAttribute(params string[] arguments)
		{
			Arguments = arguments;
		}
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class InterpolatedStringHandlerAttribute : Attribute
	{
	}
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Method, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class ModuleInitializerAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiredMemberAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
	[EditorBrowsable(EditorBrowsableState.Never)]
	[ExcludeFromCodeCoverage]
	internal sealed class RequiresLocationAttribute : Attribute
	{
	}
	[AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)]
	[ExcludeFromCodeCoverage]
	internal sealed class SkipLocalsInitAttribute : Attribute
	{
	}
}
namespace Oxygen.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}