Decompiled source of qMassControlls v1.0.0

qMassControlls.dll

Decompiled 19 hours ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[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("qMassControlls")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("qMassControlls")]
[assembly: AssemblyTitle("qMassControlls")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 qMassControlls
{
	[HarmonyPatch(typeof(DEN_DeathFloor), "Update")]
	internal static class MassPatch
	{
		internal class Defaults
		{
			public float speed;

			public float maxSpeed;

			public float speedIncreaseRate;

			public float rubberbandMult;

			public float startHeight;

			public float easeHeight;

			public float volume;

			public float closeShake;

			public float roarShake;
		}

		private static readonly FieldRef<DEN_DeathFloor, bool> canKill = AccessTools.FieldRefAccess<DEN_DeathFloor, bool>("canKill");

		private static readonly FieldRef<DEN_DeathFloor, bool> rubberbandActive = AccessTools.FieldRefAccess<DEN_DeathFloor, bool>("rubberbandActive");

		internal static DEN_DeathFloor Current;

		internal static Defaults Def;

		private static bool touchedKill;

		private static bool touchedRubber;

		private static bool touchedSpeed;

		private static bool touchedMax;

		private static bool touchedStart;

		private static bool touchedEase;

		private static bool touchedMults;

		private static void Capture(DEN_DeathFloor m)
		{
			Current = m;
			Def = new Defaults
			{
				speed = m.speed,
				maxSpeed = m.maxSpeed,
				speedIncreaseRate = m.speedIncreaseRate,
				rubberbandMult = m.rubberbandMult,
				startHeight = m.playerStartHeight,
				easeHeight = m.playerEaseHeight,
				volume = m.globalVolume,
				closeShake = m.closeScreenShake,
				roarShake = m.roarShake
			};
			touchedKill = (touchedRubber = (touchedSpeed = (touchedMax = (touchedStart = (touchedEase = (touchedMults = false))))));
		}

		[HarmonyPriority(200)]
		private static void Prefix(DEN_DeathFloor __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Current)
			{
				Capture(__instance);
			}
			if (!Plugin.Enabled.Value)
			{
				RestoreAll(__instance);
				return;
			}
			Toggle(ref touchedKill, !Plugin.CanKill.Value, delegate
			{
				canKill.Invoke(__instance) = false;
			}, delegate
			{
				canKill.Invoke(__instance) = true;
			});
			Toggle(ref touchedRubber, !Plugin.Rubberband.Value, delegate
			{
				rubberbandActive.Invoke(__instance) = false;
			}, delegate
			{
				rubberbandActive.Invoke(__instance) = true;
			});
			Toggle(ref touchedSpeed, Plugin.BaseSpeed.On.Value, delegate
			{
				__instance.speed = Plugin.BaseSpeed.Value.Value;
			}, delegate
			{
			});
			Toggle(ref touchedMax, Plugin.MaxSpeed.On.Value, delegate
			{
				__instance.maxSpeed = Plugin.MaxSpeed.Value.Value;
			}, delegate
			{
				__instance.maxSpeed = Def.maxSpeed;
			});
			Toggle(ref touchedStart, Plugin.StartDistance.On.Value, delegate
			{
				__instance.playerStartHeight = Plugin.StartDistance.Value.Value;
			}, delegate
			{
				__instance.playerStartHeight = Def.startHeight;
			});
			Toggle(ref touchedEase, Plugin.AccelStartDistance.On.Value, delegate
			{
				__instance.playerEaseHeight = Plugin.AccelStartDistance.Value.Value;
			}, delegate
			{
				__instance.playerEaseHeight = Def.easeHeight;
			});
			bool want = Plugin.AccelMult.Value != 1f || Plugin.RubberbandMult.Value != 1f || Plugin.VolumeMult.Value != 1f || Plugin.ShakeMult.Value != 1f;
			Toggle(ref touchedMults, want, delegate
			{
				__instance.speedIncreaseRate = Def.speedIncreaseRate * Plugin.AccelMult.Value;
				__instance.rubberbandMult = Def.rubberbandMult * Plugin.RubberbandMult.Value;
				__instance.globalVolume = Def.volume * Plugin.VolumeMult.Value;
				__instance.closeScreenShake = Def.closeShake * Plugin.ShakeMult.Value;
				__instance.roarShake = Def.roarShake * Plugin.ShakeMult.Value;
			}, delegate
			{
				__instance.speedIncreaseRate = Def.speedIncreaseRate;
				__instance.rubberbandMult = Def.rubberbandMult;
				__instance.globalVolume = Def.volume;
				__instance.closeScreenShake = Def.closeShake;
				__instance.roarShake = Def.roarShake;
			});
			float num = (Plugin.Frozen.Value ? 0f : Plugin.SpeedMult.Value);
			if (num != 1f)
			{
				__instance.SetUpdateSpeedMultiplier(Mathf.Max(0f, num));
			}
		}

		private static void Postfix(DEN_DeathFloor __instance)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			if (!Plugin.Enabled.Value)
			{
				return;
			}
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)playerObject == (Object)null || ((GameEntity)playerObject).IsDead())
			{
				return;
			}
			Vector3 position = ((Component)__instance).transform.position;
			float y = ((Component)playerObject).transform.position.y;
			if (Plugin.MinGap.Value > 0f && position.y > y - Plugin.MinGap.Value)
			{
				position.y = y - Plugin.MinGap.Value;
			}
			else
			{
				if (!(Plugin.MaxGap.Value > 0f) || !(position.y < y - Plugin.MaxGap.Value))
				{
					return;
				}
				position.y = y - Plugin.MaxGap.Value;
			}
			((Component)__instance).transform.position = position;
		}

		private static void Toggle(ref bool touched, bool want, Action apply, Action restore)
		{
			if (want)
			{
				apply();
				touched = true;
			}
			else if (touched)
			{
				restore();
				touched = false;
			}
		}

		private static void RestoreAll(DEN_DeathFloor m)
		{
			Toggle(ref touchedKill, want: false, null, delegate
			{
				canKill.Invoke(m) = true;
			});
			Toggle(ref touchedRubber, want: false, null, delegate
			{
				rubberbandActive.Invoke(m) = true;
			});
			Toggle(ref touchedSpeed, want: false, null, delegate
			{
			});
			Toggle(ref touchedMax, want: false, null, delegate
			{
				m.maxSpeed = Def.maxSpeed;
			});
			Toggle(ref touchedStart, want: false, null, delegate
			{
				m.playerStartHeight = Def.startHeight;
			});
			Toggle(ref touchedEase, want: false, null, delegate
			{
				m.playerEaseHeight = Def.easeHeight;
			});
			Toggle(ref touchedMults, want: false, null, delegate
			{
				m.speedIncreaseRate = Def.speedIncreaseRate;
				m.rubberbandMult = Def.rubberbandMult;
				m.globalVolume = Def.volume;
				m.closeScreenShake = Def.closeShake;
				m.roarShake = Def.roarShake;
			});
		}

		internal static void PlaceBelow(float meters)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			ENT_Player playerObject = ENT_Player.playerObject;
			if (!((Object)(object)Current == (Object)null) && !((Object)(object)playerObject == (Object)null))
			{
				((Component)Current).transform.position = ((Component)playerObject).transform.position - Vector3.up * meters;
			}
		}
	}
	internal class MassWindow : MonoBehaviour
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static UnityAction <0>__Toggle;
		}

		private static MassWindow instance;

		private bool open;

		private Rect rect = new Rect(60f, 60f, 460f, 640f);

		private Vector2 scroll;

		public static void Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("qMassControllsWindow");
			Object.DontDestroyOnLoad((Object)val);
			((Object)val).hideFlags = (HideFlags)61;
			instance = val.AddComponent<MassWindow>();
		}

		public static void Toggle()
		{
			instance?.SetOpen(!instance.open);
		}

		private void SetOpen(bool value)
		{
			open = value;
			if (open)
			{
				CL_GameManager gMan = CL_GameManager.gMan;
				if ((Object)(object)gMan != (Object)null && (Object)(object)ENT_Player.playerObject != (Object)null && !gMan.isPaused && !((GameEntity)ENT_Player.playerObject).IsDead())
				{
					gMan.Pause();
				}
			}
			else
			{
				Plugin.Cfg.Save();
			}
		}

		private void Update()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			if (Input.GetKeyDown(Plugin.MenuKey.Value))
			{
				Toggle();
			}
			if (open && Input.GetKeyDown((KeyCode)27))
			{
				SetOpen(value: false);
			}
		}

		private void LateUpdate()
		{
			if (open)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void OnGUI()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			if (open)
			{
				GUI.depth = -1000;
				rect = GUILayout.Window(1835103091, rect, new WindowFunction(Draw), "qMassControlls — the mass", Array.Empty<GUILayoutOption>());
			}
		}

		private void Draw(int id)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
			Bool(Plugin.Enabled, "Mod enabled (off = vanilla mass)");
			GUILayout.Space(6f);
			Bool(Plugin.Frozen, "Freeze the mass");
			Bool(Plugin.CanKill, "The mass can kill");
			Header("Speed");
			Float(Plugin.SpeedMult, "Speed multiplier", 0f, 20f);
			Override(Plugin.BaseSpeed, "Base speed (m/s)", 0f, 50f);
			Override(Plugin.MaxSpeed, "Max natural speed (m/s)", 0f, 100f);
			Float(Plugin.AccelMult, "Speed growth multiplier", 0f, 50f);
			Header("Catch-up");
			Bool(Plugin.Rubberband, "Rubber-band (faster when you're far above)");
			Float(Plugin.RubberbandMult, "Rubber-band strength", 0f, 10f);
			Float(Plugin.MinGap, "Keep at least N m below you (0 = off)", 0f, 200f);
			Float(Plugin.MaxGap, "Never further than N m below you (0 = off)", 0f, 500f);
			Header("Start");
			Override(Plugin.StartDistance, "Climb before it starts rising (m)", 0f, 500f);
			Override(Plugin.AccelStartDistance, "Climb before it speeds up (m)", 0f, 2000f);
			Header("Feel");
			Float(Plugin.VolumeMult, "Sound volume", 0f, 3f);
			Float(Plugin.ShakeMult, "Screen shake", 0f, 5f);
			Header("Live");
			DEN_DeathFloor current = MassPatch.Current;
			ENT_Player playerObject = ENT_Player.playerObject;
			if ((Object)(object)current != (Object)null && (Object)(object)playerObject != (Object)null)
			{
				GUILayout.Label($"Natural speed: {current.speed:0.00} m/s   (game default {MassPatch.Def.speed:0.00})", Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Distance below you: {((Component)playerObject).transform.position.y - ((Component)current).transform.position.y:0.0} m", Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Put 10 m below", Array.Empty<GUILayoutOption>()))
				{
					MassPatch.PlaceBelow(10f);
				}
				if (GUILayout.Button("Put 50 m below", Array.Empty<GUILayoutOption>()))
				{
					MassPatch.PlaceBelow(50f);
				}
				if (GUILayout.Button("Put 200 m below", Array.Empty<GUILayoutOption>()))
				{
					MassPatch.PlaceBelow(200f);
				}
				GUILayout.EndHorizontal();
			}
			else
			{
				GUILayout.Label("No mass right now. Settings apply when a run starts.", Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.Space(4f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Reset all to game defaults", Array.Empty<GUILayoutOption>()))
			{
				ResetAll();
			}
			if (GUILayout.Button("Close", Array.Empty<GUILayoutOption>()))
			{
				SetOpen(value: false);
			}
			GUILayout.EndHorizontal();
			GUI.DragWindow();
		}

		private static void Header(string text)
		{
			GUILayout.Space(8f);
			GUILayout.Label("<b>" + text + "</b>", Array.Empty<GUILayoutOption>());
		}

		private static void Bool(ConfigEntry<bool> e, string label)
		{
			e.Value = GUILayout.Toggle(e.Value, " " + label, Array.Empty<GUILayoutOption>());
		}

		private static void Float(ConfigEntry<float> e, string label, float min, float max)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(250f) });
			GUILayout.Label(e.Value.ToString("0.###"), (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (GUILayout.Button("↺", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(26f) }))
			{
				e.Value = (float)((ConfigEntryBase)e).DefaultValue;
			}
			GUILayout.EndHorizontal();
			float num = GUILayout.HorizontalSlider(e.Value, min, max, Array.Empty<GUILayoutOption>());
			if (num != e.Value)
			{
				e.Value = Mathf.Round(num * 100f) / 100f;
			}
		}

		private static void Override(Knob k, string label, float min, float max)
		{
			Bool(k.On, "Custom " + label.ToLowerInvariant());
			if (k.On.Value)
			{
				Float(k.Value, label, min, max);
			}
		}

		private static void ResetAll()
		{
			foreach (ConfigDefinition key in Plugin.Cfg.Keys)
			{
				if (!(key.Section != "Mass"))
				{
					ConfigEntryBase obj = Plugin.Cfg[key];
					obj.BoxedValue = obj.DefaultValue;
				}
			}
		}

		internal static void AddMenuButton()
		{
			//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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			Button val = null;
			Button[] array = Object.FindObjectsByType<Button>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			foreach (Button val2 in array)
			{
				if (GetText(((Component)val2).gameObject)?.Trim().ToLowerInvariant() == "play")
				{
					val = val2;
					break;
				}
			}
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogWarning((object)("Play button not found; use " + ((object)Plugin.MenuKey.Value/*cast due to .constrained prefix*/).ToString() + " to open the mass settings."));
				return;
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent);
			((Object)val3).name = "qMassControllsButton";
			val3.transform.SetSiblingIndex(((Component)val).transform.GetSiblingIndex() + 1);
			MonoBehaviour[] componentsInChildren = val3.GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val4 in componentsInChildren)
			{
				string name = ((object)val4).GetType().Name;
				if (val4 is UI_MenuButton || name.Contains("Locali") || name.Contains("Translat"))
				{
					Object.DestroyImmediate((Object)(object)val4);
				}
			}
			Button component = val3.GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			ButtonClickedEvent onClick = component.onClick;
			object obj = <>O.<0>__Toggle;
			if (obj == null)
			{
				UnityAction val5 = Toggle;
				<>O.<0>__Toggle = val5;
				obj = (object)val5;
			}
			((UnityEvent)onClick).AddListener((UnityAction)obj);
			SetText(val3, "MASS");
			if ((Object)(object)((Component)((Component)val).transform.parent).GetComponent<LayoutGroup>() == (Object)null)
			{
				Transform transform = val3.transform;
				RectTransform val6 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				if (val6 != null)
				{
					Vector2 anchoredPosition = val6.anchoredPosition;
					Rect val7 = val6.rect;
					val6.anchoredPosition = anchoredPosition + new Vector2(0f, (0f - ((Rect)(ref val7)).height) * 1.1f);
				}
			}
		}

		private static string GetText(GameObject go)
		{
			Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				PropertyInfo propertyInfo = TextProp(val);
				if (propertyInfo != null)
				{
					return propertyInfo.GetValue(val) as string;
				}
			}
			return null;
		}

		private static void SetText(GameObject go, string text)
		{
			Component[] componentsInChildren = go.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				TextProp(val)?.SetValue(val, text);
			}
		}

		private static PropertyInfo TextProp(Component c)
		{
			if ((Object)(object)c == (Object)null || !(c is Graphic))
			{
				return null;
			}
			PropertyInfo property = ((object)c).GetType().GetProperty("text", typeof(string));
			if (!(property != null) || !property.CanWrite)
			{
				return null;
			}
			return property;
		}
	}
	[HarmonyPatch(typeof(MenuManager), "Start")]
	internal static class MenuPatch
	{
		private static void Postfix()
		{
			try
			{
				MassWindow.AddMenuButton();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not add the MASS button: " + ex));
			}
		}
	}
	[BepInPlugin("q.whiteknuckle.masscontrolls", "qMassControlls", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "q.whiteknuckle.masscontrolls";

		public const string Name = "qMassControlls";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigFile Cfg;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyCode> MenuKey;

		internal static ConfigEntry<bool> Frozen;

		internal static ConfigEntry<bool> CanKill;

		internal static ConfigEntry<bool> Rubberband;

		internal static ConfigEntry<float> SpeedMult;

		internal static ConfigEntry<float> AccelMult;

		internal static ConfigEntry<float> RubberbandMult;

		internal static ConfigEntry<float> VolumeMult;

		internal static ConfigEntry<float> ShakeMult;

		internal static ConfigEntry<float> MinGap;

		internal static ConfigEntry<float> MaxGap;

		internal static Knob BaseSpeed;

		internal static Knob MaxSpeed;

		internal static Knob StartDistance;

		internal static Knob AccelStartDistance;

		private void Awake()
		{
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg = ((BaseUnityPlugin)this).Config;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "When off, the mod leaves the mass completely alone.");
			MenuKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "MenuKey", (KeyCode)289, "Opens the mass settings window anywhere (main menu, pause menu, in a run).");
			Frozen = ((BaseUnityPlugin)this).Config.Bind<bool>("Mass", "Frozen", false, "The mass stops rising (it can still kill you if you go below it).");
			CanKill = ((BaseUnityPlugin)this).Config.Bind<bool>("Mass", "CanKill", true, "When off, touching the mass does not kill you.");
			SpeedMult = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "SpeedMult", 1f, "Multiplies the mass's current rising speed.");
			AccelMult = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "AccelMult", 1f, "Multiplies how fast the mass's speed grows over the run.");
			Rubberband = ((BaseUnityPlugin)this).Config.Bind<bool>("Mass", "Rubberband", true, "The mass speeds up when you are far above it.");
			RubberbandMult = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "RubberbandMult", 1f, "Strength of the rubber-band catch-up.");
			MinGap = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "MinGap", 0f, "Keep the mass at least this many meters below you (0 = off).");
			MaxGap = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "MaxGap", 0f, "The mass is never further than this many meters below you (0 = off). Makes it hunt you.");
			VolumeMult = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "VolumeMult", 1f, "Volume of the mass's sounds.");
			ShakeMult = ((BaseUnityPlugin)this).Config.Bind<float>("Mass", "ShakeMult", 1f, "Screen shake from the mass (roar and when it's close).");
			BaseSpeed = new Knob(((BaseUnityPlugin)this).Config, "Mass", "BaseSpeed", 1f, "The mass's natural speed (m/s). It grows over time up to MaxSpeed.");
			MaxSpeed = new Knob(((BaseUnityPlugin)this).Config, "Mass", "MaxSpeed", 2f, "The highest natural speed the mass grows to.");
			StartDistance = new Knob(((BaseUnityPlugin)this).Config, "Mass", "StartDistance", 16f, "How far you must climb before the mass starts rising.");
			AccelStartDistance = new Knob(((BaseUnityPlugin)this).Config, "Mass", "AccelStartDistance", 150f, "How far you must climb before the mass starts speeding up.");
			((BaseUnityPlugin)this).Config.Save();
			new Harmony("q.whiteknuckle.masscontrolls").PatchAll();
			MassWindow.Create();
			Log.LogInfo((object)"qMassControlls 1.0.0 loaded.");
		}
	}
	internal class Knob
	{
		public readonly ConfigEntry<bool> On;

		public readonly ConfigEntry<float> Value;

		public readonly string Label;

		public Knob(ConfigFile cfg, string section, string key, float def, string desc)
		{
			Label = key;
			On = cfg.Bind<bool>(section, "Override" + key, false, "Use your own " + key + " instead of the game's.");
			Value = cfg.Bind<float>(section, key, def, desc + " Only used when Override" + key + " is on.");
		}
	}
}