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.");
}
}
}