Decompiled source of ScoreLab v1.0.1

PCVR/Mods/ScoreLab.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.Interaction;
using Il2CppSLZ.Marrow.PuppetMasta;
using Il2CppSLZ.Marrow.Utilities;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using NEP.ScoreLab;
using NEP.ScoreLab.Audio;
using NEP.ScoreLab.Core;
using NEP.ScoreLab.Data;
using NEP.ScoreLab.HUD;
using NEP.ScoreLab.Menu;
using NEP.ScoreLab.Patches;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "ScoreLab", "1.0.0", "Not Enough Photons", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ScoreLab")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0140fb38dafe5a3ef9669f29b961df65def51cb4")]
[assembly: AssemblyProduct("ScoreLab")]
[assembly: AssemblyTitle("ScoreLab")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NEP.ScoreLab
{
	public static class BuildInfo
	{
		public const string Name = "ScoreLab";

		public const string Author = "Not Enough Photons";

		public const string Company = "Not Enough Photons";

		public const string Version = "1.0.0";

		public const string DownloadLink = "https://thunderstore.io/c/bonelab/p/NotEnoughPhotons/ScoreLab";
	}
	public class Main : MelonMod
	{
		internal static Instance Logger;

		public override void OnLateInitializeMelon()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			Logger = new Instance("ScoreLab");
			Settings.CreatePreferences();
			Hooks.Initialize();
			Hooks.Game.OnMarrowGameStarted = (Action)Delegate.Combine(Hooks.Game.OnMarrowGameStarted, new Action(OnMarrowGameStarted));
			Hooks.Game.OnMarrowSceneLoaded = (Action<MarrowSceneInfo>)Delegate.Combine(Hooks.Game.OnMarrowSceneLoaded, new Action<MarrowSceneInfo>(OnMarrowSceneLoaded));
			HUDLoader.Initialize();
			SLMenu.Initialize();
		}

		public void OnMarrowGameStarted()
		{
			ScoreTracker.Initialize();
			ValueManager.Initialize();
			AudioManager.Initialize();
			ScoreDirector.Patches.InitPatches();
		}

		public void OnMarrowSceneLoaded(MarrowSceneInfo sceneInfo)
		{
			HUDManager.Initialize();
			ScoreTracker.ResetAll();
		}

		public override void OnUpdate()
		{
			ScoreTracker.Update();
		}

		public override void OnDeinitializeMelon()
		{
			HUDManager.Uninitialize();
			AudioManager.Uninitialize();
			Settings.Save();
		}
	}
}
namespace NEP.ScoreLab.Patches
{
	public static class Hooks
	{
		public static class Game
		{
			public static Action OnMarrowGameStarted;

			public static Action<MarrowSceneInfo> OnMarrowSceneLoaded;

			private static MarrowSceneInfo _lastScene;

			private static MarrowSceneInfo _currentScene;

			private static MarrowSceneInfo _nextScene;

			public static void Initialize()
			{
				MarrowGame.RegisterOnReadyAction(Action.op_Implicit((Action)delegate
				{
					OnMarrowGameStarted?.Invoke();
				}));
				Hooking.OnLevelLoaded += OnSceneMarrowLoaded;
			}

			private static void OnSceneMarrowLoaded(LevelInfo info)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				MarrowSceneInfo currentScene = default(MarrowSceneInfo);
				currentScene.Barcode = info.barcode;
				currentScene.LevelTitle = info.title;
				currentScene.MarrowScene = ((CrateReferenceT<LevelCrate>)(object)info.levelReference).Crate.MainScene;
				_currentScene = currentScene;
				_lastScene = _currentScene;
				OnMarrowSceneLoaded?.Invoke(_currentScene);
			}
		}

		public static void Initialize()
		{
			Game.Initialize();
		}
	}
}
namespace NEP.ScoreLab.Menu
{
	public static class SLMenu
	{
		private static Page _hudPage;

		public static void Initialize()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			Page obj = Page.Root.CreatePage("Not Enough Photons", Color.white, 0, true).CreatePage("ScoreLab", Color.white, 0, true);
			_hudPage = obj.CreatePage("HUDs", Color.white, 0, true);
			obj.CreateFloat("HUD Distance", Color.white, 1.125f, 0.025f, 0f, 2f, (Action<float>)delegate(float value)
			{
				Settings.DistanceToCamera = value;
			});
			obj.CreateEnum("Show HUD", Color.white, (Enum)Settings.HUDShowMode, (Action<Enum>)delegate(Enum value)
			{
				Settings.SetHUDShowMode((HUDShowMode)(object)value);
			});
			for (int i = 0; i < HUDLoader.LoadedHUDManifests.Count; i++)
			{
				int index = i;
				JSONHUDManifest manifest = HUDLoader.LoadedHUDManifests[index];
				_hudPage.CreateFunction(manifest.Name, Color.white, (Action)delegate
				{
					HUDManager.LoadHUD(manifest.Name);
				}).Logo = manifest.Logo;
			}
		}

		public static void RefreshHUDPage()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			_hudPage.RemoveAll();
			for (int i = 0; i < HUDLoader.LoadedHUDManifests.Count; i++)
			{
				int index = i;
				JSONHUDManifest manifest = HUDLoader.LoadedHUDManifests[index];
				_hudPage.CreateFunction(manifest.Name, Color.white, (Action)delegate
				{
					HUDManager.LoadHUD(manifest.Name);
				}).Logo = manifest.Logo;
			}
		}
	}
}
namespace NEP.ScoreLab.HUD
{
	public enum HUDShowMode
	{
		Always,
		UpdateOnly,
		Never
	}
	[RegisterTypeInIl2Cpp]
	public class Module : MonoBehaviour
	{
		public enum UIModuleType
		{
			Main,
			Descriptor
		}

		public UIModuleType ModuleType;

		private bool _reachedDecay;

		private bool _reachedPostDecay;

		public PackedValue PackedValue => _packedValue;

		public virtual PackedValue.PackedType PackedType => PackedValue.PackedType.Base;

		public virtual bool CanDecay => (Object)(object)((Component)this).transform.Find("-Persist") == (Object)null;

		public float DecayTime => _decayTime;

		public float PostDecayTime => _postDecayTime;

		protected TextMeshProUGUI _title { get; private set; }

		protected TextMeshProUGUI _value { get; private set; }

		protected Slider _timeBar { get; private set; }

		protected PackedValue _packedValue { get; private set; }

		protected bool _canDecay { get; private set; }

		protected bool _decayed { get; private set; }

		protected float _decayTime { get; private set; }

		protected float _postDecayTime { get; private set; }

		protected float _tDecay { get; private set; }

		protected float _tPostDecay { get; private set; }

		private string Path_Root => ((Object)this).name;

		protected virtual string Path_TitleText => "Title";

		protected virtual string Path_ValueText => "Value";

		protected virtual string Path_TimeBar => "TimeBar";

		public Module(IntPtr ptr)
			: base(ptr)
		{
		}

		public virtual void OnModuleEnable()
		{
			API.UI.OnModuleEnabled?.Invoke(this);
		}

		public virtual void OnModuleDisable()
		{
			API.UI.OnModuleDisabled?.Invoke(this);
		}

		public virtual void OnUpdate()
		{
		}

		public void AssignPackedData(PackedValue packedValue)
		{
			if (packedValue != null)
			{
				_packedValue = packedValue;
				if (_packedValue.DecayTime != 0f)
				{
					SetDecayTime(_packedValue.DecayTime);
				}
			}
		}

		public void SetDecayTime(float decayTime)
		{
			_decayTime = decayTime;
			_tDecay = _decayTime;
		}

		public void SetPostDecayTime(float postDecayTime)
		{
			_postDecayTime = postDecayTime;
			_tPostDecay = _postDecayTime;
		}

		public bool IsDecaying()
		{
			return _reachedDecay;
		}

		public bool IsDecayed()
		{
			return _reachedPostDecay;
		}

		protected void SetText(TextMeshProUGUI text, string value)
		{
			if (!((Object)(object)text == (Object)null))
			{
				((TMP_Text)text).text = value;
			}
		}

		protected void SetText(TextMeshProUGUI text, int value)
		{
			if (!((Object)(object)text == (Object)null))
			{
				SetText(text, value.ToString());
			}
		}

		protected void SetText(TextMeshProUGUI text, float value)
		{
			if (!((Object)(object)text == (Object)null))
			{
				SetText(text, value.ToString());
			}
		}

		protected void SetBarValue(Slider timeBar, float value)
		{
			timeBar.value = value;
		}

		protected void SetMaxValueToBar(Slider timeBar, float value)
		{
			if (!((Object)(object)timeBar == (Object)null))
			{
				timeBar.maxValue = value;
			}
		}

		protected void UpdateDecay()
		{
			if (!CanDecay)
			{
				return;
			}
			if (_tDecay < 0f)
			{
				if (!_reachedDecay)
				{
					API.UI.OnModuleDecayed?.Invoke(this);
					_reachedDecay = true;
				}
				_tPostDecay -= Time.deltaTime;
				if (_tPostDecay < 0f)
				{
					if (!_reachedPostDecay)
					{
						API.UI.OnModulePostDecayed?.Invoke(this);
						_reachedPostDecay = true;
					}
					_tDecay = _decayTime;
					_tPostDecay = _postDecayTime;
					_reachedDecay = false;
					_reachedPostDecay = false;
					((Component)this).gameObject.SetActive(false);
				}
			}
			else
			{
				_tDecay -= Time.deltaTime;
			}
		}

		private void Start()
		{
			Transform val = ((Component)this).transform.Find(Path_TitleText);
			Transform val2 = ((Component)this).transform.Find(Path_ValueText);
			Transform val3 = ((Component)this).transform.Find(Path_TimeBar);
			_title = ((val != null) ? ((Component)val).GetComponent<TextMeshProUGUI>() : null);
			_value = ((val2 != null) ? ((Component)val2).GetComponent<TextMeshProUGUI>() : null);
			_timeBar = ((val3 != null) ? ((Component)val3).GetComponent<Slider>() : null);
		}

		private void OnEnable()
		{
			OnModuleEnable();
		}

		private void OnDisable()
		{
			OnModuleEnable();
		}

		private void Update()
		{
			OnUpdate();
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ModuleAnimator : MonoBehaviour
	{
		public Animator Animator;

		private Module _module;

		public ModuleAnimator(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			_module = ((Component)this).GetComponent<Module>();
			Animator = ((Component)this).GetComponent<Animator>();
		}

		private void OnEnable()
		{
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, (Action<PackedValue>)delegate
			{
				OnTierReached();
			});
			API.UI.OnModuleDecayed = (Action<Module>)Delegate.Combine(API.UI.OnModuleDecayed, new Action<Module>(OnModuleDecayed));
		}

		private void OnDisable()
		{
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, (Action<PackedValue>)delegate
			{
				OnTierReached();
			});
			API.UI.OnModuleDecayed = (Action<Module>)Delegate.Remove(API.UI.OnModuleDecayed, new Action<Module>(OnModuleDecayed));
		}

		private void PlayAnimation(string name)
		{
			if (!((Object)(object)Animator == (Object)null))
			{
				Animator.Play(name, -1, 0f);
			}
		}

		private void OnModuleEnabled(Module module)
		{
			if (!((Object)(object)_module != (Object)(object)module))
			{
				if (_module.ModuleType == Module.UIModuleType.Descriptor)
				{
					PlayAnimation("descriptor_show");
				}
				else
				{
					PlayAnimation("show");
				}
			}
		}

		private void OnTierReached()
		{
			PlayAnimation("tier_reached");
		}

		private void OnModuleDecayed(Module module)
		{
			if (!((Object)(object)_module != (Object)(object)module))
			{
				if (_module.ModuleType == Module.UIModuleType.Descriptor)
				{
					PlayAnimation("descriptor_hide");
				}
				else
				{
					PlayAnimation("hide");
				}
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	public class MultiplierModule : Module
	{
		private float _currentValue;

		private float _targetValue;

		private float _rate;

		private PackedMultiplier _packedMultiplier => (PackedMultiplier)base._packedValue;

		public MultiplierModule(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if (((Object)this).name == "MultiplierDescriptor" || ((Object)this).name == "Descriptor")
			{
				ModuleType = UIModuleType.Descriptor;
			}
		}

		public override void OnModuleEnable()
		{
			base.OnModuleEnable();
			if (base._packedValue == null || _packedMultiplier == null)
			{
				return;
			}
			if (ModuleType == UIModuleType.Main)
			{
				SetText(base._value, ScoreTracker.Multiplier + "x");
			}
			else if (ModuleType == UIModuleType.Descriptor)
			{
				SetText(base._title, _packedMultiplier.Name);
				SetText(base._value, _packedMultiplier.Multiplier + "x");
			}
			if ((Object)(object)base._timeBar != (Object)null)
			{
				if (_packedMultiplier.Condition != string.Empty)
				{
					((Component)base._timeBar).gameObject.SetActive(false);
					return;
				}
				((Component)base._timeBar).gameObject.SetActive(true);
				SetMaxValueToBar(base._timeBar, _packedMultiplier.DecayTime);
				SetBarValue(base._timeBar, _packedMultiplier.DecayTime);
			}
		}

		public override void OnModuleDisable()
		{
		}

		public override void OnUpdate()
		{
			if (ModuleType == UIModuleType.Main)
			{
				SetTweenValue(ScoreTracker.Multiplier);
				_currentValue = Mathf.MoveTowards(_currentValue, _targetValue, _rate * Time.unscaledDeltaTime);
				if (Mathf.Approximately(_currentValue, _targetValue))
				{
					_currentValue = _targetValue;
				}
				SetText(base._value, _currentValue.ToString("F2"));
			}
			if (_packedMultiplier != null)
			{
				if (_packedMultiplier.condition != null)
				{
					if (!_packedMultiplier.condition())
					{
						UpdateDecay();
					}
				}
				else
				{
					UpdateDecay();
				}
			}
			else
			{
				UpdateDecay();
			}
			if ((Object)(object)base._timeBar != (Object)null)
			{
				SetBarValue(base._timeBar, base._tDecay);
			}
		}

		private void SetTweenValue(float value)
		{
			_targetValue = value;
			_rate = Mathf.Abs(_targetValue - _currentValue) / 1f;
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ScoreModule : Module
	{
		private float _targetValue;

		private float _currentValue;

		private float _rate = 4f;

		private PackedScore _packedScore => (PackedScore)base._packedValue;

		public ScoreModule(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if (((Object)this).name == "ScoreDescriptor" || ((Object)this).name == "Descriptor")
			{
				ModuleType = UIModuleType.Descriptor;
			}
		}

		public override void OnModuleEnable()
		{
			base.OnModuleEnable();
			if (ModuleType == UIModuleType.Main)
			{
				SetText(base._value, ScoreTracker.Score);
			}
			if (base._packedValue != null && ModuleType == UIModuleType.Descriptor)
			{
				SetText(base._title, _packedScore.Name);
				SetText(base._value, $"+{Mathf.RoundToInt((float)_packedScore.Score * ScoreTracker.Multiplier)}");
			}
		}

		public override void OnModuleDisable()
		{
		}

		public override void OnUpdate()
		{
			UpdateDecay();
			if (ModuleType == UIModuleType.Main)
			{
				SetTweenValue(ScoreTracker.Score);
				_currentValue = Mathf.MoveTowards(_currentValue, _targetValue, _rate * Time.unscaledDeltaTime);
				if (Mathf.Approximately(_currentValue, _targetValue))
				{
					_currentValue = _targetValue;
				}
				SetText(base._value, _currentValue.ToString("N0"));
			}
		}

		private void SetTweenValue(int value)
		{
			_targetValue = value;
			_rate = Mathf.Abs(_targetValue - _currentValue) / 1f;
		}
	}
	[RegisterTypeInIl2Cpp]
	public class HUD : MonoBehaviour
	{
		public Transform followTarget;

		public Module ScoreModule { get; set; }

		public Module MultiplierModule { get; set; }

		public Module HighScoreModule { get; set; }

		public HUD(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if ((Object)(object)((Component)this).transform.Find("MainScore") != (Object)null)
			{
				ScoreModule = ((Component)((Component)this).transform.Find("MainScore")).GetComponent<ScoreModule>();
			}
			if (Object.op_Implicit((Object)(object)((Component)this).transform.Find("MainMultiplier")))
			{
				MultiplierModule = ((Component)((Component)this).transform.Find("MainMultiplier")).GetComponent<MultiplierModule>();
			}
		}

		private void OnEnable()
		{
			UpdateModule(null);
			UpdateModule(null);
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAdded, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAccumulated, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueRemoved = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueRemoved, new Action<PackedValue>(UpdateModule));
		}

		private void OnDisable()
		{
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAdded, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAccumulated, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueRemoved = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueRemoved, new Action<PackedValue>(UpdateModule));
		}

		private void Start()
		{
			if ((Object)(object)Player.GetPhysicsRig() != (Object)null)
			{
				followTarget = ((Rig)Player.ControllerRig).m_head;
			}
		}

		private void FixedUpdate()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)followTarget == (Object)null))
			{
				Vector3 position = Vector3.Lerp(((Component)this).transform.position, followTarget.position + followTarget.forward * Settings.DistanceToCamera, Settings.MovementSmoothness * Time.unscaledDeltaTime);
				Quaternion rotation = Quaternion.LookRotation(followTarget.forward);
				((Component)this).transform.position = position;
				((Component)this).transform.rotation = rotation;
			}
		}

		public void SetParent(Transform parent)
		{
			((Component)this).transform.SetParent(parent);
		}

		public void SetScoreModule(Module module)
		{
			ScoreModule = module;
		}

		public void SetMultiplierModule(Module module)
		{
			MultiplierModule = module;
		}

		public void UpdateModule(PackedValue data)
		{
			if (data is PackedScore)
			{
				ScoreModule.AssignPackedData(data);
				ScoreModule.OnModuleEnable();
			}
			else if (data is PackedMultiplier)
			{
				MultiplierModule.AssignPackedData(data);
				MultiplierModule.OnModuleEnable();
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	public class DescriptorList : MonoBehaviour
	{
		public List<Module> ActiveModules;

		public int count = 6;

		public List<Module> Modules;

		public PackedValue.PackedType packedType { get; set; }

		public GameObject ModulePrefab { get; set; }

		public DescriptorList(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			Modules = new List<Module>();
			ActiveModules = new List<Module>();
			for (int i = 0; i < ((Component)this).transform.childCount; i++)
			{
				Transform child = ((Component)this).transform.GetChild(i);
				Modules.Add(((Component)child).GetComponent<Module>());
			}
			if (((Object)this).name == "ScoreDescriptors")
			{
				packedType = PackedValue.PackedType.Score;
			}
			else if (((Object)this).name == "MultiplierDescriptors")
			{
				packedType = PackedValue.PackedType.Multiplier;
			}
		}

		private void OnEnable()
		{
			API.UI.OnModulePostDecayed = (Action<Module>)Delegate.Combine(API.UI.OnModulePostDecayed, (Action<Module>)delegate(Module item)
			{
				ActiveModules.Remove(item);
			});
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAdded, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAccumulated, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, new Action<PackedValue>(SetModuleActive));
		}

		private void OnDisable()
		{
			API.UI.OnModulePostDecayed = (Action<Module>)Delegate.Remove(API.UI.OnModulePostDecayed, (Action<Module>)delegate(Module item)
			{
				ActiveModules.Remove(item);
			});
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAdded, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAccumulated, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, new Action<PackedValue>(SetModuleActive));
		}

		public void SetPackedType(int packedType)
		{
			this.packedType = (PackedValue.PackedType)packedType;
		}

		public void SetModuleActive(PackedValue value)
		{
			if (Modules == null || Modules.Count == 0 || value.PackedValueType != packedType)
			{
				return;
			}
			foreach (Module module in Modules)
			{
				if (!((Component)module).gameObject.activeInHierarchy)
				{
					module.AssignPackedData(value);
					module.SetDecayTime(value.DecayTime);
					module.SetPostDecayTime(0.5f);
					((Component)module).gameObject.SetActive(true);
					ActiveModules.Add(module);
					break;
				}
				if (ActiveModules.Contains(module) && !module.IsDecaying() && module.PackedValue.eventType == value.eventType)
				{
					if (value.Stackable)
					{
						module.AssignPackedData(value);
						module.OnModuleEnable();
						module.SetDecayTime(value.DecayTime);
						module.SetPostDecayTime(0.5f);
						break;
					}
					if (value.Tiers != null)
					{
						module.AssignPackedData(value);
						module.OnModuleEnable();
						module.SetDecayTime(value.DecayTime);
						module.SetPostDecayTime(0.5f);
						break;
					}
				}
			}
		}

		public void PoolObjects()
		{
			if (!((Object)(object)ModulePrefab == (Object)null))
			{
				for (int i = 0; i < count; i++)
				{
					Module component = Object.Instantiate<GameObject>(ModulePrefab, ((Component)this).transform).GetComponent<Module>();
					component.ModuleType = Module.UIModuleType.Descriptor;
					Modules.Add(component);
				}
			}
		}
	}
	public static class HUDManager
	{
		private static GameObject _parentObject;

		public static List<HUD> LoadedHUDs { get; private set; }

		public static HUD ActiveHUD { get; private set; }

		public static HUD LastHUD { get; private set; }

		internal static void Initialize()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			_parentObject = new GameObject("[ScoreLab] - HUD Container");
			LoadedHUDs = new List<HUD>();
			Populate();
			if (HUDLoader.LoadedHUDs.ContainsKey(Settings.SavedHUD))
			{
				LoadHUD(Settings.SavedHUD);
			}
			else
			{
				LoadHUD("Coda");
			}
		}

		internal static void Uninitialize()
		{
		}

		public static void Populate()
		{
			for (int i = 0; i < HUDLoader.LoadedHUDManifests.Count; i++)
			{
				JSONHUDManifest jSONHUDManifest = HUDLoader.LoadedHUDManifests[i];
				GameObject obj = Object.Instantiate<GameObject>(HUDLoader.LoadedHUDs[jSONHUDManifest.Name]);
				((Object)obj).name = jSONHUDManifest.Name;
				HUD component = obj.GetComponent<HUD>();
				if (!((Object)(object)component == (Object)null))
				{
					LoadedHUDs.Add(component);
					component.SetParent(_parentObject.transform);
					((Component)component).gameObject.SetActive(false);
				}
			}
		}

		public static void HUDShowModeUpdated(HUDShowMode mode)
		{
			if (!((Object)(object)ActiveHUD == (Object)null))
			{
				switch (mode)
				{
				case HUDShowMode.Always:
					((Component)ActiveHUD).gameObject.SetActive(true);
					break;
				case HUDShowMode.Never:
					((Component)ActiveHUD).gameObject.SetActive(false);
					break;
				}
			}
		}

		public static void LoadHUD(string name)
		{
			if ((Object)(object)ActiveHUD != (Object)null)
			{
				LastHUD = ActiveHUD;
			}
			UnloadHUD();
			foreach (HUD loadedHUD in LoadedHUDs)
			{
				if (((Object)loadedHUD).name == name)
				{
					ActiveHUD = loadedHUD;
					break;
				}
			}
			if (!((Object)(object)ActiveHUD == (Object)null))
			{
				Settings.SavedHUD = name;
				ValueManager.UsePackage(name);
				((Component)ActiveHUD).gameObject.SetActive(true);
				ActiveHUD.SetParent(null);
			}
		}

		public static void UnloadHUD()
		{
			if ((Object)(object)ActiveHUD != (Object)null)
			{
				ActiveHUD.SetParent(_parentObject.transform);
				((Component)ActiveHUD).gameObject.SetActive(false);
				ActiveHUD = null;
			}
		}

		public static void DestroyHUD()
		{
			if ((Object)(object)ActiveHUD != (Object)null)
			{
				Object.Destroy((Object)(object)ActiveHUD);
				ActiveHUD = null;
			}
		}

		public static void DestroyLoadedHUDs()
		{
			if (LoadedHUDs == null || LoadedHUDs.Count == 0)
			{
				return;
			}
			foreach (HUD loadedHUD in LoadedHUDs)
			{
				Object.Destroy((Object)(object)((Component)loadedHUD).gameObject);
			}
			LoadedHUDs.Clear();
		}
	}
}
namespace NEP.ScoreLab.Data
{
	public static class HUDLoader
	{
		public static Dictionary<string, AudioClip> HUDAudioBank;

		public static Dictionary<string, GameObject> LoadedHUDs;

		public static List<JSONHUDManifest> LoadedHUDManifests;

		private static List<AssetBundle> _assetBundles;

		private static List<Object> _persistentBundleObjects;

		public static void Initialize()
		{
			LoadedHUDs = new Dictionary<string, GameObject>();
			HUDAudioBank = new Dictionary<string, AudioClip>();
			LoadedHUDManifests = new List<JSONHUDManifest>();
			_persistentBundleObjects = new List<Object>();
			_assetBundles = new List<AssetBundle>();
			LoadHUDs();
		}

		public static void SpawnDefaultUI()
		{
			SpawnUI("Coda");
		}

		public static void SpawnUI(string name)
		{
			foreach (JSONHUDManifest loadedHUDManifest in LoadedHUDManifests)
			{
				if (loadedHUDManifest.Name == name)
				{
					SpawnUI(LoadedHUDs[name]);
				}
			}
		}

		public static void SpawnUI(GameObject uiObject)
		{
			Object.Instantiate<GameObject>(uiObject);
		}

		public static void LoadHUDs()
		{
			foreach (string item2 in Directory.EnumerateDirectories(Path.Combine(MelonEnvironment.UserDataDirectory, "Not Enough Photons/ScoreLab")))
			{
				IEnumerable<string> enumerable = Directory.EnumerateFiles(item2);
				string text = string.Empty;
				string text2 = string.Empty;
				foreach (string item3 in enumerable)
				{
					if (item3.EndsWith(".hud"))
					{
						text = item3;
					}
					if (item3.EndsWith(".hud_manifest"))
					{
						text2 = item3;
					}
				}
				if (text == string.Empty)
				{
					Main.Logger.Error("Missing .HUD file in " + item2 + "!");
					continue;
				}
				if (text2 == string.Empty)
				{
					Main.Logger.Error("Missing HUD manifest file in " + item2 + "!");
					continue;
				}
				JSONHUDManifest item = default(JSONHUDManifest);
				if (!item.FromJSON(text2))
				{
					Main.Logger.Error("Failed to read HUD manifest data! Source: " + item2);
					continue;
				}
				AssetBundle val = AssetBundle.LoadFromFile(text);
				GameObject value = HelperMethods.LoadPersistentAsset<GameObject>(val, item.AssetName);
				Il2CppReferenceArray<Object> val2 = val.LoadAllAssets();
				Texture2D val3 = HelperMethods.LoadPersistentAsset<Texture2D>(val, "Logo");
				if ((Object)(object)val3 != (Object)null)
				{
					item.SetHUDLogo(val3);
				}
				_assetBundles.Add(val);
				LoadedHUDManifests.Add(item);
				LoadedHUDs.Add(item.Name, value);
				if (val2 == null || ((Il2CppArrayBase<Object>)(object)val2).Length == 0)
				{
					continue;
				}
				foreach (Object item4 in (Il2CppArrayBase<Object>)(object)val2)
				{
					AudioClip val4 = ((Il2CppObjectBase)item4).TryCast<AudioClip>();
					if ((Object)(object)val4 != (Object)null)
					{
						((Object)val4).hideFlags = (HideFlags)32;
						HUDAudioBank.Add(item4.name, val4);
					}
				}
			}
		}

		public static void ReloadHUDs()
		{
			if ((Object)(object)HUDManager.ActiveHUD != (Object)null)
			{
				HUDManager.DestroyHUD();
			}
			HUDManager.DestroyLoadedHUDs();
			HUDAudioBank.Clear();
			LoadedHUDManifests.Clear();
			LoadedHUDs.Clear();
			foreach (AssetBundle assetBundle in _assetBundles)
			{
				assetBundle.Unload(true);
			}
			_assetBundles.Clear();
			LoadHUDs();
			SLMenu.RefreshHUDPage();
			HUDManager.Populate();
			HUDManager.LoadHUD(Settings.SavedHUD);
		}
	}
	public struct JSONAudioParams
	{
		public string[] sounds;

		public float volume;

		public float pitch;

		public bool FromJSON(JObject jObject)
		{
			if (jObject == null)
			{
				return false;
			}
			JToken obj = jObject["Clips"];
			JArray val = (JArray)(object)((obj is JArray) ? obj : null);
			if (val != null)
			{
				sounds = new string[((JContainer)val).Count];
				for (int i = 0; i < sounds.Length; i++)
				{
					sounds[i] = Extensions.Value<string>((IEnumerable<JToken>)val[i]);
				}
			}
			volume = Extensions.Value<float>((IEnumerable<JToken>)jObject["Volume"]);
			pitch = Extensions.Value<float>((IEnumerable<JToken>)jObject["Pitch"]);
			return true;
		}
	}
	public struct JSONHUDManifest
	{
		public string Name;

		public string Author;

		public string Description;

		public string[] Tags;

		public string AssetName;

		public Texture2D Logo;

		public bool FromJSON(string pathToJson)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using (StreamReader streamReader = new StreamReader(pathToJson))
			{
				JsonTextReader val = new JsonTextReader((TextReader)streamReader);
				try
				{
					JToken obj = JToken.ReadFrom((JsonReader)(object)val);
					JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
					if (val2 == null)
					{
						return false;
					}
					Name = Extensions.Value<string>((IEnumerable<JToken>)val2["name"]);
					Author = Extensions.Value<string>((IEnumerable<JToken>)val2["author"]);
					AssetName = Extensions.Value<string>((IEnumerable<JToken>)val2["assetName"]);
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			return true;
		}

		public void SetHUDLogo(Texture2D texture)
		{
			Logo = texture;
		}
	}
	public struct JSONMult
	{
		public string EventType;

		public string TierEventType;

		public float DecayTime;

		public bool Stackable;

		public JSONAudioParams EventAudio;

		public string Name;

		public float Multiplier;

		public string Condition;

		public int TierRequirement;

		public JSONMult[] Tiers;

		public bool FromJSON(string pathToJson)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using (StreamReader streamReader = new StreamReader(pathToJson))
			{
				JsonTextReader val = new JsonTextReader((TextReader)streamReader);
				try
				{
					JToken obj = JToken.ReadFrom((JsonReader)(object)val);
					JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
					if (val2 == null)
					{
						return false;
					}
					ReadMultObject(val2);
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			return true;
		}

		private void ReadMultObject(JObject obj)
		{
			EventType = Extensions.Value<string>((IEnumerable<JToken>)obj["EventType"]);
			DecayTime = Extensions.Value<float>((IEnumerable<JToken>)obj["DecayTime"]);
			Stackable = Extensions.Value<bool>((IEnumerable<JToken>)obj["Stackable"]);
			Condition = Extensions.Value<string>((IEnumerable<JToken>)obj["Condition"]);
			EventAudio.FromJSON(Extensions.Value<JObject>((IEnumerable<JToken>)obj["EventAudio"]));
			Name = Extensions.Value<string>((IEnumerable<JToken>)obj["Name"]);
			Multiplier = Extensions.Value<float>((IEnumerable<JToken>)obj["Multiplier"]);
			TierRequirement = Extensions.Value<int>((IEnumerable<JToken>)obj["TierRequirement"]);
			JToken obj2 = obj["Tiers"];
			JArray val = ((obj2 != null) ? Extensions.Value<JArray>((IEnumerable<JToken>)obj2) : null);
			List<JSONMult> list = new List<JSONMult>();
			if (val != null)
			{
				for (int i = 0; i < ((JContainer)val).Count; i++)
				{
					JSONMult item = default(JSONMult);
					JToken obj3 = val[i];
					JObject obj4 = (JObject)(object)((obj3 is JObject) ? obj3 : null);
					item.ReadMultObject(obj4);
					list.Add(item);
				}
				Tiers = list.ToArray();
			}
		}
	}
	public struct JSONScore
	{
		public string EventType;

		public string TierEventType;

		public float DecayTime;

		public bool Stackable;

		public JSONAudioParams EventAudio;

		public string Name;

		public int Score;

		public int TierRequirement;

		public JSONScore[] Tiers;

		public bool FromJSON(string pathToJson)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using (StreamReader streamReader = new StreamReader(pathToJson))
			{
				JsonTextReader val = new JsonTextReader((TextReader)streamReader);
				try
				{
					JToken obj = JToken.ReadFrom((JsonReader)(object)val);
					JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
					if (val2 == null)
					{
						return false;
					}
					ReadScoreObject(val2);
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			return true;
		}

		private void ReadScoreObject(JObject obj)
		{
			EventType = Extensions.Value<string>((IEnumerable<JToken>)obj["EventType"]);
			DecayTime = Extensions.Value<float>((IEnumerable<JToken>)obj["DecayTime"]);
			Stackable = Extensions.Value<bool>((IEnumerable<JToken>)obj["Stackable"]);
			EventAudio.FromJSON(Extensions.Value<JObject>((IEnumerable<JToken>)obj["EventAudio"]));
			Name = Extensions.Value<string>((IEnumerable<JToken>)obj["Name"]);
			Score = Extensions.Value<int>((IEnumerable<JToken>)obj["Score"]);
			TierRequirement = Extensions.Value<int>((IEnumerable<JToken>)obj["TierRequirement"]);
			JToken obj2 = obj["Tiers"];
			JArray val = ((obj2 != null) ? Extensions.Value<JArray>((IEnumerable<JToken>)obj2) : null);
			List<JSONScore> list = new List<JSONScore>();
			if (val != null)
			{
				for (int i = 0; i < ((JContainer)val).Count; i++)
				{
					JSONScore item = default(JSONScore);
					JToken obj3 = val[i];
					JObject obj4 = (JObject)(object)((obj3 is JObject) ? obj3 : null);
					item.ReadScoreObject(obj4);
					list.Add(item);
				}
				Tiers = list.ToArray();
			}
		}
	}
	public struct MarrowSceneInfo
	{
		public string LevelTitle;

		public string Barcode;

		public MarrowScene MarrowScene;
	}
	public static class EventType
	{
		public static class Score
		{
			public static readonly string Kill = "SCORE_KILL";

			public static readonly string Headshot = "SCORE_HEADSHOT";

			public static readonly string EnemyMidAirKill = "SCORE_MID_AIR";

			public static readonly string GameWaveCompleted = "SCORE_WAVE_COMPLETED";

			public static readonly string GameRoundCompleted = "SCORE_ROUND_COMPLETED";

			public static readonly string Crabcest = "SCORE_CRABCEST";

			public static readonly string Facehug = "SCORE_FACEHUG";

			public static readonly string StealthKill = "SCORE_STEALTH_KILL";
		}

		public static class Mult
		{
			public static readonly string Kill = "MULT_KILL";

			public static readonly string MidAir = "MULT_MIDAIR";

			public static readonly string Seated = "MULT_SEATED";

			public static readonly string SecondWind = "MULT_SECONDWIND";

			public static readonly string Ragolled = "MULT_RAGDOLLED";

			public static readonly string SwappedAvatars = "MULT_SWAPPED_AVATARS";

			public static readonly string SlowMo = "MULT_SLOWMO";
		}

		public static readonly string None = "None";
	}
	public class PackedAudioParams
	{
		public AudioClip[] Clips { get; private set; }

		public float Volume { get; private set; }

		public float Pitch { get; private set; }

		public PackedAudioParams()
		{
			Clips = null;
			Volume = 1f;
			Pitch = 1f;
		}

		public PackedAudioParams(JSONAudioParams audioParams)
		{
			Clips = (AudioClip[])(object)new AudioClip[audioParams.sounds.Length];
			for (int i = 0; i < Clips.Length; i++)
			{
				Clips[i] = HUDLoader.HUDAudioBank[audioParams.sounds[i]];
			}
			Volume = audioParams.volume;
			Pitch = audioParams.pitch;
		}
	}
	public class PackedHighScore : PackedValue
	{
		public int bestScore;

		public override PackedType PackedValueType => PackedType.HighScore;

		public PackedHighScore(string name, int bestScore)
		{
			this.bestScore = bestScore;
		}

		public override void OnValueCreated()
		{
		}

		public override void OnValueRemoved()
		{
		}
	}
	[Serializable]
	public class PackedMultiplier : PackedValue
	{
		public float Multiplier;

		public float AccumulatedMultiplier;

		public string Condition;

		private bool _timed;

		private bool _timeBegin;

		public override PackedType PackedValueType => PackedType.Multiplier;

		public float Elapsed => _tDecay;

		public Func<bool> condition { get; private set; }

		public PackedMultiplier()
		{
		}

		public PackedMultiplier(JSONMult mult, bool useTiers = false)
		{
			eventType = mult.EventType;
			DecayTime = mult.DecayTime;
			Stackable = mult.Stackable;
			Name = mult.Name;
			Multiplier = mult.Multiplier;
			Condition = mult.Condition;
			TierRequirement = mult.TierRequirement;
			EventAudio = new PackedAudioParams(mult.EventAudio);
			if (useTiers)
			{
				TierEventType = mult.TierEventType;
			}
		}

		public override void OnValueCreated()
		{
			if (DecayTime != 0f)
			{
				_timed = true;
			}
			condition = API.GameConditions.GetCondition(Condition);
			AccumulatedMultiplier = Multiplier;
			_tDecay = DecayTime;
		}

		public override void OnValueRemoved()
		{
			_timeBegin = false;
			ResetTier();
		}

		public override void OnUpdate()
		{
			if (condition != null && !condition())
			{
				ScoreTracker.Remove(this);
			}
			OnUpdateDecay();
		}

		public override void OnUpdateDecay()
		{
			if (_timed)
			{
				if (!_timeBegin)
				{
					API.Multiplier.OnMultiplierTimeBegin?.Invoke(this);
					_timeBegin = true;
				}
				if (_tDecay <= 0f)
				{
					API.Multiplier.OnMultiplierTimeExpired?.Invoke(this);
					_tDecay = DecayTime;
					ScoreTracker.Remove(this);
				}
				_tDecay -= Time.deltaTime;
			}
		}
	}
	[Serializable]
	public class PackedScore : PackedValue
	{
		public int Score;

		public int AccumulatedScore;

		public override PackedType PackedValueType => PackedType.Score;

		public PackedScore()
		{
		}

		public PackedScore(JSONScore score, bool useTiers = false)
		{
			eventType = score.EventType;
			DecayTime = score.DecayTime;
			Stackable = score.Stackable;
			Name = score.Name;
			Score = score.Score;
			TierRequirement = score.TierRequirement;
			EventAudio = new PackedAudioParams(score.EventAudio);
			if (useTiers)
			{
				TierEventType = score.TierEventType;
			}
			else
			{
				AccumulatedScore = score.Score;
			}
		}

		public override void OnValueCreated()
		{
			_tDecay = DecayTime;
			AccumulatedScore = Score;
		}

		public override void OnValueRemoved()
		{
			ResetTier();
		}

		public override void OnUpdate()
		{
			OnUpdateDecay();
		}

		public override void OnUpdateDecay()
		{
			if (_tDecay <= 0f)
			{
				ScoreTracker.Remove(this);
			}
			_tDecay -= Time.deltaTime;
		}
	}
	[Serializable]
	public class PackedValue
	{
		public enum PackedType
		{
			Base,
			Score,
			Multiplier,
			HighScore,
			Misc
		}

		public string Name;

		public string eventType;

		public string TierEventType;

		public PackedAudioParams EventAudio;

		public bool Stackable;

		public float DecayTime;

		public float PostDecayTime;

		public PackedValue Parent;

		public PackedValue[] Tiers;

		public int TierRequirement;

		protected float _tDecay;

		private int _tierIndex;

		private int _tierRequirementIndex;

		public virtual PackedType PackedValueType => PackedType.Base;

		public PackedValue CurrentTier
		{
			get
			{
				if (Tiers == null || Tiers.Length == 0)
				{
					return this;
				}
				if (_tierIndex == Tiers.Length)
				{
					_tierIndex = Tiers.Length;
					return Tiers[_tierIndex];
				}
				return Tiers[_tierIndex];
			}
		}

		public PackedValue NextTier
		{
			get
			{
				if (_tierIndex + 1 >= Tiers.Length)
				{
					return Tiers[_tierIndex];
				}
				return Tiers[_tierIndex + 1];
			}
		}

		public int TierIndex => _tierIndex;

		public int TierRequirementIndex => _tierRequirementIndex;

		public virtual bool IsActive { get; }

		public virtual void OnValueCreated()
		{
		}

		public virtual void OnValueRemoved()
		{
		}

		public virtual void OnUpdate()
		{
		}

		public virtual void OnUpdateDecay()
		{
		}

		public void SetDecayTime(float decayTime)
		{
			_tDecay = decayTime;
		}

		public void ToNextTier()
		{
			_tierRequirementIndex++;
			if (_tierRequirementIndex >= TierRequirement)
			{
				_tierRequirementIndex = TierRequirement;
				API.Value.OnValueTierReached?.Invoke(CurrentTier);
				if (_tierIndex + 1 < Tiers.Length)
				{
					_tierIndex++;
				}
			}
		}

		protected void ResetTier()
		{
			_tierIndex = 0;
		}
	}
	public static class ValueManager
	{
		public static Dictionary<string, int> HighScoreTable;

		public static readonly string Path_Developer = Path.Combine(MelonEnvironment.UserDataDirectory, "Not Enough Photons");

		public static readonly string Path_Mod = Path.Combine(Path_Developer, "ScoreLab");

		private static readonly string File_HighScores = Path.Combine(Path_Mod, "high_score_table.json");

		public static Dictionary<string, ValuePackage> Packages { get; private set; }

		public static ValuePackage ActivePackage { get; private set; }

		public static void Initialize()
		{
			HighScoreTable = new Dictionary<string, int>();
			Packages = new Dictionary<string, ValuePackage>();
			foreach (JSONHUDManifest loadedHUDManifest in HUDLoader.LoadedHUDManifests)
			{
				JSONScore[] scoresForHUD = GetScoresForHUD(loadedHUDManifest.Name);
				JSONMult[] multipliersForHUD = GetMultipliersForHUD(loadedHUDManifest.Name);
				PackedScore[] scores = CreateScoreObjects(scoresForHUD);
				PackedMultiplier[] multipliers = CreateMultiplierObjects(multipliersForHUD);
				Packages.Add(loadedHUDManifest.Name, new ValuePackage(scores, multipliers));
			}
			UsePackage(Settings.SavedHUD);
		}

		public static string[] GetAllFiles(string path, string extensionFilter)
		{
			string[] files = Directory.GetFiles(path);
			List<string> list = new List<string>();
			string[] array = files;
			foreach (string text in array)
			{
				if (text.EndsWith(extensionFilter))
				{
					list.Add(text);
				}
			}
			return list.ToArray();
		}

		public static void UsePackage(string name)
		{
			if (Packages.TryGetValue(name, out var value))
			{
				ActivePackage = value;
			}
		}

		public static PackedValue Get(string eventType)
		{
			if (ActivePackage.Values == null)
			{
				return null;
			}
			if (ActivePackage.Values.TryGetValue(eventType, out var value))
			{
				return value;
			}
			return null;
		}

		public static Dictionary<string, int> ReadHighScore()
		{
			return JsonConvert.DeserializeObject(File_HighScores) as Dictionary<string, int>;
		}

		public static void WriteHighScore()
		{
			string file_HighScores = File_HighScores;
			if (!File.Exists(file_HighScores))
			{
				Main.Logger.Warning("High score file doesn't exist! Creating one.");
				File.Create(file_HighScores);
			}
			else
			{
				string contents = JsonConvert.SerializeObject((object)HighScoreTable);
				File.WriteAllText(file_HighScores, contents);
			}
		}

		public static void WriteBestScore(PackedHighScore highScore)
		{
			string name = highScore.Name;
			int bestScore = highScore.bestScore;
			HighScoreTable.Add(name, bestScore);
		}

		private static JSONScore[] GetScoresForHUD(string name)
		{
			string path = Path.Combine(Path_Mod, name + "/Data/Score");
			if (!Directory.Exists(path))
			{
				Main.Logger.Warning("HUD " + name + " doesn't have a score data folder!");
				return null;
			}
			string[] allFiles = GetAllFiles(path, ".json");
			List<JSONScore> list = new List<JSONScore>();
			string[] array = allFiles;
			for (int i = 0; i < array.Length; i++)
			{
				JSONScore item = ReadScoreData(array[i]);
				list.Add(item);
			}
			return list.ToArray();
		}

		private static JSONMult[] GetMultipliersForHUD(string name)
		{
			string path = Path.Combine(Path_Mod, name + "/Data/Multiplier");
			if (!Directory.Exists(path))
			{
				Main.Logger.Warning("HUD " + name + " doesn't have a multiplier data folder!");
				return null;
			}
			string[] allFiles = GetAllFiles(path, ".json");
			List<JSONMult> list = new List<JSONMult>();
			string[] array = allFiles;
			for (int i = 0; i < array.Length; i++)
			{
				JSONMult item = ReadMultiplierData(array[i]);
				list.Add(item);
			}
			return list.ToArray();
		}

		private static PackedScore[] CreateScoreObjects(JSONScore[] scores)
		{
			if (scores == null)
			{
				return null;
			}
			List<PackedScore> list = new List<PackedScore>();
			for (int i = 0; i < scores.Length; i++)
			{
				JSONScore score = scores[i];
				PackedScore packedScore = new PackedScore(score);
				if (score.Tiers != null && score.Tiers.Length != 0)
				{
					List<PackedScore> list2 = new List<PackedScore>();
					JSONScore[] tiers = score.Tiers;
					for (int j = 0; j < tiers.Length; j++)
					{
						PackedScore packedScore2 = new PackedScore(tiers[j], useTiers: true);
						packedScore2.eventType = packedScore.eventType;
						list2.Add(packedScore2);
					}
					PackedValue[] tiers2 = list2.ToArray();
					packedScore.Tiers = tiers2;
				}
				list.Add(packedScore);
			}
			return list.ToArray();
		}

		private static PackedMultiplier[] CreateMultiplierObjects(JSONMult[] multipliers)
		{
			if (multipliers == null)
			{
				return null;
			}
			List<PackedMultiplier> list = new List<PackedMultiplier>();
			for (int i = 0; i < multipliers.Length; i++)
			{
				JSONMult mult = multipliers[i];
				PackedMultiplier packedMultiplier = new PackedMultiplier(mult);
				if (mult.Tiers != null && mult.Tiers.Length != 0)
				{
					List<PackedMultiplier> list2 = new List<PackedMultiplier>();
					JSONMult[] tiers = mult.Tiers;
					for (int j = 0; j < tiers.Length; j++)
					{
						PackedMultiplier packedMultiplier2 = new PackedMultiplier(tiers[j], useTiers: true);
						packedMultiplier2.eventType = packedMultiplier.eventType;
						list2.Add(packedMultiplier2);
					}
					PackedValue[] tiers2 = list2.ToArray();
					packedMultiplier.Tiers = tiers2;
				}
				list.Add(packedMultiplier);
			}
			return list.ToArray();
		}

		private static JSONScore ReadScoreData(string file)
		{
			JSONScore result = default(JSONScore);
			result.FromJSON(file);
			return result;
		}

		private static JSONMult ReadMultiplierData(string file)
		{
			JSONMult result = default(JSONMult);
			result.FromJSON(file);
			return result;
		}
	}
	public struct ValuePackage
	{
		public Dictionary<string, PackedValue> Values;

		public ValuePackage(PackedScore[] scores, PackedMultiplier[] multipliers)
		{
			Values = new Dictionary<string, PackedValue>();
			if (scores != null)
			{
				foreach (PackedScore packedScore in scores)
				{
					Values.Add(packedScore.eventType, packedScore);
				}
			}
			if (multipliers != null)
			{
				foreach (PackedMultiplier packedMultiplier in multipliers)
				{
					Values.Add(packedMultiplier.eventType, packedMultiplier);
				}
			}
		}
	}
}
namespace NEP.ScoreLab.Core
{
	public static class API
	{
		public static class Value
		{
			public static Action<PackedValue> OnValueAdded;

			public static Action<PackedValue> OnValueAccumulated;

			public static Action<PackedValue> OnValueTierReached;

			public static Action<PackedValue> OnValueRemoved;
		}

		public static class Score
		{
			public static Action<int> OnScoreUpdated;

			public static Action<int> OnScoreDifferenceUpdated;

			public static Action<int> OnLastScoreUpdated;
		}

		public static class Multiplier
		{
			public static Action<PackedMultiplier> OnMultiplierTimeBegin;

			public static Action<PackedMultiplier> OnMultiplierTimeExpired;
		}

		public static class HighScore
		{
			public static Action<PackedHighScore> OnHighScoreReached;

			public static Action<PackedHighScore> OnHighScoreUpdated;

			public static Action<PackedHighScore> OnHighScoreLoaded;

			public static Action<PackedHighScore> OnHighScoreSaved;
		}

		public static class GameConditions
		{
			private static Dictionary<string, Func<bool>> _conditionTable = new Dictionary<string, Func<bool>>
			{
				{
					"IsPlayerMoving",
					() => ScoreDirector.IsPlayerMoving
				},
				{
					"IsPlayerSeated",
					() => ScoreDirector.IsPlayerSeated
				},
				{
					"IsPlayerInAir",
					() => ScoreDirector.IsPlayerInAir
				},
				{
					"IsPlayerRagdolled",
					() => ScoreDirector.IsPlayerRagdolled
				},
				{
					"IsSlowMoEnabled",
					() => ScoreDirector.IsSlowMoEnabled
				}
			};

			public static Func<bool> GetCondition(string cond)
			{
				if (string.IsNullOrEmpty(cond))
				{
					Debug.LogWarning(Object.op_Implicit(cond + " doesn't exist in the condition table."));
					return null;
				}
				if (!_conditionTable.ContainsKey(cond))
				{
					Debug.LogWarning(Object.op_Implicit(cond + " doesn't exist in the condition table."));
					return null;
				}
				return _conditionTable[cond];
			}
		}

		public static class UI
		{
			public static Action<NEP.ScoreLab.HUD.Module> OnModuleEnabled;

			public static Action<NEP.ScoreLab.HUD.Module> OnModuleDisabled;

			public static Action<NEP.ScoreLab.HUD.Module> OnModuleDecayed;

			public static Action<NEP.ScoreLab.HUD.Module> OnModulePostDecayed;
		}
	}
	public static class ScoreDirector
	{
		public static class Patches
		{
			[HarmonyPatch(typeof(Projectile), "Awake")]
			public static class ProjectilePatch
			{
				public static void Postfix(Projectile __instance)
				{
					Action<Collider, Vector3, Vector3> action = OnProjectileCollision;
					((UnityEvent<Collider, Vector3, Vector3>)(object)__instance.onCollision).AddListener(UnityAction<Collider, Vector3, Vector3>.op_Implicit(action));
				}

				private static void OnProjectileCollision(Collider collider, Vector3 world, Vector3 normal)
				{
					MarrowBody val = MarrowBody.Cache.Get(((Component)collider).gameObject);
					if (!((Object)(object)val == (Object)null))
					{
						TriggerRefProxy component = ((Component)val).GetComponent<TriggerRefProxy>();
						if (!((Object)(object)component == (Object)null) && !component.aiManager.isDead && (Object)(object)((Component)component.targetHead).gameObject == (Object)(object)((Component)val).gameObject)
						{
							ScoreTracker.Add(EventType.Score.Headshot);
						}
					}
				}
			}

			[HarmonyPatch(typeof(RigManager), "SwitchAvatar")]
			public static class RigManagerSwapAvatarPatch
			{
				public static void Postfix(Avatar newAvatar)
				{
					_playerRecentlySwappedAvatars = true;
				}
			}

			[HarmonyPatch(typeof(BehaviourCrablet))]
			[HarmonyPatch("AttachToFace")]
			public static class CrabletAttachToFacePatch
			{
				public static void Postfix(Rigidbody face, TriggerRefProxy trp, bool preAttach = false, bool isPlayer = true)
				{
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					//IL_000c: Invalid comparison between Unknown and I4
					if (!isPlayer)
					{
						if ((int)trp.npcType == 32)
						{
							ScoreTracker.Add(EventType.Score.Crabcest);
						}
						else
						{
							ScoreTracker.Add(EventType.Score.Facehug);
						}
					}
				}
			}

			[HarmonyPatch(typeof(Seat))]
			[HarmonyPatch("Register")]
			public static class RegisterSeatPatch
			{
				public static void Postfix(RigManager rM)
				{
					IsPlayerSeated = true;
					ScoreTracker.Add(EventType.Mult.Seated);
				}
			}

			[HarmonyPatch(typeof(Seat))]
			[HarmonyPatch("DeRegister")]
			public static class DeRegisterSeatPatch
			{
				public static void Postfix()
				{
					IsPlayerSeated = false;
				}
			}

			[HarmonyPatch(typeof(Player_Health))]
			[HarmonyPatch("LifeSavingDamgeDealt")]
			public static class SecondWindPatch
			{
				public static void Postfix()
				{
					ScoreTracker.Add(EventType.Mult.SecondWind);
				}
			}

			[HarmonyPatch(typeof(Arena_GameController))]
			[HarmonyPatch("StartNextWave")]
			public static class StartNextWavePatch
			{
				public static void Postfix(Arena_GameController __instance)
				{
					ScoreTracker.Add(EventType.Score.GameWaveCompleted);
				}
			}

			[HarmonyPatch(typeof(Arena_GameController))]
			[HarmonyPatch("EndOfRound")]
			public static class StartNextRoundPatch
			{
				public static void Postfix(Arena_GameController __instance)
				{
					ScoreTracker.Add(EventType.Score.GameRoundCompleted);
				}
			}

			[HarmonyPatch(typeof(PhysicsRig))]
			[HarmonyPatch("OnUpdate")]
			public static class PhysRigPatch
			{
				private static bool _midAirTargetBool;

				private static float _tMidAirDelay = 0.5f;

				private static float _tAirTime;

				private static bool _ragdolledTargetBool;

				private static float _tRagdollDelay = 0.5f;

				private static float _tRagdollTime;

				public static void Postfix(PhysicsRig __instance)
				{
					IsPlayerInAir = !__instance.physG.isGrounded;
					if (IsPlayerInAir)
					{
						if (!_midAirTargetBool)
						{
							_tAirTime += Time.deltaTime;
							if (_tAirTime > _tMidAirDelay)
							{
								ScoreTracker.Add(EventType.Mult.MidAir);
								_midAirTargetBool = true;
							}
						}
					}
					else
					{
						_tAirTime = 0f;
						_midAirTargetBool = false;
					}
					if (IsPlayerRagdolled)
					{
						if (!_ragdolledTargetBool)
						{
							_ragdolledTargetBool = true;
						}
					}
					else
					{
						_ragdolledTargetBool = false;
					}
					if (_playerRecentlySwappedAvatars)
					{
						ScoreTracker.Add(EventType.Mult.SwappedAvatars);
						_playerRecentlySwappedAvatars = false;
					}
				}
			}

			[HarmonyPatch(typeof(PhysicsRig))]
			[HarmonyPatch("RagdollRig")]
			public static class PhysRigRagdollPatch
			{
				public static void Postfix(PhysicsRig __instance)
				{
					IsPlayerRagdolled = true;
				}
			}

			[HarmonyPatch(typeof(PhysicsRig))]
			[HarmonyPatch("UnRagdollRig")]
			public static class PhysRigUnRagdollPatch
			{
				public static void Postfix(PhysicsRig __instance)
				{
					IsPlayerRagdolled = false;
				}
			}

			[HarmonyPatch(typeof(TimeManager), "OnPostTimeUpdate")]
			public static class TimeManagerUpdatePatch
			{
				private static bool _slowmoSwitch;

				public static void Postfix()
				{
				}
			}

			[HarmonyPatch(typeof(TimeManager), "INCREASE_TIMESCALE")]
			public static class TimeManagerIncreaseTimePatch
			{
				public static void Postfix()
				{
				}
			}

			[HarmonyPatch(typeof(TimeManager), "DECREASE_TIMESCALE")]
			public static class TimeManagerDecreaseTimePatch
			{
				public static void Postfix()
				{
				}
			}

			public static void InitPatches()
			{
				Hooking.OnNPCKillStart += OnAIDeath;
			}

			public static void OnAIDeath(BehaviourBaseNav behaviour)
			{
				ScoreTracker.Add(ValueManager.Get(EventType.Score.Kill));
				ScoreTracker.Add(ValueManager.Get(EventType.Mult.Kill));
				if (!behaviour.sensors.isGrounded)
				{
					ScoreTracker.Add(EventType.Score.EnemyMidAirKill);
				}
				if ((Object)(object)behaviour.sensors.target == (Object)null)
				{
					ScoreTracker.Add(EventType.Score.StealthKill);
				}
			}
		}

		public static readonly string PlayerName = "";

		public static bool IsPlayerMoving = false;

		public static bool IsPlayerInAir = false;

		public static bool IsPlayerSeated = false;

		public static bool IsPlayerRagdolled = false;

		public static bool IsSlowMoEnabled = false;

		private static bool _playerRecentlySwappedAvatars = false;
	}
	public static class ScoreTracker
	{
		private static int _score = 0;

		private static int _lastScore = 0;

		private static float _multiplier = 1f;

		private static float _baseMultiplier = 1f;

		public static List<PackedValue> ActiveValues { get; private set; }

		public static int Score => _score;

		public static int LastScore => _lastScore;

		public static float Multiplier => _multiplier;

		public static void Initialize()
		{
			ActiveValues = new List<PackedValue>();
		}

		public static void Update()
		{
			if (ActiveValues != null)
			{
				for (int i = 0; i < ActiveValues.Count; i++)
				{
					ActiveValues[i].OnUpdate();
				}
			}
		}

		public static void Add(string eventType)
		{
			Add(Create(eventType));
		}

		public static void Add(PackedValue value)
		{
			if (value != null)
			{
				if (value.PackedValueType == PackedValue.PackedType.Score)
				{
					SetPackedScore((PackedScore)value);
				}
				else if (value.PackedValueType == PackedValue.PackedType.Multiplier)
				{
					SetPackedMultiplier((PackedMultiplier)value);
				}
			}
		}

		public static void Remove(PackedValue value)
		{
			if (value.PackedValueType == PackedValue.PackedType.Score)
			{
				ActiveValues.Remove(value);
				value.OnValueRemoved();
				API.Value.OnValueRemoved?.Invoke(value);
			}
			else if (value.PackedValueType == PackedValue.PackedType.Multiplier)
			{
				ActiveValues.Remove(value);
				RemoveMultiplier((value as PackedMultiplier).AccumulatedMultiplier);
				value.OnValueRemoved();
				API.Value.OnValueRemoved?.Invoke(value);
			}
		}

		public static void AddScore(int score)
		{
			_lastScore = _score;
			_score += Mathf.RoundToInt((float)score * _multiplier);
		}

		public static void AddMultiplier(float multiplier)
		{
			_multiplier += multiplier;
		}

		public static void SetMultiplier(float multiplier)
		{
			_multiplier = multiplier;
		}

		public static void ResetScore()
		{
			_score = 0;
			_lastScore = 0;
		}

		public static void ResetMultiplier()
		{
			_multiplier = 1f;
		}

		public static void ResetAll()
		{
			ResetScore();
			ResetMultiplier();
			ResetHighScore();
			ActiveValues.Clear();
		}

		public static void ResetHighScore()
		{
		}

		public static void RemoveMultiplier(float multiplier)
		{
			if (_multiplier < _baseMultiplier)
			{
				_multiplier = _baseMultiplier;
			}
			_multiplier -= multiplier;
		}

		public static bool CheckDuplicate(PackedValue value)
		{
			foreach (PackedValue activeValue in ActiveValues)
			{
				if (activeValue.eventType == value.eventType)
				{
					return true;
				}
			}
			return false;
		}

		private static void SetPackedScore(PackedScore score)
		{
			if (score != null)
			{
				if (!CheckDuplicate(score))
				{
					InitializeValue(score);
					AddScore(score.Score);
					ActiveValues.Add(score);
					API.Value.OnValueAdded?.Invoke(score);
				}
				else if (score.Tiers != null)
				{
					PackedScore clone = GetClone<PackedScore>(score);
					PackedScore packedScore = (PackedScore)clone.CurrentTier;
					clone.ToNextTier();
					clone.TierRequirement = packedScore.TierRequirement;
					clone.SetDecayTime(packedScore.DecayTime);
					AddScore(packedScore.Score);
				}
				else if (score.Stackable)
				{
					PackedScore clone2 = GetClone<PackedScore>(score);
					AddScore(score.Score);
					clone2.SetDecayTime(clone2.DecayTime);
					clone2.AccumulatedScore += clone2.Score;
					API.Value.OnValueAccumulated?.Invoke(clone2);
				}
				else
				{
					PackedScore packedScore2 = CopyFromScore(score);
					InitializeValue(packedScore2);
					AddScore(packedScore2.Score);
					ActiveValues.Add(packedScore2);
					API.Value.OnValueAdded?.Invoke(packedScore2);
				}
			}
		}

		private static void SetPackedMultiplier(PackedMultiplier multiplier)
		{
			if (multiplier != null)
			{
				if (!CheckDuplicate(multiplier))
				{
					InitializeValue(multiplier);
					AddMultiplier(multiplier.Multiplier);
					ActiveValues.Add(multiplier);
					API.Value.OnValueAdded?.Invoke(multiplier);
				}
				else if (multiplier.Tiers != null)
				{
					PackedMultiplier clone = GetClone<PackedMultiplier>(multiplier);
					PackedMultiplier packedMultiplier = (PackedMultiplier)clone.CurrentTier;
					clone.ToNextTier();
					clone.TierRequirement = packedMultiplier.TierRequirement;
					clone.SetDecayTime(packedMultiplier.DecayTime);
					AddMultiplier(packedMultiplier.Multiplier);
					multiplier.AccumulatedMultiplier += packedMultiplier.Multiplier;
					API.Value.OnValueTierReached?.Invoke(packedMultiplier);
				}
				else if (multiplier.Stackable)
				{
					PackedMultiplier clone2 = GetClone<PackedMultiplier>(multiplier);
					AddMultiplier(multiplier.Multiplier);
					clone2.SetDecayTime(clone2.DecayTime);
					clone2.AccumulatedMultiplier += clone2.Multiplier;
					API.Value.OnValueAccumulated?.Invoke(clone2);
				}
				else
				{
					PackedMultiplier packedMultiplier2 = CopyFromMult(multiplier);
					InitializeValue(packedMultiplier2);
					AddMultiplier(multiplier.Multiplier);
					ActiveValues.Add(packedMultiplier2);
					API.Value.OnValueAdded?.Invoke(packedMultiplier2);
				}
			}
		}

		private static PackedScore CopyFromScore(PackedScore original)
		{
			return new PackedScore
			{
				eventType = original.eventType,
				Name = original.Name,
				Score = original.Score,
				EventAudio = original.EventAudio,
				DecayTime = original.DecayTime
			};
		}

		private static PackedMultiplier CopyFromMult(PackedMultiplier original)
		{
			return new PackedMultiplier
			{
				eventType = original.eventType,
				Name = original.Name,
				Multiplier = original.Multiplier,
				EventAudio = original.EventAudio,
				DecayTime = original.DecayTime,
				Condition = original.Condition
			};
		}

		private static PackedValue Create(string eventType)
		{
			PackedValue packedValue = ValueManager.Get(eventType);
			if (packedValue == null)
			{
				return null;
			}
			if (packedValue.PackedValueType == PackedValue.PackedType.Score)
			{
				PackedScore packedScore = (PackedScore)packedValue;
				return new PackedScore
				{
					eventType = packedScore.eventType,
					Stackable = packedScore.Stackable,
					DecayTime = packedScore.DecayTime,
					Name = packedScore.Name,
					Score = packedScore.Score,
					EventAudio = packedScore.EventAudio,
					TierRequirement = packedScore.TierRequirement,
					Tiers = packedScore.Tiers
				};
			}
			if (packedValue.PackedValueType == PackedValue.PackedType.Multiplier)
			{
				PackedMultiplier packedMultiplier = (PackedMultiplier)packedValue;
				return new PackedMultiplier
				{
					eventType = packedMultiplier.eventType,
					Stackable = packedMultiplier.Stackable,
					DecayTime = packedMultiplier.DecayTime,
					Name = packedMultiplier.Name,
					Multiplier = packedMultiplier.Multiplier,
					Condition = packedMultiplier.Condition,
					EventAudio = packedMultiplier.EventAudio,
					TierRequirement = packedMultiplier.TierRequirement,
					Tiers = packedMultiplier.Tiers
				};
			}
			return null;
		}

		private static void InitializeValue(PackedValue value)
		{
			value.OnValueCreated();
			value.SetDecayTime(value.DecayTime);
		}

		private static T GetClone<T>(PackedValue value) where T : PackedValue
		{
			return (T)ActiveValues.Find((PackedValue match) => match.eventType == value.eventType);
		}
	}
	public static class Settings
	{
		public static float DistanceToCamera;

		public static float MovementSmoothness;

		public static bool UseAnnouncer;

		public static string SavedHUD;

		public static HUDShowMode HUDShowMode;

		private static MelonPreferences_Category m_scorelabCategory;

		private static MelonPreferences_Entry<float> m_eDistanceToCamera;

		private static MelonPreferences_Entry<float> m_eMovementSmoothness;

		private static MelonPreferences_Entry<bool> m_eUseAnnouncer;

		private static MelonPreferences_Entry<string> m_eSavedHUD;

		private static MelonPreferences_Entry<int> m_eHudShowMode;

		public static void CreatePreferences()
		{
			m_scorelabCategory = MelonPreferences.CreateCategory("ScoreLab");
			m_eDistanceToCamera = m_scorelabCategory.CreateEntry<float>("DistanceToCamera", 1.125f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eMovementSmoothness = m_scorelabCategory.CreateEntry<float>("MovementSmoothness", 16f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eUseAnnouncer = m_scorelabCategory.CreateEntry<bool>("UseAnnouncer", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eSavedHUD = m_scorelabCategory.CreateEntry<string>("SavedHUD", "Coda", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eHudShowMode = m_scorelabCategory.CreateEntry<int>("HUDShowMode", 0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			DistanceToCamera = m_eDistanceToCamera.Value;
			MovementSmoothness = m_eMovementSmoothness.Value;
			UseAnnouncer = m_eUseAnnouncer.Value;
			SavedHUD = m_eSavedHUD.Value;
			HUDShowMode = (HUDShowMode)m_eHudShowMode.Value;
		}

		public static void Save(bool log = false)
		{
			m_eDistanceToCamera.Value = DistanceToCamera;
			m_eMovementSmoothness.Value = MovementSmoothness;
			m_eUseAnnouncer.Value = UseAnnouncer;
			m_eSavedHUD.Value = SavedHUD;
			m_scorelabCategory.SaveToFile(log);
		}

		public static void SetDistanceToCamera(float distance)
		{
			m_eDistanceToCamera.Value = distance;
		}

		public static void SetMovementSmoothness(float movementSmoothness)
		{
			m_eMovementSmoothness.Value = movementSmoothness;
		}

		public static void SetUseAnnouncer(bool useAnnouncer)
		{
			m_eUseAnnouncer.Value = useAnnouncer;
		}

		public static void SetHUDShowMode(HUDShowMode mode)
		{
			m_eHudShowMode.Value = (int)mode;
			HUDManager.HUDShowModeUpdated(mode);
		}
	}
}
namespace NEP.ScoreLab.Audio
{
	public static class AudioManager
	{
		public static void Initialize()
		{
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAdded, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAccumulated, new Action<PackedValue>(OnValueReceived));
		}

		public static void Uninitialize()
		{
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAdded, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAccumulated, new Action<PackedValue>(OnValueReceived));
		}

		private static void OnValueReceived(PackedValue value)
		{
			if (Settings.UseAnnouncer && value.EventAudio != null && value.EventAudio.Clips != null && value.EventAudio.Clips.Length != 0)
			{
				AudioClip val = null;
				if (value.EventAudio.Clips.Length == 1)
				{
					val = value.EventAudio.Clips[0];
				}
				else
				{
					int num = Random.Range(0, value.EventAudio.Clips.Length);
					val = value.EventAudio.Clips[num];
				}
				Play(val, value.EventAudio.Volume, value.EventAudio.Pitch);
			}
		}

		public static void Play(AudioClip clip, float volume = 1f, float pitch = 1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Audio.PlayAtPoint(clip, Vector3.zero, Audio.InHead, volume, pitch, 0f);
		}
	}
}

Quest/Mods/ScoreLab.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BoneLib;
using BoneLib.BoneMenu;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Bonelab;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.Interaction;
using Il2CppSLZ.Marrow.PuppetMasta;
using Il2CppSLZ.Marrow.Utilities;
using Il2CppSLZ.Marrow.Warehouse;
using Il2CppSLZ.VRMK;
using Il2CppSystem;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using NEP.ScoreLab;
using NEP.ScoreLab.Audio;
using NEP.ScoreLab.Core;
using NEP.ScoreLab.Data;
using NEP.ScoreLab.HUD;
using NEP.ScoreLab.Menu;
using NEP.ScoreLab.Patches;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "ScoreLab", "1.0.0", "Not Enough Photons", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ScoreLab")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0140fb38dafe5a3ef9669f29b961df65def51cb4")]
[assembly: AssemblyProduct("ScoreLab")]
[assembly: AssemblyTitle("ScoreLab")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace NEP.ScoreLab
{
	public static class BuildInfo
	{
		public const string Name = "ScoreLab";

		public const string Author = "Not Enough Photons";

		public const string Company = "Not Enough Photons";

		public const string Version = "1.0.0";

		public const string DownloadLink = "https://thunderstore.io/c/bonelab/p/NotEnoughPhotons/ScoreLab";
	}
	public class Main : MelonMod
	{
		internal static Instance Logger;

		public override void OnLateInitializeMelon()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			Logger = new Instance("ScoreLab");
			Settings.CreatePreferences();
			Hooks.Initialize();
			Hooks.Game.OnMarrowGameStarted = (Action)Delegate.Combine(Hooks.Game.OnMarrowGameStarted, new Action(OnMarrowGameStarted));
			Hooks.Game.OnMarrowSceneLoaded = (Action<MarrowSceneInfo>)Delegate.Combine(Hooks.Game.OnMarrowSceneLoaded, new Action<MarrowSceneInfo>(OnMarrowSceneLoaded));
			HUDLoader.Initialize();
			SLMenu.Initialize();
		}

		public void OnMarrowGameStarted()
		{
			ScoreTracker.Initialize();
			ValueManager.Initialize();
			AudioManager.Initialize();
			ScoreDirector.Patches.InitPatches();
		}

		public void OnMarrowSceneLoaded(MarrowSceneInfo sceneInfo)
		{
			HUDManager.Initialize();
			ScoreTracker.ResetAll();
		}

		public override void OnUpdate()
		{
			ScoreTracker.Update();
		}

		public override void OnDeinitializeMelon()
		{
			HUDManager.Uninitialize();
			AudioManager.Uninitialize();
			Settings.Save();
		}
	}
}
namespace NEP.ScoreLab.Patches
{
	public static class Hooks
	{
		public static class Game
		{
			public static Action OnMarrowGameStarted;

			public static Action<MarrowSceneInfo> OnMarrowSceneLoaded;

			private static MarrowSceneInfo _lastScene;

			private static MarrowSceneInfo _currentScene;

			private static MarrowSceneInfo _nextScene;

			public static void Initialize()
			{
				MarrowGame.RegisterOnReadyAction(Action.op_Implicit((Action)delegate
				{
					OnMarrowGameStarted?.Invoke();
				}));
				Hooking.OnLevelLoaded += OnSceneMarrowLoaded;
			}

			private static void OnSceneMarrowLoaded(LevelInfo info)
			{
				//IL_000a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				MarrowSceneInfo currentScene = default(MarrowSceneInfo);
				currentScene.Barcode = info.barcode;
				currentScene.LevelTitle = info.title;
				currentScene.MarrowScene = ((CrateReferenceT<LevelCrate>)(object)info.levelReference).Crate.MainScene;
				_currentScene = currentScene;
				_lastScene = _currentScene;
				OnMarrowSceneLoaded?.Invoke(_currentScene);
			}
		}

		public static void Initialize()
		{
			Game.Initialize();
		}
	}
}
namespace NEP.ScoreLab.Menu
{
	public static class SLMenu
	{
		private static Page _hudPage;

		public static void Initialize()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			Page obj = Page.Root.CreatePage("Not Enough Photons", Color.white, 0, true).CreatePage("ScoreLab", Color.white, 0, true);
			_hudPage = obj.CreatePage("HUDs", Color.white, 0, true);
			obj.CreateFloat("HUD Distance", Color.white, 1.125f, 0.025f, 0f, 2f, (Action<float>)delegate(float value)
			{
				Settings.DistanceToCamera = value;
			});
			obj.CreateEnum("Show HUD", Color.white, (Enum)Settings.HUDShowMode, (Action<Enum>)delegate(Enum value)
			{
				Settings.SetHUDShowMode((HUDShowMode)(object)value);
			});
			for (int i = 0; i < HUDLoader.LoadedHUDManifests.Count; i++)
			{
				int index = i;
				JSONHUDManifest manifest = HUDLoader.LoadedHUDManifests[index];
				_hudPage.CreateFunction(manifest.Name, Color.white, (Action)delegate
				{
					HUDManager.LoadHUD(manifest.Name);
				}).Logo = manifest.Logo;
			}
		}

		public static void RefreshHUDPage()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			_hudPage.RemoveAll();
			for (int i = 0; i < HUDLoader.LoadedHUDManifests.Count; i++)
			{
				int index = i;
				JSONHUDManifest manifest = HUDLoader.LoadedHUDManifests[index];
				_hudPage.CreateFunction(manifest.Name, Color.white, (Action)delegate
				{
					HUDManager.LoadHUD(manifest.Name);
				}).Logo = manifest.Logo;
			}
		}
	}
}
namespace NEP.ScoreLab.HUD
{
	public enum HUDShowMode
	{
		Always,
		UpdateOnly,
		Never
	}
	[RegisterTypeInIl2Cpp]
	public class Module : MonoBehaviour
	{
		public enum UIModuleType
		{
			Main,
			Descriptor
		}

		public UIModuleType ModuleType;

		private bool _reachedDecay;

		private bool _reachedPostDecay;

		public PackedValue PackedValue => _packedValue;

		public virtual PackedValue.PackedType PackedType => PackedValue.PackedType.Base;

		public virtual bool CanDecay => (Object)(object)((Component)this).transform.Find("-Persist") == (Object)null;

		public float DecayTime => _decayTime;

		public float PostDecayTime => _postDecayTime;

		protected TextMeshProUGUI _title { get; private set; }

		protected TextMeshProUGUI _value { get; private set; }

		protected Slider _timeBar { get; private set; }

		protected PackedValue _packedValue { get; private set; }

		protected bool _canDecay { get; private set; }

		protected bool _decayed { get; private set; }

		protected float _decayTime { get; private set; }

		protected float _postDecayTime { get; private set; }

		protected float _tDecay { get; private set; }

		protected float _tPostDecay { get; private set; }

		private string Path_Root => ((Object)this).name;

		protected virtual string Path_TitleText => "Title";

		protected virtual string Path_ValueText => "Value";

		protected virtual string Path_TimeBar => "TimeBar";

		public Module(IntPtr ptr)
			: base(ptr)
		{
		}

		public virtual void OnModuleEnable()
		{
			API.UI.OnModuleEnabled?.Invoke(this);
		}

		public virtual void OnModuleDisable()
		{
			API.UI.OnModuleDisabled?.Invoke(this);
		}

		public virtual void OnUpdate()
		{
		}

		public void AssignPackedData(PackedValue packedValue)
		{
			if (packedValue != null)
			{
				_packedValue = packedValue;
				if (_packedValue.DecayTime != 0f)
				{
					SetDecayTime(_packedValue.DecayTime);
				}
			}
		}

		public void SetDecayTime(float decayTime)
		{
			_decayTime = decayTime;
			_tDecay = _decayTime;
		}

		public void SetPostDecayTime(float postDecayTime)
		{
			_postDecayTime = postDecayTime;
			_tPostDecay = _postDecayTime;
		}

		public bool IsDecaying()
		{
			return _reachedDecay;
		}

		public bool IsDecayed()
		{
			return _reachedPostDecay;
		}

		protected void SetText(TextMeshProUGUI text, string value)
		{
			if (!((Object)(object)text == (Object)null))
			{
				((TMP_Text)text).text = value;
			}
		}

		protected void SetText(TextMeshProUGUI text, int value)
		{
			if (!((Object)(object)text == (Object)null))
			{
				SetText(text, value.ToString());
			}
		}

		protected void SetText(TextMeshProUGUI text, float value)
		{
			if (!((Object)(object)text == (Object)null))
			{
				SetText(text, value.ToString());
			}
		}

		protected void SetBarValue(Slider timeBar, float value)
		{
			timeBar.value = value;
		}

		protected void SetMaxValueToBar(Slider timeBar, float value)
		{
			if (!((Object)(object)timeBar == (Object)null))
			{
				timeBar.maxValue = value;
			}
		}

		protected void UpdateDecay()
		{
			if (!CanDecay)
			{
				return;
			}
			if (_tDecay < 0f)
			{
				if (!_reachedDecay)
				{
					API.UI.OnModuleDecayed?.Invoke(this);
					_reachedDecay = true;
				}
				_tPostDecay -= Time.deltaTime;
				if (_tPostDecay < 0f)
				{
					if (!_reachedPostDecay)
					{
						API.UI.OnModulePostDecayed?.Invoke(this);
						_reachedPostDecay = true;
					}
					_tDecay = _decayTime;
					_tPostDecay = _postDecayTime;
					_reachedDecay = false;
					_reachedPostDecay = false;
					((Component)this).gameObject.SetActive(false);
				}
			}
			else
			{
				_tDecay -= Time.deltaTime;
			}
		}

		private void Start()
		{
			Transform val = ((Component)this).transform.Find(Path_TitleText);
			Transform val2 = ((Component)this).transform.Find(Path_ValueText);
			Transform val3 = ((Component)this).transform.Find(Path_TimeBar);
			_title = ((val != null) ? ((Component)val).GetComponent<TextMeshProUGUI>() : null);
			_value = ((val2 != null) ? ((Component)val2).GetComponent<TextMeshProUGUI>() : null);
			_timeBar = ((val3 != null) ? ((Component)val3).GetComponent<Slider>() : null);
		}

		private void OnEnable()
		{
			OnModuleEnable();
		}

		private void OnDisable()
		{
			OnModuleEnable();
		}

		private void Update()
		{
			OnUpdate();
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ModuleAnimator : MonoBehaviour
	{
		public Animator Animator;

		private Module _module;

		public ModuleAnimator(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			_module = ((Component)this).GetComponent<Module>();
			Animator = ((Component)this).GetComponent<Animator>();
		}

		private void OnEnable()
		{
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, (Action<PackedValue>)delegate
			{
				OnTierReached();
			});
			API.UI.OnModuleDecayed = (Action<Module>)Delegate.Combine(API.UI.OnModuleDecayed, new Action<Module>(OnModuleDecayed));
		}

		private void OnDisable()
		{
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, (Action<PackedValue>)delegate
			{
				OnTierReached();
			});
			API.UI.OnModuleDecayed = (Action<Module>)Delegate.Remove(API.UI.OnModuleDecayed, new Action<Module>(OnModuleDecayed));
		}

		private void PlayAnimation(string name)
		{
			if (!((Object)(object)Animator == (Object)null))
			{
				Animator.Play(name, -1, 0f);
			}
		}

		private void OnModuleEnabled(Module module)
		{
			if (!((Object)(object)_module != (Object)(object)module))
			{
				if (_module.ModuleType == Module.UIModuleType.Descriptor)
				{
					PlayAnimation("descriptor_show");
				}
				else
				{
					PlayAnimation("show");
				}
			}
		}

		private void OnTierReached()
		{
			PlayAnimation("tier_reached");
		}

		private void OnModuleDecayed(Module module)
		{
			if (!((Object)(object)_module != (Object)(object)module))
			{
				if (_module.ModuleType == Module.UIModuleType.Descriptor)
				{
					PlayAnimation("descriptor_hide");
				}
				else
				{
					PlayAnimation("hide");
				}
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	public class MultiplierModule : Module
	{
		private float _currentValue;

		private float _targetValue;

		private float _rate;

		private PackedMultiplier _packedMultiplier => (PackedMultiplier)base._packedValue;

		public MultiplierModule(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if (((Object)this).name == "MultiplierDescriptor" || ((Object)this).name == "Descriptor")
			{
				ModuleType = UIModuleType.Descriptor;
			}
		}

		public override void OnModuleEnable()
		{
			base.OnModuleEnable();
			if (base._packedValue == null || _packedMultiplier == null)
			{
				return;
			}
			if (ModuleType == UIModuleType.Main)
			{
				SetText(base._value, ScoreTracker.Multiplier + "x");
			}
			else if (ModuleType == UIModuleType.Descriptor)
			{
				SetText(base._title, _packedMultiplier.Name);
				SetText(base._value, _packedMultiplier.Multiplier + "x");
			}
			if ((Object)(object)base._timeBar != (Object)null)
			{
				if (_packedMultiplier.Condition != string.Empty)
				{
					((Component)base._timeBar).gameObject.SetActive(false);
					return;
				}
				((Component)base._timeBar).gameObject.SetActive(true);
				SetMaxValueToBar(base._timeBar, _packedMultiplier.DecayTime);
				SetBarValue(base._timeBar, _packedMultiplier.DecayTime);
			}
		}

		public override void OnModuleDisable()
		{
		}

		public override void OnUpdate()
		{
			if (ModuleType == UIModuleType.Main)
			{
				SetTweenValue(ScoreTracker.Multiplier);
				_currentValue = Mathf.MoveTowards(_currentValue, _targetValue, _rate * Time.unscaledDeltaTime);
				if (Mathf.Approximately(_currentValue, _targetValue))
				{
					_currentValue = _targetValue;
				}
				SetText(base._value, _currentValue.ToString("F2"));
			}
			if (_packedMultiplier != null)
			{
				if (_packedMultiplier.condition != null)
				{
					if (!_packedMultiplier.condition())
					{
						UpdateDecay();
					}
				}
				else
				{
					UpdateDecay();
				}
			}
			else
			{
				UpdateDecay();
			}
			if ((Object)(object)base._timeBar != (Object)null)
			{
				SetBarValue(base._timeBar, base._tDecay);
			}
		}

		private void SetTweenValue(float value)
		{
			_targetValue = value;
			_rate = Mathf.Abs(_targetValue - _currentValue) / 1f;
		}
	}
	[RegisterTypeInIl2Cpp]
	public class ScoreModule : Module
	{
		private float _targetValue;

		private float _currentValue;

		private float _rate = 4f;

		private PackedScore _packedScore => (PackedScore)base._packedValue;

		public ScoreModule(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if (((Object)this).name == "ScoreDescriptor" || ((Object)this).name == "Descriptor")
			{
				ModuleType = UIModuleType.Descriptor;
			}
		}

		public override void OnModuleEnable()
		{
			base.OnModuleEnable();
			if (ModuleType == UIModuleType.Main)
			{
				SetText(base._value, ScoreTracker.Score);
			}
			if (base._packedValue != null && ModuleType == UIModuleType.Descriptor)
			{
				SetText(base._title, _packedScore.Name);
				SetText(base._value, $"+{Mathf.RoundToInt((float)_packedScore.Score * ScoreTracker.Multiplier)}");
			}
		}

		public override void OnModuleDisable()
		{
		}

		public override void OnUpdate()
		{
			UpdateDecay();
			if (ModuleType == UIModuleType.Main)
			{
				SetTweenValue(ScoreTracker.Score);
				_currentValue = Mathf.MoveTowards(_currentValue, _targetValue, _rate * Time.unscaledDeltaTime);
				if (Mathf.Approximately(_currentValue, _targetValue))
				{
					_currentValue = _targetValue;
				}
				SetText(base._value, _currentValue.ToString("N0"));
			}
		}

		private void SetTweenValue(int value)
		{
			_targetValue = value;
			_rate = Mathf.Abs(_targetValue - _currentValue) / 1f;
		}
	}
	[RegisterTypeInIl2Cpp]
	public class HUD : MonoBehaviour
	{
		public Transform followTarget;

		public Module ScoreModule { get; set; }

		public Module MultiplierModule { get; set; }

		public Module HighScoreModule { get; set; }

		public HUD(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			if ((Object)(object)((Component)this).transform.Find("MainScore") != (Object)null)
			{
				ScoreModule = ((Component)((Component)this).transform.Find("MainScore")).GetComponent<ScoreModule>();
			}
			if (Object.op_Implicit((Object)(object)((Component)this).transform.Find("MainMultiplier")))
			{
				MultiplierModule = ((Component)((Component)this).transform.Find("MainMultiplier")).GetComponent<MultiplierModule>();
			}
		}

		private void OnEnable()
		{
			UpdateModule(null);
			UpdateModule(null);
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAdded, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAccumulated, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueRemoved = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueRemoved, new Action<PackedValue>(UpdateModule));
		}

		private void OnDisable()
		{
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAdded, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAccumulated, new Action<PackedValue>(UpdateModule));
			API.Value.OnValueRemoved = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueRemoved, new Action<PackedValue>(UpdateModule));
		}

		private void Start()
		{
			if ((Object)(object)Player.GetPhysicsRig() != (Object)null)
			{
				followTarget = ((Rig)Player.ControllerRig).m_head;
			}
		}

		private void FixedUpdate()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: 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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)followTarget == (Object)null))
			{
				Vector3 position = Vector3.Lerp(((Component)this).transform.position, followTarget.position + followTarget.forward * Settings.DistanceToCamera, Settings.MovementSmoothness * Time.unscaledDeltaTime);
				Quaternion rotation = Quaternion.LookRotation(followTarget.forward);
				((Component)this).transform.position = position;
				((Component)this).transform.rotation = rotation;
			}
		}

		public void SetParent(Transform parent)
		{
			((Component)this).transform.SetParent(parent);
		}

		public void SetScoreModule(Module module)
		{
			ScoreModule = module;
		}

		public void SetMultiplierModule(Module module)
		{
			MultiplierModule = module;
		}

		public void UpdateModule(PackedValue data)
		{
			if (data is PackedScore)
			{
				ScoreModule.AssignPackedData(data);
				ScoreModule.OnModuleEnable();
			}
			else if (data is PackedMultiplier)
			{
				MultiplierModule.AssignPackedData(data);
				MultiplierModule.OnModuleEnable();
			}
		}
	}
	[RegisterTypeInIl2Cpp]
	public class DescriptorList : MonoBehaviour
	{
		public List<Module> ActiveModules;

		public int count = 6;

		public List<Module> Modules;

		public PackedValue.PackedType packedType { get; set; }

		public GameObject ModulePrefab { get; set; }

		public DescriptorList(IntPtr ptr)
			: base(ptr)
		{
		}

		private void Awake()
		{
			Modules = new List<Module>();
			ActiveModules = new List<Module>();
			for (int i = 0; i < ((Component)this).transform.childCount; i++)
			{
				Transform child = ((Component)this).transform.GetChild(i);
				Modules.Add(((Component)child).GetComponent<Module>());
			}
			if (((Object)this).name == "ScoreDescriptors")
			{
				packedType = PackedValue.PackedType.Score;
			}
			else if (((Object)this).name == "MultiplierDescriptors")
			{
				packedType = PackedValue.PackedType.Multiplier;
			}
		}

		private void OnEnable()
		{
			API.UI.OnModulePostDecayed = (Action<Module>)Delegate.Combine(API.UI.OnModulePostDecayed, (Action<Module>)delegate(Module item)
			{
				ActiveModules.Remove(item);
			});
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAdded, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAccumulated, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, new Action<PackedValue>(SetModuleActive));
		}

		private void OnDisable()
		{
			API.UI.OnModulePostDecayed = (Action<Module>)Delegate.Remove(API.UI.OnModulePostDecayed, (Action<Module>)delegate(Module item)
			{
				ActiveModules.Remove(item);
			});
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAdded, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAccumulated, new Action<PackedValue>(SetModuleActive));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, new Action<PackedValue>(SetModuleActive));
		}

		public void SetPackedType(int packedType)
		{
			this.packedType = (PackedValue.PackedType)packedType;
		}

		public void SetModuleActive(PackedValue value)
		{
			if (Modules == null || Modules.Count == 0 || value.PackedValueType != packedType)
			{
				return;
			}
			foreach (Module module in Modules)
			{
				if (!((Component)module).gameObject.activeInHierarchy)
				{
					module.AssignPackedData(value);
					module.SetDecayTime(value.DecayTime);
					module.SetPostDecayTime(0.5f);
					((Component)module).gameObject.SetActive(true);
					ActiveModules.Add(module);
					break;
				}
				if (ActiveModules.Contains(module) && !module.IsDecaying() && module.PackedValue.eventType == value.eventType)
				{
					if (value.Stackable)
					{
						module.AssignPackedData(value);
						module.OnModuleEnable();
						module.SetDecayTime(value.DecayTime);
						module.SetPostDecayTime(0.5f);
						break;
					}
					if (value.Tiers != null)
					{
						module.AssignPackedData(value);
						module.OnModuleEnable();
						module.SetDecayTime(value.DecayTime);
						module.SetPostDecayTime(0.5f);
						break;
					}
				}
			}
		}

		public void PoolObjects()
		{
			if (!((Object)(object)ModulePrefab == (Object)null))
			{
				for (int i = 0; i < count; i++)
				{
					Module component = Object.Instantiate<GameObject>(ModulePrefab, ((Component)this).transform).GetComponent<Module>();
					component.ModuleType = Module.UIModuleType.Descriptor;
					Modules.Add(component);
				}
			}
		}
	}
	public static class HUDManager
	{
		private static GameObject _parentObject;

		public static List<HUD> LoadedHUDs { get; private set; }

		public static HUD ActiveHUD { get; private set; }

		public static HUD LastHUD { get; private set; }

		internal static void Initialize()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			_parentObject = new GameObject("[ScoreLab] - HUD Container");
			LoadedHUDs = new List<HUD>();
			Populate();
			if (HUDLoader.LoadedHUDs.ContainsKey(Settings.SavedHUD))
			{
				LoadHUD(Settings.SavedHUD);
			}
			else
			{
				LoadHUD("Coda");
			}
		}

		internal static void Uninitialize()
		{
		}

		public static void Populate()
		{
			for (int i = 0; i < HUDLoader.LoadedHUDManifests.Count; i++)
			{
				JSONHUDManifest jSONHUDManifest = HUDLoader.LoadedHUDManifests[i];
				GameObject obj = Object.Instantiate<GameObject>(HUDLoader.LoadedHUDs[jSONHUDManifest.Name]);
				((Object)obj).name = jSONHUDManifest.Name;
				HUD component = obj.GetComponent<HUD>();
				if (!((Object)(object)component == (Object)null))
				{
					LoadedHUDs.Add(component);
					component.SetParent(_parentObject.transform);
					((Component)component).gameObject.SetActive(false);
				}
			}
		}

		public static void HUDShowModeUpdated(HUDShowMode mode)
		{
			if (!((Object)(object)ActiveHUD == (Object)null))
			{
				switch (mode)
				{
				case HUDShowMode.Always:
					((Component)ActiveHUD).gameObject.SetActive(true);
					break;
				case HUDShowMode.Never:
					((Component)ActiveHUD).gameObject.SetActive(false);
					break;
				}
			}
		}

		public static void LoadHUD(string name)
		{
			if ((Object)(object)ActiveHUD != (Object)null)
			{
				LastHUD = ActiveHUD;
			}
			UnloadHUD();
			foreach (HUD loadedHUD in LoadedHUDs)
			{
				if (((Object)loadedHUD).name == name)
				{
					ActiveHUD = loadedHUD;
					break;
				}
			}
			if (!((Object)(object)ActiveHUD == (Object)null))
			{
				Settings.SavedHUD = name;
				ValueManager.UsePackage(name);
				((Component)ActiveHUD).gameObject.SetActive(true);
				ActiveHUD.SetParent(null);
			}
		}

		public static void UnloadHUD()
		{
			if ((Object)(object)ActiveHUD != (Object)null)
			{
				ActiveHUD.SetParent(_parentObject.transform);
				((Component)ActiveHUD).gameObject.SetActive(false);
				ActiveHUD = null;
			}
		}

		public static void DestroyHUD()
		{
			if ((Object)(object)ActiveHUD != (Object)null)
			{
				Object.Destroy((Object)(object)ActiveHUD);
				ActiveHUD = null;
			}
		}

		public static void DestroyLoadedHUDs()
		{
			if (LoadedHUDs == null || LoadedHUDs.Count == 0)
			{
				return;
			}
			foreach (HUD loadedHUD in LoadedHUDs)
			{
				Object.Destroy((Object)(object)((Component)loadedHUD).gameObject);
			}
			LoadedHUDs.Clear();
		}
	}
}
namespace NEP.ScoreLab.Data
{
	public static class HUDLoader
	{
		public static Dictionary<string, AudioClip> HUDAudioBank;

		public static Dictionary<string, GameObject> LoadedHUDs;

		public static List<JSONHUDManifest> LoadedHUDManifests;

		private static List<AssetBundle> _assetBundles;

		private static List<Object> _persistentBundleObjects;

		public static void Initialize()
		{
			LoadedHUDs = new Dictionary<string, GameObject>();
			HUDAudioBank = new Dictionary<string, AudioClip>();
			LoadedHUDManifests = new List<JSONHUDManifest>();
			_persistentBundleObjects = new List<Object>();
			_assetBundles = new List<AssetBundle>();
			LoadHUDs();
		}

		public static void SpawnDefaultUI()
		{
			SpawnUI("Coda");
		}

		public static void SpawnUI(string name)
		{
			foreach (JSONHUDManifest loadedHUDManifest in LoadedHUDManifests)
			{
				if (loadedHUDManifest.Name == name)
				{
					SpawnUI(LoadedHUDs[name]);
				}
			}
		}

		public static void SpawnUI(GameObject uiObject)
		{
			Object.Instantiate<GameObject>(uiObject);
		}

		public static void LoadHUDs()
		{
			foreach (string item2 in Directory.EnumerateDirectories(Path.Combine(MelonEnvironment.UserDataDirectory, "Not Enough Photons/ScoreLab")))
			{
				IEnumerable<string> enumerable = Directory.EnumerateFiles(item2);
				string text = string.Empty;
				string text2 = string.Empty;
				foreach (string item3 in enumerable)
				{
					if (item3.EndsWith(".hud"))
					{
						text = item3;
					}
					if (item3.EndsWith(".hud_manifest"))
					{
						text2 = item3;
					}
				}
				if (text == string.Empty)
				{
					Main.Logger.Error("Missing .HUD file in " + item2 + "!");
					continue;
				}
				if (text2 == string.Empty)
				{
					Main.Logger.Error("Missing HUD manifest file in " + item2 + "!");
					continue;
				}
				JSONHUDManifest item = default(JSONHUDManifest);
				if (!item.FromJSON(text2))
				{
					Main.Logger.Error("Failed to read HUD manifest data! Source: " + item2);
					continue;
				}
				AssetBundle val = AssetBundle.LoadFromFile(text);
				GameObject value = HelperMethods.LoadPersistentAsset<GameObject>(val, item.AssetName);
				Il2CppReferenceArray<Object> val2 = val.LoadAllAssets();
				Texture2D val3 = HelperMethods.LoadPersistentAsset<Texture2D>(val, "Logo");
				if ((Object)(object)val3 != (Object)null)
				{
					item.SetHUDLogo(val3);
				}
				_assetBundles.Add(val);
				LoadedHUDManifests.Add(item);
				LoadedHUDs.Add(item.Name, value);
				if (val2 == null || ((Il2CppArrayBase<Object>)(object)val2).Length == 0)
				{
					continue;
				}
				foreach (Object item4 in (Il2CppArrayBase<Object>)(object)val2)
				{
					AudioClip val4 = ((Il2CppObjectBase)item4).TryCast<AudioClip>();
					if ((Object)(object)val4 != (Object)null)
					{
						((Object)val4).hideFlags = (HideFlags)32;
						HUDAudioBank.Add(item4.name, val4);
					}
				}
			}
		}

		public static void ReloadHUDs()
		{
			if ((Object)(object)HUDManager.ActiveHUD != (Object)null)
			{
				HUDManager.DestroyHUD();
			}
			HUDManager.DestroyLoadedHUDs();
			HUDAudioBank.Clear();
			LoadedHUDManifests.Clear();
			LoadedHUDs.Clear();
			foreach (AssetBundle assetBundle in _assetBundles)
			{
				assetBundle.Unload(true);
			}
			_assetBundles.Clear();
			LoadHUDs();
			SLMenu.RefreshHUDPage();
			HUDManager.Populate();
			HUDManager.LoadHUD(Settings.SavedHUD);
		}
	}
	public struct JSONAudioParams
	{
		public string[] sounds;

		public float volume;

		public float pitch;

		public bool FromJSON(JObject jObject)
		{
			if (jObject == null)
			{
				return false;
			}
			JToken obj = jObject["Clips"];
			JArray val = (JArray)(object)((obj is JArray) ? obj : null);
			if (val != null)
			{
				sounds = new string[((JContainer)val).Count];
				for (int i = 0; i < sounds.Length; i++)
				{
					sounds[i] = Extensions.Value<string>((IEnumerable<JToken>)val[i]);
				}
			}
			volume = Extensions.Value<float>((IEnumerable<JToken>)jObject["Volume"]);
			pitch = Extensions.Value<float>((IEnumerable<JToken>)jObject["Pitch"]);
			return true;
		}
	}
	public struct JSONHUDManifest
	{
		public string Name;

		public string Author;

		public string Description;

		public string[] Tags;

		public string AssetName;

		public Texture2D Logo;

		public bool FromJSON(string pathToJson)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using (StreamReader streamReader = new StreamReader(pathToJson))
			{
				JsonTextReader val = new JsonTextReader((TextReader)streamReader);
				try
				{
					JToken obj = JToken.ReadFrom((JsonReader)(object)val);
					JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
					if (val2 == null)
					{
						return false;
					}
					Name = Extensions.Value<string>((IEnumerable<JToken>)val2["name"]);
					Author = Extensions.Value<string>((IEnumerable<JToken>)val2["author"]);
					AssetName = Extensions.Value<string>((IEnumerable<JToken>)val2["assetName"]);
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			return true;
		}

		public void SetHUDLogo(Texture2D texture)
		{
			Logo = texture;
		}
	}
	public struct JSONMult
	{
		public string EventType;

		public string TierEventType;

		public float DecayTime;

		public bool Stackable;

		public JSONAudioParams EventAudio;

		public string Name;

		public float Multiplier;

		public string Condition;

		public int TierRequirement;

		public JSONMult[] Tiers;

		public bool FromJSON(string pathToJson)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using (StreamReader streamReader = new StreamReader(pathToJson))
			{
				JsonTextReader val = new JsonTextReader((TextReader)streamReader);
				try
				{
					JToken obj = JToken.ReadFrom((JsonReader)(object)val);
					JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
					if (val2 == null)
					{
						return false;
					}
					ReadMultObject(val2);
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			return true;
		}

		private void ReadMultObject(JObject obj)
		{
			EventType = Extensions.Value<string>((IEnumerable<JToken>)obj["EventType"]);
			DecayTime = Extensions.Value<float>((IEnumerable<JToken>)obj["DecayTime"]);
			Stackable = Extensions.Value<bool>((IEnumerable<JToken>)obj["Stackable"]);
			Condition = Extensions.Value<string>((IEnumerable<JToken>)obj["Condition"]);
			EventAudio.FromJSON(Extensions.Value<JObject>((IEnumerable<JToken>)obj["EventAudio"]));
			Name = Extensions.Value<string>((IEnumerable<JToken>)obj["Name"]);
			Multiplier = Extensions.Value<float>((IEnumerable<JToken>)obj["Multiplier"]);
			TierRequirement = Extensions.Value<int>((IEnumerable<JToken>)obj["TierRequirement"]);
			JToken obj2 = obj["Tiers"];
			JArray val = ((obj2 != null) ? Extensions.Value<JArray>((IEnumerable<JToken>)obj2) : null);
			List<JSONMult> list = new List<JSONMult>();
			if (val != null)
			{
				for (int i = 0; i < ((JContainer)val).Count; i++)
				{
					JSONMult item = default(JSONMult);
					JToken obj3 = val[i];
					JObject obj4 = (JObject)(object)((obj3 is JObject) ? obj3 : null);
					item.ReadMultObject(obj4);
					list.Add(item);
				}
				Tiers = list.ToArray();
			}
		}
	}
	public struct JSONScore
	{
		public string EventType;

		public string TierEventType;

		public float DecayTime;

		public bool Stackable;

		public JSONAudioParams EventAudio;

		public string Name;

		public int Score;

		public int TierRequirement;

		public JSONScore[] Tiers;

		public bool FromJSON(string pathToJson)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Expected O, but got Unknown
			using (StreamReader streamReader = new StreamReader(pathToJson))
			{
				JsonTextReader val = new JsonTextReader((TextReader)streamReader);
				try
				{
					JToken obj = JToken.ReadFrom((JsonReader)(object)val);
					JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
					if (val2 == null)
					{
						return false;
					}
					ReadScoreObject(val2);
				}
				finally
				{
					((IDisposable)val)?.Dispose();
				}
			}
			return true;
		}

		private void ReadScoreObject(JObject obj)
		{
			EventType = Extensions.Value<string>((IEnumerable<JToken>)obj["EventType"]);
			DecayTime = Extensions.Value<float>((IEnumerable<JToken>)obj["DecayTime"]);
			Stackable = Extensions.Value<bool>((IEnumerable<JToken>)obj["Stackable"]);
			EventAudio.FromJSON(Extensions.Value<JObject>((IEnumerable<JToken>)obj["EventAudio"]));
			Name = Extensions.Value<string>((IEnumerable<JToken>)obj["Name"]);
			Score = Extensions.Value<int>((IEnumerable<JToken>)obj["Score"]);
			TierRequirement = Extensions.Value<int>((IEnumerable<JToken>)obj["TierRequirement"]);
			JToken obj2 = obj["Tiers"];
			JArray val = ((obj2 != null) ? Extensions.Value<JArray>((IEnumerable<JToken>)obj2) : null);
			List<JSONScore> list = new List<JSONScore>();
			if (val != null)
			{
				for (int i = 0; i < ((JContainer)val).Count; i++)
				{
					JSONScore item = default(JSONScore);
					JToken obj3 = val[i];
					JObject obj4 = (JObject)(object)((obj3 is JObject) ? obj3 : null);
					item.ReadScoreObject(obj4);
					list.Add(item);
				}
				Tiers = list.ToArray();
			}
		}
	}
	public struct MarrowSceneInfo
	{
		public string LevelTitle;

		public string Barcode;

		public MarrowScene MarrowScene;
	}
	public static class EventType
	{
		public static class Score
		{
			public static readonly string Kill = "SCORE_KILL";

			public static readonly string Headshot = "SCORE_HEADSHOT";

			public static readonly string EnemyMidAirKill = "SCORE_MID_AIR";

			public static readonly string GameWaveCompleted = "SCORE_WAVE_COMPLETED";

			public static readonly string GameRoundCompleted = "SCORE_ROUND_COMPLETED";

			public static readonly string Crabcest = "SCORE_CRABCEST";

			public static readonly string Facehug = "SCORE_FACEHUG";

			public static readonly string StealthKill = "SCORE_STEALTH_KILL";
		}

		public static class Mult
		{
			public static readonly string Kill = "MULT_KILL";

			public static readonly string MidAir = "MULT_MIDAIR";

			public static readonly string Seated = "MULT_SEATED";

			public static readonly string SecondWind = "MULT_SECONDWIND";

			public static readonly string Ragolled = "MULT_RAGDOLLED";

			public static readonly string SwappedAvatars = "MULT_SWAPPED_AVATARS";

			public static readonly string SlowMo = "MULT_SLOWMO";
		}

		public static readonly string None = "None";
	}
	public class PackedAudioParams
	{
		public AudioClip[] Clips { get; private set; }

		public float Volume { get; private set; }

		public float Pitch { get; private set; }

		public PackedAudioParams()
		{
			Clips = null;
			Volume = 1f;
			Pitch = 1f;
		}

		public PackedAudioParams(JSONAudioParams audioParams)
		{
			Clips = (AudioClip[])(object)new AudioClip[audioParams.sounds.Length];
			for (int i = 0; i < Clips.Length; i++)
			{
				Clips[i] = HUDLoader.HUDAudioBank[audioParams.sounds[i]];
			}
			Volume = audioParams.volume;
			Pitch = audioParams.pitch;
		}
	}
	public class PackedHighScore : PackedValue
	{
		public int bestScore;

		public override PackedType PackedValueType => PackedType.HighScore;

		public PackedHighScore(string name, int bestScore)
		{
			this.bestScore = bestScore;
		}

		public override void OnValueCreated()
		{
		}

		public override void OnValueRemoved()
		{
		}
	}
	[Serializable]
	public class PackedMultiplier : PackedValue
	{
		public float Multiplier;

		public float AccumulatedMultiplier;

		public string Condition;

		private bool _timed;

		private bool _timeBegin;

		public override PackedType PackedValueType => PackedType.Multiplier;

		public float Elapsed => _tDecay;

		public Func<bool> condition { get; private set; }

		public PackedMultiplier()
		{
		}

		public PackedMultiplier(JSONMult mult, bool useTiers = false)
		{
			eventType = mult.EventType;
			DecayTime = mult.DecayTime;
			Stackable = mult.Stackable;
			Name = mult.Name;
			Multiplier = mult.Multiplier;
			Condition = mult.Condition;
			TierRequirement = mult.TierRequirement;
			EventAudio = new PackedAudioParams(mult.EventAudio);
			if (useTiers)
			{
				TierEventType = mult.TierEventType;
			}
		}

		public override void OnValueCreated()
		{
			if (DecayTime != 0f)
			{
				_timed = true;
			}
			condition = API.GameConditions.GetCondition(Condition);
			AccumulatedMultiplier = Multiplier;
			_tDecay = DecayTime;
		}

		public override void OnValueRemoved()
		{
			_timeBegin = false;
			ResetTier();
		}

		public override void OnUpdate()
		{
			if (condition != null && !condition())
			{
				ScoreTracker.Remove(this);
			}
			OnUpdateDecay();
		}

		public override void OnUpdateDecay()
		{
			if (_timed)
			{
				if (!_timeBegin)
				{
					API.Multiplier.OnMultiplierTimeBegin?.Invoke(this);
					_timeBegin = true;
				}
				if (_tDecay <= 0f)
				{
					API.Multiplier.OnMultiplierTimeExpired?.Invoke(this);
					_tDecay = DecayTime;
					ScoreTracker.Remove(this);
				}
				_tDecay -= Time.deltaTime;
			}
		}
	}
	[Serializable]
	public class PackedScore : PackedValue
	{
		public int Score;

		public int AccumulatedScore;

		public override PackedType PackedValueType => PackedType.Score;

		public PackedScore()
		{
		}

		public PackedScore(JSONScore score, bool useTiers = false)
		{
			eventType = score.EventType;
			DecayTime = score.DecayTime;
			Stackable = score.Stackable;
			Name = score.Name;
			Score = score.Score;
			TierRequirement = score.TierRequirement;
			EventAudio = new PackedAudioParams(score.EventAudio);
			if (useTiers)
			{
				TierEventType = score.TierEventType;
			}
			else
			{
				AccumulatedScore = score.Score;
			}
		}

		public override void OnValueCreated()
		{
			_tDecay = DecayTime;
			AccumulatedScore = Score;
		}

		public override void OnValueRemoved()
		{
			ResetTier();
		}

		public override void OnUpdate()
		{
			OnUpdateDecay();
		}

		public override void OnUpdateDecay()
		{
			if (_tDecay <= 0f)
			{
				ScoreTracker.Remove(this);
			}
			_tDecay -= Time.deltaTime;
		}
	}
	[Serializable]
	public class PackedValue
	{
		public enum PackedType
		{
			Base,
			Score,
			Multiplier,
			HighScore,
			Misc
		}

		public string Name;

		public string eventType;

		public string TierEventType;

		public PackedAudioParams EventAudio;

		public bool Stackable;

		public float DecayTime;

		public float PostDecayTime;

		public PackedValue Parent;

		public PackedValue[] Tiers;

		public int TierRequirement;

		protected float _tDecay;

		private int _tierIndex;

		private int _tierRequirementIndex;

		public virtual PackedType PackedValueType => PackedType.Base;

		public PackedValue CurrentTier
		{
			get
			{
				if (Tiers == null || Tiers.Length == 0)
				{
					return this;
				}
				if (_tierIndex == Tiers.Length)
				{
					_tierIndex = Tiers.Length;
					return Tiers[_tierIndex];
				}
				return Tiers[_tierIndex];
			}
		}

		public PackedValue NextTier
		{
			get
			{
				if (_tierIndex + 1 >= Tiers.Length)
				{
					return Tiers[_tierIndex];
				}
				return Tiers[_tierIndex + 1];
			}
		}

		public int TierIndex => _tierIndex;

		public int TierRequirementIndex => _tierRequirementIndex;

		public virtual bool IsActive { get; }

		public virtual void OnValueCreated()
		{
		}

		public virtual void OnValueRemoved()
		{
		}

		public virtual void OnUpdate()
		{
		}

		public virtual void OnUpdateDecay()
		{
		}

		public void SetDecayTime(float decayTime)
		{
			_tDecay = decayTime;
		}

		public void ToNextTier()
		{
			_tierRequirementIndex++;
			if (_tierRequirementIndex >= TierRequirement)
			{
				_tierRequirementIndex = TierRequirement;
				API.Value.OnValueTierReached?.Invoke(CurrentTier);
				if (_tierIndex + 1 < Tiers.Length)
				{
					_tierIndex++;
				}
			}
		}

		protected void ResetTier()
		{
			_tierIndex = 0;
		}
	}
	public static class ValueManager
	{
		public static Dictionary<string, int> HighScoreTable;

		public static readonly string Path_Developer = Path.Combine(MelonEnvironment.UserDataDirectory, "Not Enough Photons");

		public static readonly string Path_Mod = Path.Combine(Path_Developer, "ScoreLab");

		private static readonly string File_HighScores = Path.Combine(Path_Mod, "high_score_table.json");

		public static Dictionary<string, ValuePackage> Packages { get; private set; }

		public static ValuePackage ActivePackage { get; private set; }

		public static void Initialize()
		{
			HighScoreTable = new Dictionary<string, int>();
			Packages = new Dictionary<string, ValuePackage>();
			foreach (JSONHUDManifest loadedHUDManifest in HUDLoader.LoadedHUDManifests)
			{
				JSONScore[] scoresForHUD = GetScoresForHUD(loadedHUDManifest.Name);
				JSONMult[] multipliersForHUD = GetMultipliersForHUD(loadedHUDManifest.Name);
				PackedScore[] scores = CreateScoreObjects(scoresForHUD);
				PackedMultiplier[] multipliers = CreateMultiplierObjects(multipliersForHUD);
				Packages.Add(loadedHUDManifest.Name, new ValuePackage(scores, multipliers));
			}
			UsePackage(Settings.SavedHUD);
		}

		public static string[] GetAllFiles(string path, string extensionFilter)
		{
			string[] files = Directory.GetFiles(path);
			List<string> list = new List<string>();
			string[] array = files;
			foreach (string text in array)
			{
				if (text.EndsWith(extensionFilter))
				{
					list.Add(text);
				}
			}
			return list.ToArray();
		}

		public static void UsePackage(string name)
		{
			if (Packages.TryGetValue(name, out var value))
			{
				ActivePackage = value;
			}
		}

		public static PackedValue Get(string eventType)
		{
			if (ActivePackage.Values == null)
			{
				return null;
			}
			if (ActivePackage.Values.TryGetValue(eventType, out var value))
			{
				return value;
			}
			return null;
		}

		public static Dictionary<string, int> ReadHighScore()
		{
			return JsonConvert.DeserializeObject(File_HighScores) as Dictionary<string, int>;
		}

		public static void WriteHighScore()
		{
			string file_HighScores = File_HighScores;
			if (!File.Exists(file_HighScores))
			{
				Main.Logger.Warning("High score file doesn't exist! Creating one.");
				File.Create(file_HighScores);
			}
			else
			{
				string contents = JsonConvert.SerializeObject((object)HighScoreTable);
				File.WriteAllText(file_HighScores, contents);
			}
		}

		public static void WriteBestScore(PackedHighScore highScore)
		{
			string name = highScore.Name;
			int bestScore = highScore.bestScore;
			HighScoreTable.Add(name, bestScore);
		}

		private static JSONScore[] GetScoresForHUD(string name)
		{
			string path = Path.Combine(Path_Mod, name + "/Data/Score");
			if (!Directory.Exists(path))
			{
				Main.Logger.Warning("HUD " + name + " doesn't have a score data folder!");
				return null;
			}
			string[] allFiles = GetAllFiles(path, ".json");
			List<JSONScore> list = new List<JSONScore>();
			string[] array = allFiles;
			for (int i = 0; i < array.Length; i++)
			{
				JSONScore item = ReadScoreData(array[i]);
				list.Add(item);
			}
			return list.ToArray();
		}

		private static JSONMult[] GetMultipliersForHUD(string name)
		{
			string path = Path.Combine(Path_Mod, name + "/Data/Multiplier");
			if (!Directory.Exists(path))
			{
				Main.Logger.Warning("HUD " + name + " doesn't have a multiplier data folder!");
				return null;
			}
			string[] allFiles = GetAllFiles(path, ".json");
			List<JSONMult> list = new List<JSONMult>();
			string[] array = allFiles;
			for (int i = 0; i < array.Length; i++)
			{
				JSONMult item = ReadMultiplierData(array[i]);
				list.Add(item);
			}
			return list.ToArray();
		}

		private static PackedScore[] CreateScoreObjects(JSONScore[] scores)
		{
			if (scores == null)
			{
				return null;
			}
			List<PackedScore> list = new List<PackedScore>();
			for (int i = 0; i < scores.Length; i++)
			{
				JSONScore score = scores[i];
				PackedScore packedScore = new PackedScore(score);
				if (score.Tiers != null && score.Tiers.Length != 0)
				{
					List<PackedScore> list2 = new List<PackedScore>();
					JSONScore[] tiers = score.Tiers;
					for (int j = 0; j < tiers.Length; j++)
					{
						PackedScore packedScore2 = new PackedScore(tiers[j], useTiers: true);
						packedScore2.eventType = packedScore.eventType;
						list2.Add(packedScore2);
					}
					PackedValue[] tiers2 = list2.ToArray();
					packedScore.Tiers = tiers2;
				}
				list.Add(packedScore);
			}
			return list.ToArray();
		}

		private static PackedMultiplier[] CreateMultiplierObjects(JSONMult[] multipliers)
		{
			if (multipliers == null)
			{
				return null;
			}
			List<PackedMultiplier> list = new List<PackedMultiplier>();
			for (int i = 0; i < multipliers.Length; i++)
			{
				JSONMult mult = multipliers[i];
				PackedMultiplier packedMultiplier = new PackedMultiplier(mult);
				if (mult.Tiers != null && mult.Tiers.Length != 0)
				{
					List<PackedMultiplier> list2 = new List<PackedMultiplier>();
					JSONMult[] tiers = mult.Tiers;
					for (int j = 0; j < tiers.Length; j++)
					{
						PackedMultiplier packedMultiplier2 = new PackedMultiplier(tiers[j], useTiers: true);
						packedMultiplier2.eventType = packedMultiplier.eventType;
						list2.Add(packedMultiplier2);
					}
					PackedValue[] tiers2 = list2.ToArray();
					packedMultiplier.Tiers = tiers2;
				}
				list.Add(packedMultiplier);
			}
			return list.ToArray();
		}

		private static JSONScore ReadScoreData(string file)
		{
			JSONScore result = default(JSONScore);
			result.FromJSON(file);
			return result;
		}

		private static JSONMult ReadMultiplierData(string file)
		{
			JSONMult result = default(JSONMult);
			result.FromJSON(file);
			return result;
		}
	}
	public struct ValuePackage
	{
		public Dictionary<string, PackedValue> Values;

		public ValuePackage(PackedScore[] scores, PackedMultiplier[] multipliers)
		{
			Values = new Dictionary<string, PackedValue>();
			if (scores != null)
			{
				foreach (PackedScore packedScore in scores)
				{
					Values.Add(packedScore.eventType, packedScore);
				}
			}
			if (multipliers != null)
			{
				foreach (PackedMultiplier packedMultiplier in multipliers)
				{
					Values.Add(packedMultiplier.eventType, packedMultiplier);
				}
			}
		}
	}
}
namespace NEP.ScoreLab.Core
{
	public static class API
	{
		public static class Value
		{
			public static Action<PackedValue> OnValueAdded;

			public static Action<PackedValue> OnValueAccumulated;

			public static Action<PackedValue> OnValueTierReached;

			public static Action<PackedValue> OnValueRemoved;
		}

		public static class Score
		{
			public static Action<int> OnScoreUpdated;

			public static Action<int> OnScoreDifferenceUpdated;

			public static Action<int> OnLastScoreUpdated;
		}

		public static class Multiplier
		{
			public static Action<PackedMultiplier> OnMultiplierTimeBegin;

			public static Action<PackedMultiplier> OnMultiplierTimeExpired;
		}

		public static class HighScore
		{
			public static Action<PackedHighScore> OnHighScoreReached;

			public static Action<PackedHighScore> OnHighScoreUpdated;

			public static Action<PackedHighScore> OnHighScoreLoaded;

			public static Action<PackedHighScore> OnHighScoreSaved;
		}

		public static class GameConditions
		{
			private static Dictionary<string, Func<bool>> _conditionTable = new Dictionary<string, Func<bool>>
			{
				{
					"IsPlayerMoving",
					() => ScoreDirector.IsPlayerMoving
				},
				{
					"IsPlayerSeated",
					() => ScoreDirector.IsPlayerSeated
				},
				{
					"IsPlayerInAir",
					() => ScoreDirector.IsPlayerInAir
				},
				{
					"IsPlayerRagdolled",
					() => ScoreDirector.IsPlayerRagdolled
				},
				{
					"IsSlowMoEnabled",
					() => ScoreDirector.IsSlowMoEnabled
				}
			};

			public static Func<bool> GetCondition(string cond)
			{
				if (string.IsNullOrEmpty(cond))
				{
					Debug.LogWarning(Object.op_Implicit(cond + " doesn't exist in the condition table."));
					return null;
				}
				if (!_conditionTable.ContainsKey(cond))
				{
					Debug.LogWarning(Object.op_Implicit(cond + " doesn't exist in the condition table."));
					return null;
				}
				return _conditionTable[cond];
			}
		}

		public static class UI
		{
			public static Action<NEP.ScoreLab.HUD.Module> OnModuleEnabled;

			public static Action<NEP.ScoreLab.HUD.Module> OnModuleDisabled;

			public static Action<NEP.ScoreLab.HUD.Module> OnModuleDecayed;

			public static Action<NEP.ScoreLab.HUD.Module> OnModulePostDecayed;
		}
	}
	public static class ScoreDirector
	{
		public static class Patches
		{
			[HarmonyPatch(typeof(Projectile), "Awake")]
			public static class ProjectilePatch
			{
				public static void Postfix(Projectile __instance)
				{
					Action<Collider, Vector3, Vector3> action = OnProjectileCollision;
					((UnityEvent<Collider, Vector3, Vector3>)(object)__instance.onCollision).AddListener(UnityAction<Collider, Vector3, Vector3>.op_Implicit(action));
				}

				private static void OnProjectileCollision(Collider collider, Vector3 world, Vector3 normal)
				{
					MarrowBody val = MarrowBody.Cache.Get(((Component)collider).gameObject);
					if (!((Object)(object)val == (Object)null))
					{
						TriggerRefProxy component = ((Component)val).GetComponent<TriggerRefProxy>();
						if (!((Object)(object)component == (Object)null) && !component.aiManager.isDead && (Object)(object)((Component)component.targetHead).gameObject == (Object)(object)((Component)val).gameObject)
						{
							ScoreTracker.Add(EventType.Score.Headshot);
						}
					}
				}
			}

			[HarmonyPatch(typeof(RigManager), "SwitchAvatar")]
			public static class RigManagerSwapAvatarPatch
			{
				public static void Postfix(Avatar newAvatar)
				{
					_playerRecentlySwappedAvatars = true;
				}
			}

			[HarmonyPatch(typeof(BehaviourCrablet))]
			[HarmonyPatch("AttachToFace")]
			public static class CrabletAttachToFacePatch
			{
				public static void Postfix(Rigidbody face, TriggerRefProxy trp, bool preAttach = false, bool isPlayer = true)
				{
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					//IL_000c: Invalid comparison between Unknown and I4
					if (!isPlayer)
					{
						if ((int)trp.npcType == 32)
						{
							ScoreTracker.Add(EventType.Score.Crabcest);
						}
						else
						{
							ScoreTracker.Add(EventType.Score.Facehug);
						}
					}
				}
			}

			[HarmonyPatch(typeof(Seat))]
			[HarmonyPatch("Register")]
			public static class RegisterSeatPatch
			{
				public static void Postfix(RigManager rM)
				{
					IsPlayerSeated = true;
					ScoreTracker.Add(EventType.Mult.Seated);
				}
			}

			[HarmonyPatch(typeof(Seat))]
			[HarmonyPatch("DeRegister")]
			public static class DeRegisterSeatPatch
			{
				public static void Postfix()
				{
					IsPlayerSeated = false;
				}
			}

			[HarmonyPatch(typeof(Player_Health))]
			[HarmonyPatch("LifeSavingDamgeDealt")]
			public static class SecondWindPatch
			{
				public static void Postfix()
				{
					ScoreTracker.Add(EventType.Mult.SecondWind);
				}
			}

			[HarmonyPatch(typeof(Arena_GameController))]
			[HarmonyPatch("StartNextWave")]
			public static class StartNextWavePatch
			{
				public static void Postfix(Arena_GameController __instance)
				{
					ScoreTracker.Add(EventType.Score.GameWaveCompleted);
				}
			}

			[HarmonyPatch(typeof(Arena_GameController))]
			[HarmonyPatch("EndOfRound")]
			public static class StartNextRoundPatch
			{
				public static void Postfix(Arena_GameController __instance)
				{
					ScoreTracker.Add(EventType.Score.GameRoundCompleted);
				}
			}

			[HarmonyPatch(typeof(PhysicsRig))]
			[HarmonyPatch("OnUpdate")]
			public static class PhysRigPatch
			{
				private static bool _midAirTargetBool;

				private static float _tMidAirDelay = 0.5f;

				private static float _tAirTime;

				private static bool _ragdolledTargetBool;

				private static float _tRagdollDelay = 0.5f;

				private static float _tRagdollTime;

				public static void Postfix(PhysicsRig __instance)
				{
					IsPlayerInAir = !__instance.physG.isGrounded;
					if (IsPlayerInAir)
					{
						if (!_midAirTargetBool)
						{
							_tAirTime += Time.deltaTime;
							if (_tAirTime > _tMidAirDelay)
							{
								ScoreTracker.Add(EventType.Mult.MidAir);
								_midAirTargetBool = true;
							}
						}
					}
					else
					{
						_tAirTime = 0f;
						_midAirTargetBool = false;
					}
					if (IsPlayerRagdolled)
					{
						if (!_ragdolledTargetBool)
						{
							_ragdolledTargetBool = true;
						}
					}
					else
					{
						_ragdolledTargetBool = false;
					}
					if (_playerRecentlySwappedAvatars)
					{
						ScoreTracker.Add(EventType.Mult.SwappedAvatars);
						_playerRecentlySwappedAvatars = false;
					}
				}
			}

			[HarmonyPatch(typeof(PhysicsRig))]
			[HarmonyPatch("RagdollRig")]
			public static class PhysRigRagdollPatch
			{
				public static void Postfix(PhysicsRig __instance)
				{
					IsPlayerRagdolled = true;
				}
			}

			[HarmonyPatch(typeof(PhysicsRig))]
			[HarmonyPatch("UnRagdollRig")]
			public static class PhysRigUnRagdollPatch
			{
				public static void Postfix(PhysicsRig __instance)
				{
					IsPlayerRagdolled = false;
				}
			}

			[HarmonyPatch(typeof(TimeManager), "OnPostTimeUpdate")]
			public static class TimeManagerUpdatePatch
			{
				private static bool _slowmoSwitch;

				public static void Postfix()
				{
				}
			}

			[HarmonyPatch(typeof(TimeManager), "INCREASE_TIMESCALE")]
			public static class TimeManagerIncreaseTimePatch
			{
				public static void Postfix()
				{
				}
			}

			[HarmonyPatch(typeof(TimeManager), "DECREASE_TIMESCALE")]
			public static class TimeManagerDecreaseTimePatch
			{
				public static void Postfix()
				{
				}
			}

			public static void InitPatches()
			{
				Hooking.OnNPCKillStart += OnAIDeath;
			}

			public static void OnAIDeath(BehaviourBaseNav behaviour)
			{
				ScoreTracker.Add(ValueManager.Get(EventType.Score.Kill));
				ScoreTracker.Add(ValueManager.Get(EventType.Mult.Kill));
				if (!behaviour.sensors.isGrounded)
				{
					ScoreTracker.Add(EventType.Score.EnemyMidAirKill);
				}
				if ((Object)(object)behaviour.sensors.target == (Object)null)
				{
					ScoreTracker.Add(EventType.Score.StealthKill);
				}
			}
		}

		public static readonly string PlayerName = "";

		public static bool IsPlayerMoving = false;

		public static bool IsPlayerInAir = false;

		public static bool IsPlayerSeated = false;

		public static bool IsPlayerRagdolled = false;

		public static bool IsSlowMoEnabled = false;

		private static bool _playerRecentlySwappedAvatars = false;
	}
	public static class ScoreTracker
	{
		private static int _score = 0;

		private static int _lastScore = 0;

		private static float _multiplier = 1f;

		private static float _baseMultiplier = 1f;

		public static List<PackedValue> ActiveValues { get; private set; }

		public static int Score => _score;

		public static int LastScore => _lastScore;

		public static float Multiplier => _multiplier;

		public static void Initialize()
		{
			ActiveValues = new List<PackedValue>();
		}

		public static void Update()
		{
			if (ActiveValues != null)
			{
				for (int i = 0; i < ActiveValues.Count; i++)
				{
					ActiveValues[i].OnUpdate();
				}
			}
		}

		public static void Add(string eventType)
		{
			Add(Create(eventType));
		}

		public static void Add(PackedValue value)
		{
			if (value != null)
			{
				if (value.PackedValueType == PackedValue.PackedType.Score)
				{
					SetPackedScore((PackedScore)value);
				}
				else if (value.PackedValueType == PackedValue.PackedType.Multiplier)
				{
					SetPackedMultiplier((PackedMultiplier)value);
				}
			}
		}

		public static void Remove(PackedValue value)
		{
			if (value.PackedValueType == PackedValue.PackedType.Score)
			{
				ActiveValues.Remove(value);
				value.OnValueRemoved();
				API.Value.OnValueRemoved?.Invoke(value);
			}
			else if (value.PackedValueType == PackedValue.PackedType.Multiplier)
			{
				ActiveValues.Remove(value);
				RemoveMultiplier((value as PackedMultiplier).AccumulatedMultiplier);
				value.OnValueRemoved();
				API.Value.OnValueRemoved?.Invoke(value);
			}
		}

		public static void AddScore(int score)
		{
			_lastScore = _score;
			_score += Mathf.RoundToInt((float)score * _multiplier);
		}

		public static void AddMultiplier(float multiplier)
		{
			_multiplier += multiplier;
		}

		public static void SetMultiplier(float multiplier)
		{
			_multiplier = multiplier;
		}

		public static void ResetScore()
		{
			_score = 0;
			_lastScore = 0;
		}

		public static void ResetMultiplier()
		{
			_multiplier = 1f;
		}

		public static void ResetAll()
		{
			ResetScore();
			ResetMultiplier();
			ResetHighScore();
			ActiveValues.Clear();
		}

		public static void ResetHighScore()
		{
		}

		public static void RemoveMultiplier(float multiplier)
		{
			if (_multiplier < _baseMultiplier)
			{
				_multiplier = _baseMultiplier;
			}
			_multiplier -= multiplier;
		}

		public static bool CheckDuplicate(PackedValue value)
		{
			foreach (PackedValue activeValue in ActiveValues)
			{
				if (activeValue.eventType == value.eventType)
				{
					return true;
				}
			}
			return false;
		}

		private static void SetPackedScore(PackedScore score)
		{
			if (score != null)
			{
				if (!CheckDuplicate(score))
				{
					InitializeValue(score);
					AddScore(score.Score);
					ActiveValues.Add(score);
					API.Value.OnValueAdded?.Invoke(score);
				}
				else if (score.Tiers != null)
				{
					PackedScore clone = GetClone<PackedScore>(score);
					PackedScore packedScore = (PackedScore)clone.CurrentTier;
					clone.ToNextTier();
					clone.TierRequirement = packedScore.TierRequirement;
					clone.SetDecayTime(packedScore.DecayTime);
					AddScore(packedScore.Score);
				}
				else if (score.Stackable)
				{
					PackedScore clone2 = GetClone<PackedScore>(score);
					AddScore(score.Score);
					clone2.SetDecayTime(clone2.DecayTime);
					clone2.AccumulatedScore += clone2.Score;
					API.Value.OnValueAccumulated?.Invoke(clone2);
				}
				else
				{
					PackedScore packedScore2 = CopyFromScore(score);
					InitializeValue(packedScore2);
					AddScore(packedScore2.Score);
					ActiveValues.Add(packedScore2);
					API.Value.OnValueAdded?.Invoke(packedScore2);
				}
			}
		}

		private static void SetPackedMultiplier(PackedMultiplier multiplier)
		{
			if (multiplier != null)
			{
				if (!CheckDuplicate(multiplier))
				{
					InitializeValue(multiplier);
					AddMultiplier(multiplier.Multiplier);
					ActiveValues.Add(multiplier);
					API.Value.OnValueAdded?.Invoke(multiplier);
				}
				else if (multiplier.Tiers != null)
				{
					PackedMultiplier clone = GetClone<PackedMultiplier>(multiplier);
					PackedMultiplier packedMultiplier = (PackedMultiplier)clone.CurrentTier;
					clone.ToNextTier();
					clone.TierRequirement = packedMultiplier.TierRequirement;
					clone.SetDecayTime(packedMultiplier.DecayTime);
					AddMultiplier(packedMultiplier.Multiplier);
					multiplier.AccumulatedMultiplier += packedMultiplier.Multiplier;
					API.Value.OnValueTierReached?.Invoke(packedMultiplier);
				}
				else if (multiplier.Stackable)
				{
					PackedMultiplier clone2 = GetClone<PackedMultiplier>(multiplier);
					AddMultiplier(multiplier.Multiplier);
					clone2.SetDecayTime(clone2.DecayTime);
					clone2.AccumulatedMultiplier += clone2.Multiplier;
					API.Value.OnValueAccumulated?.Invoke(clone2);
				}
				else
				{
					PackedMultiplier packedMultiplier2 = CopyFromMult(multiplier);
					InitializeValue(packedMultiplier2);
					AddMultiplier(multiplier.Multiplier);
					ActiveValues.Add(packedMultiplier2);
					API.Value.OnValueAdded?.Invoke(packedMultiplier2);
				}
			}
		}

		private static PackedScore CopyFromScore(PackedScore original)
		{
			return new PackedScore
			{
				eventType = original.eventType,
				Name = original.Name,
				Score = original.Score,
				EventAudio = original.EventAudio,
				DecayTime = original.DecayTime
			};
		}

		private static PackedMultiplier CopyFromMult(PackedMultiplier original)
		{
			return new PackedMultiplier
			{
				eventType = original.eventType,
				Name = original.Name,
				Multiplier = original.Multiplier,
				EventAudio = original.EventAudio,
				DecayTime = original.DecayTime,
				Condition = original.Condition
			};
		}

		private static PackedValue Create(string eventType)
		{
			PackedValue packedValue = ValueManager.Get(eventType);
			if (packedValue == null)
			{
				return null;
			}
			if (packedValue.PackedValueType == PackedValue.PackedType.Score)
			{
				PackedScore packedScore = (PackedScore)packedValue;
				return new PackedScore
				{
					eventType = packedScore.eventType,
					Stackable = packedScore.Stackable,
					DecayTime = packedScore.DecayTime,
					Name = packedScore.Name,
					Score = packedScore.Score,
					EventAudio = packedScore.EventAudio,
					TierRequirement = packedScore.TierRequirement,
					Tiers = packedScore.Tiers
				};
			}
			if (packedValue.PackedValueType == PackedValue.PackedType.Multiplier)
			{
				PackedMultiplier packedMultiplier = (PackedMultiplier)packedValue;
				return new PackedMultiplier
				{
					eventType = packedMultiplier.eventType,
					Stackable = packedMultiplier.Stackable,
					DecayTime = packedMultiplier.DecayTime,
					Name = packedMultiplier.Name,
					Multiplier = packedMultiplier.Multiplier,
					Condition = packedMultiplier.Condition,
					EventAudio = packedMultiplier.EventAudio,
					TierRequirement = packedMultiplier.TierRequirement,
					Tiers = packedMultiplier.Tiers
				};
			}
			return null;
		}

		private static void InitializeValue(PackedValue value)
		{
			value.OnValueCreated();
			value.SetDecayTime(value.DecayTime);
		}

		private static T GetClone<T>(PackedValue value) where T : PackedValue
		{
			return (T)ActiveValues.Find((PackedValue match) => match.eventType == value.eventType);
		}
	}
	public static class Settings
	{
		public static float DistanceToCamera;

		public static float MovementSmoothness;

		public static bool UseAnnouncer;

		public static string SavedHUD;

		public static HUDShowMode HUDShowMode;

		private static MelonPreferences_Category m_scorelabCategory;

		private static MelonPreferences_Entry<float> m_eDistanceToCamera;

		private static MelonPreferences_Entry<float> m_eMovementSmoothness;

		private static MelonPreferences_Entry<bool> m_eUseAnnouncer;

		private static MelonPreferences_Entry<string> m_eSavedHUD;

		private static MelonPreferences_Entry<int> m_eHudShowMode;

		public static void CreatePreferences()
		{
			m_scorelabCategory = MelonPreferences.CreateCategory("ScoreLab");
			m_eDistanceToCamera = m_scorelabCategory.CreateEntry<float>("DistanceToCamera", 1.125f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eMovementSmoothness = m_scorelabCategory.CreateEntry<float>("MovementSmoothness", 16f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eUseAnnouncer = m_scorelabCategory.CreateEntry<bool>("UseAnnouncer", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eSavedHUD = m_scorelabCategory.CreateEntry<string>("SavedHUD", "Coda", (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			m_eHudShowMode = m_scorelabCategory.CreateEntry<int>("HUDShowMode", 0, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			DistanceToCamera = m_eDistanceToCamera.Value;
			MovementSmoothness = m_eMovementSmoothness.Value;
			UseAnnouncer = m_eUseAnnouncer.Value;
			SavedHUD = m_eSavedHUD.Value;
			HUDShowMode = (HUDShowMode)m_eHudShowMode.Value;
		}

		public static void Save(bool log = false)
		{
			m_eDistanceToCamera.Value = DistanceToCamera;
			m_eMovementSmoothness.Value = MovementSmoothness;
			m_eUseAnnouncer.Value = UseAnnouncer;
			m_eSavedHUD.Value = SavedHUD;
			m_scorelabCategory.SaveToFile(log);
		}

		public static void SetDistanceToCamera(float distance)
		{
			m_eDistanceToCamera.Value = distance;
		}

		public static void SetMovementSmoothness(float movementSmoothness)
		{
			m_eMovementSmoothness.Value = movementSmoothness;
		}

		public static void SetUseAnnouncer(bool useAnnouncer)
		{
			m_eUseAnnouncer.Value = useAnnouncer;
		}

		public static void SetHUDShowMode(HUDShowMode mode)
		{
			m_eHudShowMode.Value = (int)mode;
			HUDManager.HUDShowModeUpdated(mode);
		}
	}
}
namespace NEP.ScoreLab.Audio
{
	public static class AudioManager
	{
		public static void Initialize()
		{
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAdded, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueTierReached, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Combine(API.Value.OnValueAccumulated, new Action<PackedValue>(OnValueReceived));
		}

		public static void Uninitialize()
		{
			API.Value.OnValueAdded = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAdded, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueTierReached = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueTierReached, new Action<PackedValue>(OnValueReceived));
			API.Value.OnValueAccumulated = (Action<PackedValue>)Delegate.Remove(API.Value.OnValueAccumulated, new Action<PackedValue>(OnValueReceived));
		}

		private static void OnValueReceived(PackedValue value)
		{
			if (Settings.UseAnnouncer && value.EventAudio != null && value.EventAudio.Clips != null && value.EventAudio.Clips.Length != 0)
			{
				AudioClip val = null;
				if (value.EventAudio.Clips.Length == 1)
				{
					val = value.EventAudio.Clips[0];
				}
				else
				{
					int num = Random.Range(0, value.EventAudio.Clips.Length);
					val = value.EventAudio.Clips[num];
				}
				Play(val, value.EventAudio.Volume, value.EventAudio.Pitch);
			}
		}

		public static void Play(AudioClip clip, float volume = 1f, float pitch = 1f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Audio.PlayAtPoint(clip, Vector3.zero, Audio.InHead, volume, pitch, 0f);
		}
	}
}