Decompiled source of FUNKIN IS FUEL v1.0.0

plugins/FunkinIsFuel.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using PluginConfig.API;
using PluginConfig.API.Decorators;
using PluginConfig.API.Fields;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RapBattle;

internal class BfSprite
{
	private struct AnimDef
	{
		public string Prefix;

		public Vector2 Offset;

		public bool Loop;

		public AnimDef(string prefix, float x, float y, bool loop)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Prefix = prefix;
			Offset = new Vector2(x, y);
			Loop = loop;
		}
	}

	private static readonly Dictionary<string, AnimDef> Defs = new Dictionary<string, AnimDef>
	{
		{
			"idle",
			new AnimDef("BF idle dance", -5f, 0f, loop: false)
		},
		{
			"singLEFT",
			new AnimDef("BF NOTE LEFT", 12f, -6f, loop: false)
		},
		{
			"singDOWN",
			new AnimDef("BF NOTE DOWN", -10f, -50f, loop: false)
		},
		{
			"singUP",
			new AnimDef("BF NOTE UP", -29f, 27f, loop: false)
		},
		{
			"singRIGHT",
			new AnimDef("BF NOTE RIGHT", -38f, -7f, loop: false)
		},
		{
			"singLEFTmiss",
			new AnimDef("BF NOTE LEFT MISS", 12f, 24f, loop: false)
		},
		{
			"singDOWNmiss",
			new AnimDef("BF NOTE DOWN MISS", -11f, -19f, loop: false)
		},
		{
			"singUPmiss",
			new AnimDef("BF NOTE UP MISS", -29f, 27f, loop: false)
		},
		{
			"singRIGHTmiss",
			new AnimDef("BF NOTE RIGHT MISS", -30f, 21f, loop: false)
		},
		{
			"hey",
			new AnimDef("BF HEY!!", 7f, 4f, loop: false)
		},
		{
			"hit",
			new AnimDef("BF hit", 0f, 0f, loop: false)
		},
		{
			"dodge",
			new AnimDef("boyfriend dodge", 0f, 0f, loop: false)
		},
		{
			"attack",
			new AnimDef("boyfriend attack", 0f, 0f, loop: false)
		},
		{
			"preAttack",
			new AnimDef("bf pre attack", 0f, 0f, loop: false)
		},
		{
			"scared",
			new AnimDef("BF idle shaking", -4f, 0f, loop: true)
		},
		{
			"firstDeath",
			new AnimDef("BF dies", 37f, 11f, loop: false)
		},
		{
			"deathLoop",
			new AnimDef("BF Dead Loop", 37f, 5f, loop: true)
		}
	};

	private static readonly string[] SingNames = new string[4] { "singLEFT", "singDOWN", "singUP", "singRIGHT" };

	private static Atlas atlas;

	private static Material material;

	private static string triedFolder;

	public GameObject Go;

	public float Height;

	private Mesh mesh;

	private float k;

	private Vector2 anchor;

	private string anim = "idle";

	private float animStart;

	private float holdUntil;

	private bool flipped;

	private bool dead;

	private readonly Vector3[] verts = (Vector3[])(object)new Vector3[4];

	private readonly Vector2[] uvs = (Vector2[])(object)new Vector2[4];

	public Vector3 Center => Go.transform.position + Vector3.up * Height * 0.5f;

	private static bool Load()
	{
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Expected O, but got Unknown
		if (triedFolder == SongLibrary.FunkinFolder)
		{
			return atlas != null;
		}
		triedFolder = SongLibrary.FunkinFolder;
		string text = Path.Combine(Path.Combine(Path.Combine(Path.Combine(SongLibrary.FunkinFolder, "assets"), "shared"), "images"), "characters");
		atlas = Atlas.Load(Path.Combine(text, "BOYFRIEND.png"), Path.Combine(text, "BOYFRIEND.xml"));
		if (atlas == null || atlas.Anim("BF idle dance") == null)
		{
			RapBattlePlugin.Log.LogWarning((object)("Boyfriend's sprite sheet wasn't found in " + text));
			atlas = null;
			return false;
		}
		try
		{
			atlas.Texture.Compress(false);
			atlas.Texture.Apply(false, true);
		}
		catch (Exception)
		{
		}
		Shader val = Shader.Find("Sprites/Default");
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Transparent");
		}
		if ((Object)(object)val == (Object)null)
		{
			val = Shader.Find("Unlit/Transparent Cutout");
		}
		material = new Material(val);
		material.mainTexture = (Texture)(object)atlas.Texture;
		((Object)material).hideFlags = (HideFlags)32;
		return true;
	}

	public static BfSprite Create(Vector3 feet, float height)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Expected O, but got Unknown
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Expected O, but got Unknown
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0103: Unknown result type (might be due to invalid IL or missing references)
		if (!Load())
		{
			return null;
		}
		BfSprite bfSprite = new BfSprite();
		bfSprite.Height = height;
		bfSprite.Go = new GameObject("Rap Battle Boyfriend");
		bfSprite.Go.transform.position = feet;
		bfSprite.mesh = new Mesh();
		((Object)bfSprite.mesh).name = "Boyfriend";
		bfSprite.mesh.MarkDynamic();
		bfSprite.Go.AddComponent<MeshFilter>().sharedMesh = bfSprite.mesh;
		MeshRenderer val = bfSprite.Go.AddComponent<MeshRenderer>();
		((Renderer)val).sharedMaterial = material;
		((Renderer)val).shadowCastingMode = (ShadowCastingMode)0;
		((Renderer)val).receiveShadows = false;
		AtlasFrame atlasFrame = atlas.Frame("BF idle dance", 0);
		AnimDef animDef = Defs["idle"];
		float num = 0f - animDef.Offset.x + atlasFrame.OffX;
		float num2 = 0f - animDef.Offset.y + atlasFrame.OffY;
		bfSprite.anchor = new Vector2(num + atlasFrame.W * 0.5f, num2 + atlasFrame.H);
		bfSprite.k = height / Mathf.Max(1f, atlasFrame.H);
		bfSprite.mesh.vertices = bfSprite.verts;
		bfSprite.mesh.uv = bfSprite.uvs;
		bfSprite.mesh.triangles = new int[6] { 0, 2, 1, 2, 3, 1 };
		bfSprite.Play("idle");
		return bfSprite;
	}

	public void Play(string name)
	{
		if (!dead || !(name != "deathLoop"))
		{
			if (!Defs.ContainsKey(name) || atlas.Anim(Defs[name].Prefix) == null)
			{
				name = "idle";
			}
			anim = name;
			animStart = Time.unscaledTime;
		}
	}

	public void Sing(int lane, float now, float holdMs, float stepMs)
	{
		Play(SingNames[lane]);
		holdUntil = now + holdMs + stepMs * 4f;
	}

	public void Hold(int lane, float now, float stepMs)
	{
		if (anim != SingNames[lane])
		{
			Play(SingNames[lane]);
		}
		holdUntil = Mathf.Max(holdUntil, now + stepMs * 2f);
	}

	public void Miss(int lane, float now, float stepMs)
	{
		Play(SingNames[lane] + "miss");
		holdUntil = now + stepMs * 5f;
	}

	public void Hey(float now, float holdMs)
	{
		Play("hey");
		holdUntil = now + holdMs;
	}

	public void Hurt(float now, float holdMs)
	{
		Play("hit");
		holdUntil = now + holdMs;
	}

	public void Dodge(float now, float holdMs)
	{
		Play("dodge");
		holdUntil = now + holdMs;
	}

	public void Attack(float now, float holdMs)
	{
		Play("attack");
		holdUntil = now + holdMs;
	}

	public void Scared(float now, float holdMs)
	{
		Play("scared");
		holdUntil = now + holdMs;
	}

	public void Die()
	{
		Play("firstDeath");
		dead = true;
		holdUntil = float.MaxValue;
	}

	public void Beat(int beat, float now)
	{
		if (!dead && now > holdUntil && beat % 2 == 0)
		{
			Play("idle");
		}
	}

	public void Tick(float now, Camera cam, Vector3 enemy)
	{
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0308: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0346: Unknown result type (might be due to invalid IL or missing references)
		//IL_034b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_0379: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0403: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)Go == (Object)null || atlas == null)
		{
			return;
		}
		if (!dead && anim != "idle" && now > holdUntil && anim != "scared")
		{
			Play("idle");
		}
		if (anim == "scared" && now > holdUntil)
		{
			Play("idle");
		}
		if ((Object)(object)cam != (Object)null)
		{
			Vector3 val = Go.transform.position - ((Component)cam).transform.position;
			val.y = 0f;
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				Go.transform.rotation = Quaternion.LookRotation(val, Vector3.up);
			}
			Vector3 val2 = cam.WorldToScreenPoint(Go.transform.position);
			Vector3 val3 = cam.WorldToScreenPoint(enemy);
			if (val2.z > 0f && val3.z > 0f)
			{
				flipped = val3.x > val2.x + 5f;
			}
		}
		string text = anim;
		if (flipped)
		{
			if (text.StartsWith("singLEFT"))
			{
				text = "singRIGHT" + text.Substring(8);
			}
			else if (text.StartsWith("singRIGHT"))
			{
				text = "singLEFT" + text.Substring(9);
			}
		}
		AnimDef animDef = Defs[text];
		List<AtlasFrame> list = atlas.Anim(animDef.Prefix);
		if (list == null || list.Count == 0)
		{
			return;
		}
		int num = (int)((Time.unscaledTime - animStart) * 24f);
		if (animDef.Loop)
		{
			num %= list.Count;
		}
		else if (num >= list.Count)
		{
			num = list.Count - 1;
			if (anim == "firstDeath")
			{
				anim = "deathLoop";
				animStart = Time.unscaledTime;
			}
		}
		AtlasFrame atlasFrame = list[num];
		float num2 = 0f - animDef.Offset.x + atlasFrame.OffX;
		float num3 = 0f - animDef.Offset.y + atlasFrame.OffY;
		float num4 = (num2 - anchor.x) * k;
		float num5 = (num2 + atlasFrame.W - anchor.x) * k;
		float num6 = (anchor.y - (num3 + atlasFrame.H)) * k;
		float num7 = (anchor.y - num3) * k;
		if (flipped)
		{
			num4 = 0f - num4;
			num5 = 0f - num5;
		}
		ref Vector3 reference = ref verts[0];
		reference = new Vector3(num4, num6, 0f);
		ref Vector3 reference2 = ref verts[1];
		reference2 = new Vector3(num5, num6, 0f);
		ref Vector3 reference3 = ref verts[2];
		reference3 = new Vector3(num4, num7, 0f);
		ref Vector3 reference4 = ref verts[3];
		reference4 = new Vector3(num5, num7, 0f);
		ref Vector2 reference5 = ref uvs[0];
		reference5 = new Vector2(((Rect)(ref atlasFrame.Uv)).xMin, ((Rect)(ref atlasFrame.Uv)).yMin);
		ref Vector2 reference6 = ref uvs[1];
		reference6 = new Vector2(((Rect)(ref atlasFrame.Uv)).xMax, ((Rect)(ref atlasFrame.Uv)).yMin);
		ref Vector2 reference7 = ref uvs[2];
		reference7 = new Vector2(((Rect)(ref atlasFrame.Uv)).xMin, ((Rect)(ref atlasFrame.Uv)).yMax);
		ref Vector2 reference8 = ref uvs[3];
		reference8 = new Vector2(((Rect)(ref atlasFrame.Uv)).xMax, ((Rect)(ref atlasFrame.Uv)).yMax);
		mesh.vertices = verts;
		mesh.uv = uvs;
		mesh.RecalculateBounds();
	}

	public void Destroy()
	{
		if ((Object)(object)Go != (Object)null)
		{
			Object.Destroy((Object)(object)Go);
		}
		if ((Object)(object)mesh != (Object)null)
		{
			Object.Destroy((Object)(object)mesh);
		}
		Go = null;
	}
}
internal class NoteData
{
	public float Time;

	public int Lane;

	public float Length;

	public string Kind;

	public bool Player;

	public bool Avoid;

	public bool Hit;

	public bool Missed;

	public bool Holding;

	public bool Dropped;

	public bool HoldDone;
}
internal class EventData
{
	public float Time;

	public string Name;

	public JToken Value;
}
internal class Conductor
{
	private struct Change
	{
		public float Time;

		public float Bpm;

		public float Beat;
	}

	private readonly List<Change> changes = new List<Change>();

	public Conductor(List<float> times, List<float> bpms)
	{
		List<KeyValuePair<float, float>> list = new List<KeyValuePair<float, float>>();
		for (int i = 0; i < times.Count && i < bpms.Count; i++)
		{
			if (bpms[i] > 0f)
			{
				list.Add(new KeyValuePair<float, float>(times[i], bpms[i]));
			}
		}
		if (list.Count == 0)
		{
			list.Add(new KeyValuePair<float, float>(0f, 100f));
		}
		list.Sort((KeyValuePair<float, float> a, KeyValuePair<float, float> b) => a.Key.CompareTo(b.Key));
		float num = 0f;
		Change item = default(Change);
		for (int num2 = 0; num2 < list.Count; num2++)
		{
			if (num2 > 0)
			{
				num += (list[num2].Key - list[num2 - 1].Key) * list[num2 - 1].Value / 60000f;
			}
			item.Time = ((num2 == 0) ? Math.Min(0f, list[num2].Key) : list[num2].Key);
			item.Bpm = list[num2].Value;
			item.Beat = num;
			changes.Add(item);
		}
	}

	private Change At(float ms)
	{
		Change result = changes[0];
		for (int i = 1; i < changes.Count && !(changes[i].Time > ms); i++)
		{
			result = changes[i];
		}
		return result;
	}

	public float BeatAt(float ms)
	{
		Change change = At(ms);
		return change.Beat + (ms - change.Time) * change.Bpm / 60000f;
	}

	public float MsAtBeat(float beat)
	{
		Change change = changes[0];
		for (int i = 1; i < changes.Count && !(changes[i].Beat > beat); i++)
		{
			change = changes[i];
		}
		return change.Time + (beat - change.Beat) * 60000f / change.Bpm;
	}

	public float BpmAt(float ms)
	{
		return At(ms).Bpm;
	}

	public float CrochetAt(float ms)
	{
		return 60000f / At(ms).Bpm;
	}

	public float StepAt(float ms)
	{
		return 15000f / At(ms).Bpm;
	}
}
internal class ChartData
{
	public SongEntry Song;

	public string Difficulty;

	public float ScrollSpeed = 1f;

	public List<NoteData> Notes = new List<NoteData>();

	public List<EventData> Events = new List<EventData>();

	public Conductor Conductor;

	public float LastNoteTime;

	public int PlayerNoteCount;

	public HashSet<string> EventNames = new HashSet<string>();
}
internal static class ChartLoader
{
	private static readonly string[] DifficultyOrder = new string[5] { "hard", "normal", "easy", "erect", "nightmare" };

	private static readonly string[] HardestFirst = new string[5] { "nightmare", "erect", "hard", "normal", "easy" };

	private static readonly string[] AvoidKindWords = new string[8] { "hell", "death", "hurt", "mine", "bomb", "glitch", "poison", "danger" };

	internal static ChartData Load(SongEntry song, string preferred, Random rng, out string error)
	{
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		error = null;
		JObject val = JObject.Parse(File.ReadAllText(song.ChartPath));
		JToken obj = val["notes"];
		JObject val2 = (JObject)(object)((obj is JObject) ? obj : null);
		if (val2 == null)
		{
			error = "chart has no notes";
			return null;
		}
		List<string> list = new List<string>();
		foreach (JProperty item2 in val2.Properties())
		{
			JToken value = item2.Value;
			JArray val3 = (JArray)(object)((value is JArray) ? value : null);
			if (val3 == null)
			{
				continue;
			}
			int num = 0;
			foreach (JToken item3 in val3)
			{
				if ((int)SongLibrary.Num(item3[(object)"d"], 0f) % 8 < 4)
				{
					num++;
				}
			}
			if (num >= 16)
			{
				list.Add(item2.Name);
			}
		}
		if (list.Count == 0)
		{
			error = "no difficulty with enough player notes";
			return null;
		}
		string text = null;
		if (preferred == "random")
		{
			text = list[rng.Next(list.Count)];
		}
		if (preferred == "hardest")
		{
			string[] hardestFirst = HardestFirst;
			foreach (string name in hardestFirst)
			{
				text = Find(list, name);
				if (text != null)
				{
					break;
				}
			}
		}
		if (text == null)
		{
			text = Find(list, preferred);
		}
		int num2 = 0;
		while (text == null && num2 < DifficultyOrder.Length)
		{
			text = Find(list, DifficultyOrder[num2]);
			num2++;
		}
		if (text == null)
		{
			text = list[0];
		}
		ChartData chartData = new ChartData();
		chartData.Song = song;
		chartData.Difficulty = text;
		chartData.Conductor = new Conductor(song.BpmTimes, song.Bpms);
		JToken obj2 = val["scrollSpeed"];
		JObject val4 = (JObject)(object)((obj2 is JObject) ? obj2 : null);
		if (val4 != null)
		{
			JToken val5 = val4[text] ?? val4["default"];
			if (val5 == null)
			{
				using IEnumerator<JProperty> enumerator3 = val4.Properties().GetEnumerator();
				if (enumerator3.MoveNext())
				{
					JProperty current3 = enumerator3.Current;
					val5 = current3.Value;
				}
			}
			chartData.ScrollSpeed = SongLibrary.Num(val5, 1f);
		}
		else if (val["scrollSpeed"] != null)
		{
			chartData.ScrollSpeed = SongLibrary.Num(val["scrollSpeed"], 1f);
		}
		if (chartData.ScrollSpeed <= 0.1f)
		{
			chartData.ScrollSpeed = 1f;
		}
		HashSet<long> hashSet = new HashSet<long>();
		foreach (JToken item4 in (JArray)val2[text])
		{
			NoteData noteData = new NoteData();
			noteData.Time = SongLibrary.Num(item4[(object)"t"], 0f);
			int num3 = (int)SongLibrary.Num(item4[(object)"d"], 0f) % 8;
			if (num3 < 0)
			{
				num3 += 8;
			}
			noteData.Lane = num3 % 4;
			noteData.Player = num3 < 4;
			noteData.Length = Math.Max(0f, SongLibrary.Num(item4[(object)"l"], 0f));
			if (noteData.Length < 60f)
			{
				noteData.Length = 0f;
			}
			noteData.Kind = SongLibrary.Str(item4[(object)"k"], "") ?? "";
			noteData.Avoid = IsAvoidKind(noteData.Kind);
			long item = ((long)Math.Round(noteData.Time) << 4) | (uint)num3;
			if (hashSet.Add(item))
			{
				chartData.Notes.Add(noteData);
				if (noteData.Player && !noteData.Avoid)
				{
					chartData.PlayerNoteCount++;
				}
				chartData.LastNoteTime = Math.Max(chartData.LastNoteTime, noteData.Time + noteData.Length);
			}
		}
		chartData.Notes.Sort((NoteData a, NoteData b) => a.Time.CompareTo(b.Time));
		JToken obj3 = val["events"];
		JArray val6 = (JArray)(object)((obj3 is JArray) ? obj3 : null);
		if (val6 != null)
		{
			foreach (JToken item5 in val6)
			{
				EventData eventData = new EventData();
				eventData.Time = SongLibrary.Num(item5[(object)"t"], 0f);
				eventData.Name = SongLibrary.Str(item5[(object)"e"], "");
				eventData.Value = item5[(object)"v"];
				if (eventData.Name.Length != 0)
				{
					chartData.Events.Add(eventData);
					chartData.EventNames.Add(eventData.Name);
				}
			}
		}
		return chartData;
	}

	private static string Find(List<string> list, string name)
	{
		foreach (string item in list)
		{
			if (string.Equals(item, name, StringComparison.OrdinalIgnoreCase))
			{
				return item;
			}
		}
		return null;
	}

	internal static bool IsAvoidKind(string kind)
	{
		if (string.IsNullOrEmpty(kind))
		{
			return false;
		}
		string text = kind.ToLowerInvariant();
		string[] avoidKindWords = AvoidKindWords;
		foreach (string value in avoidKindWords)
		{
			if (text.Contains(value))
			{
				return true;
			}
		}
		return false;
	}
}
internal static class ConfigMenu
{
	internal const string PluginConfiguratorGuid = "com.eternalUnion.pluginConfigurator";

	internal static void Build()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
		PluginConfigurator val = PluginConfigurator.Create("FUNKIN' IS FUEL", "funkinisfuel.ultrakill");
		ConfigPanel rootPanel = val.rootPanel;
		new ConfigHeader(rootPanel, "Mic", 24);
		AddKey(rootPanel, "Throw mic", RapBattlePlugin.MicKey);
		AddKey(rootPanel, "Pose maker", RapBattlePlugin.PoseEditorKey);
		AddKey(rootPanel, "Mic menu", RapBattlePlugin.MicMenuKey);
		AddBool(rootPanel, "Show the mic on the HUD", RapBattlePlugin.ShowMicHud);
		AddString(rootPanel, "Who raps for you (V1 / Boyfriend / Both)", RapBattlePlugin.PlayerCharacter);
		AddString(rootPanel, "Sick/Good popups (Notes / Center / Off)", RapBattlePlugin.RatingsPosition);
		AddFloat(rootPanel, "Boss intensity", RapBattlePlugin.BossIntensity, 0f, 2f);
		AddBool(rootPanel, "Other enemies dance", RapBattlePlugin.CrowdDance);
		AddInt(rootPanel, "Mics per level (0 = unlimited)", RapBattlePlugin.MicsPerLevel, 0, 20);
		new ConfigHeader(rootPanel, "Songs", 24);
		AddString(rootPanel, "FNF folder", RapBattlePlugin.FunkinPath);
		AddBool(rootPanel, "Base game songs", RapBattlePlugin.IncludeBaseGame);
		AddBool(rootPanel, "Mod songs", RapBattlePlugin.IncludeMods);
		AddString(rootPanel, "Excluded song ids", RapBattlePlugin.ExcludedSongs);
		AddString(rootPanel, "Difficulty (easy/normal/hard/erect/nightmare/random)", RapBattlePlugin.Difficulty);
		new ConfigHeader(rootPanel, "Notes", 24);
		string[] array = new string[4] { "Left", "Down", "Up", "Right" };
		for (int i = 0; i < 4; i++)
		{
			AddKey(rootPanel, array[i], RapBattlePlugin.LaneKeys[i]);
		}
		for (int j = 0; j < 4; j++)
		{
			AddKey(rootPanel, array[j] + " (alt)", RapBattlePlugin.LaneKeys[j + 4]);
		}
		AddBool(rootPanel, "Ghost tapping", RapBattlePlugin.GhostTapping);
		AddBool(rootPanel, "Downscroll", RapBattlePlugin.Downscroll);
		AddBool(rootPanel, "Middlescroll", RapBattlePlugin.Middlescroll);
		AddFloat(rootPanel, "Scroll speed multiplier", RapBattlePlugin.ScrollSpeedMultiplier, 0.5f, 3f);
		AddFloat(rootPanel, "Audio offset (ms)", RapBattlePlugin.AudioOffsetMs, -300f, 300f);
		AddFloat(rootPanel, "Song volume", RapBattlePlugin.SongVolume, 0f, 1f);
		new ConfigHeader(rootPanel, "Battle", 24);
		AddInt(rootPanel, "Damage when you lose (100 = death)", RapBattlePlugin.LoseDamage, 0, 200);
		AddFloat(rootPanel, "Boss damage when you win (%)", RapBattlePlugin.BossWinDamagePercent, 0f, 100f);
		AddFloat(rootPanel, "Enemy health drain per note", RapBattlePlugin.OpponentHealthDrain, 0f, 0.05f);
		AddFloat(rootPanel, "Attacks per minute", RapBattlePlugin.AttacksPerMinute, 0f, 12f);
		AddBool(rootPanel, "Song mechanics become attacks", RapBattlePlugin.ChartAttacks);
		AddFloat(rootPanel, "Attack damage", RapBattlePlugin.AttackDamage, 0f, 2f);
		AddFloat(rootPanel, "Parry heal", RapBattlePlugin.ParryHeal, 0f, 2f);
		AddFloat(rootPanel, "Parry/dodge window (ms)", RapBattlePlugin.AttackWindowMs, 60f, 400f);
		new ConfigHeader(rootPanel, "Camera & events", 24);
		AddFloat(rootPanel, "Battle FOV", RapBattlePlugin.BattleFov, 30f, 100f);
		AddFloat(rootPanel, "Camera bop", RapBattlePlugin.CameraBopIntensity, 0f, 3f);
		AddBool(rootPanel, "Remix events into every song", RapBattlePlugin.RemixEvents);
		AddBool(rootPanel, "Screen flashes", RapBattlePlugin.ScreenFlashes);
		AddBool(rootPanel, "Show V1 on stage", RapBattlePlugin.ShowV1);
		AddBool(rootPanel, "Verbose log", RapBattlePlugin.DebugLog);
	}

	private static string FieldGuid(ConfigEntryBase entry)
	{
		return (entry.Definition.Section + "." + entry.Definition.Key).ToLowerInvariant();
	}

	private static void AddBool(ConfigPanel panel, string label, ConfigEntry<bool> entry)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		BoolField field = new BoolField(panel, label, FieldGuid((ConfigEntryBase)(object)entry), entry.Value, false);
		field.postValueChangeEvent += (PostBoolValueChangeEvent)delegate(bool value)
		{
			entry.Value = value;
		};
		entry.SettingChanged += delegate
		{
			if (field.value != entry.Value)
			{
				field.value = entry.Value;
			}
		};
	}

	private static void AddFloat(ConfigPanel panel, string label, ConfigEntry<float> entry, float min, float max)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		FloatField field = new FloatField(panel, label, FieldGuid((ConfigEntryBase)(object)entry), entry.Value, min, max, true, false);
		field.postValueChangeEvent += (PostFloatValueChangeEvent)delegate(float value)
		{
			entry.Value = value;
		};
		entry.SettingChanged += delegate
		{
			if (field.value != entry.Value)
			{
				field.value = entry.Value;
			}
		};
	}

	private static void AddInt(ConfigPanel panel, string label, ConfigEntry<int> entry, int min, int max)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Expected O, but got Unknown
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Expected O, but got Unknown
		IntField field = new IntField(panel, label, FieldGuid((ConfigEntryBase)(object)entry), entry.Value, min, max, true, false);
		field.postValueChangeEvent += (PostIntValueChangeEvent)delegate(int value)
		{
			entry.Value = value;
		};
		entry.SettingChanged += delegate
		{
			if (field.value != entry.Value)
			{
				field.value = entry.Value;
			}
		};
	}

	private static void AddString(ConfigPanel panel, string label, ConfigEntry<string> entry)
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		StringField field = new StringField(panel, label, FieldGuid((ConfigEntryBase)(object)entry), entry.Value, true, false);
		field.postValueChangeEvent += (PostStringValueChangeEvent)delegate(string value)
		{
			entry.Value = value;
		};
		entry.SettingChanged += delegate
		{
			if (field.value != entry.Value)
			{
				field.value = entry.Value;
			}
		};
	}

	private static void AddKey(ConfigPanel panel, string label, ConfigEntry<KeyCode> entry)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		KeyCodeField field = new KeyCodeField(panel, label, FieldGuid((ConfigEntryBase)(object)entry), entry.Value, false);
		field.postValueChangeEvent += (PostKeyCodeValueChangeEvent)delegate(KeyCode value)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			entry.Value = value;
		};
		entry.SettingChanged += delegate
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (field.value != entry.Value)
			{
				field.value = entry.Value;
			}
		};
	}
}
internal static class Ease
{
	internal static readonly Func<float, float> Linear = (float t) => t;

	internal static Func<float, float> Get(string name)
	{
		if (string.IsNullOrEmpty(name))
		{
			return Linear;
		}
		string text = name.Trim();
		string text2 = text.ToLowerInvariant();
		switch (text2)
		{
		case "linear":
		case "classic":
		case "instant":
			return Linear;
		default:
		{
			string text3 = "InOut";
			string text4 = text2;
			if (text2.EndsWith("inout"))
			{
				text3 = "InOut";
				text4 = text2.Substring(0, text2.Length - 5);
			}
			else if (text2.EndsWith("out"))
			{
				text3 = "Out";
				text4 = text2.Substring(0, text2.Length - 3);
			}
			else if (text2.EndsWith("in"))
			{
				text3 = "In";
				text4 = text2.Substring(0, text2.Length - 2);
			}
			Func<float, float> ein = In(text4);
			if (ein == null)
			{
				return Linear;
			}
			if (text4 == "smoothstep" || text4 == "smootherstep")
			{
				Func<float, float> io = ((text4 == "smoothstep") ? ((Func<float, float>)((float t) => t * t * (3f - 2f * t))) : ((Func<float, float>)((float t) => t * t * t * (t * (t * 6f - 15f) + 10f))));
				if (text3 == "In")
				{
					return (float t) => 2f * io(t * 0.5f);
				}
				if (text3 == "Out")
				{
					return (float t) => 2f * io(t * 0.5f + 0.5f) - 1f;
				}
				return io;
			}
			if (text3 == "In")
			{
				return ein;
			}
			if (text3 == "Out")
			{
				return (float t) => 1f - ein(1f - t);
			}
			return (float t) => (!(t < 0.5f)) ? (1f - ein((1f - t) * 2f) * 0.5f) : (ein(t * 2f) * 0.5f);
		}
		}
	}

	internal static string Combine(string ease, string dir)
	{
		if (string.IsNullOrEmpty(ease))
		{
			return "linear";
		}
		if (string.IsNullOrEmpty(dir))
		{
			return ease;
		}
		string text = ease.ToLowerInvariant();
		switch (text)
		{
		case "classic":
		case "instant":
		case "linear":
			return ease;
		default:
			if (text.EndsWith("in") || text.EndsWith("out"))
			{
				return ease;
			}
			return ease + dir;
		}
	}

	private static Func<float, float> In(string family)
	{
		switch (family)
		{
		case "quad":
			return (float t) => t * t;
		case "cube":
		case "cubic":
			return (float t) => t * t * t;
		case "quart":
			return (float t) => t * t * t * t;
		case "quint":
			return (float t) => t * t * t * t * t;
		case "sine":
			return (float t) => 1f - Mathf.Cos(t * (float)Math.PI * 0.5f);
		case "expo":
			return (float t) => (!(t <= 0f)) ? Mathf.Pow(2f, 10f * (t - 1f)) : 0f;
		case "circ":
			return (float t) => 1f - Mathf.Sqrt(Mathf.Max(0f, 1f - t * t));
		case "back":
			return (float t) => t * t * (2.70158f * t - 1.70158f);
		case "elastic":
			return (float t) => (t <= 0f || t >= 1f) ? t : ((0f - Mathf.Pow(2f, 10f * (t - 1f))) * Mathf.Sin((t - 1.075f) * ((float)Math.PI * 2f) / 0.3f));
		case "bounce":
			return (float t) => 1f - BounceOut(1f - t);
		case "smoothstep":
		case "smootherstep":
			return Linear;
		default:
			return null;
		}
	}

	private static float BounceOut(float t)
	{
		if (t < 0.36363637f)
		{
			return 7.5625f * t * t;
		}
		if (t < 0.72727275f)
		{
			t -= 0.54545456f;
			return 7.5625f * t * t + 0.75f;
		}
		if (t < 0.90909094f)
		{
			t -= 0.8181818f;
			return 7.5625f * t * t + 0.9375f;
		}
		t -= 21f / 22f;
		return 7.5625f * t * t + 63f / 64f;
	}
}
internal class FloatTween
{
	private float from;

	private float to;

	private float t0;

	private float dur;

	private Func<float, float> ease = Ease.Linear;

	public float Target => to;

	public FloatTween(float value)
	{
		from = (to = value);
	}

	public void Set(float value)
	{
		from = (to = value);
		dur = 0f;
	}

	public void To(float target, float now, float durationMs, Func<float, float> curve)
	{
		from = Value(now);
		to = target;
		t0 = now;
		dur = Mathf.Max(0f, durationMs);
		ease = curve ?? Ease.Linear;
	}

	public float Value(float now)
	{
		if (dur <= 0f || now >= t0 + dur)
		{
			return to;
		}
		if (now <= t0)
		{
			return from;
		}
		return from + (to - from) * ease((now - t0) / dur);
	}
}
internal static class EventMaker
{
	internal static void AddGenerated(ChartData chart, List<EventData> into, Random rng, bool remix, float endMs)
	{
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Expected O, but got Unknown
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Expected O, but got Unknown
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Expected O, but got Unknown
		//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Expected O, but got Unknown
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Expected O, but got Unknown
		//IL_0322: Unknown result type (might be due to invalid IL or missing references)
		//IL_032c: Expected O, but got Unknown
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0362: Expected O, but got Unknown
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_0376: Expected O, but got Unknown
		//IL_0378: Unknown result type (might be due to invalid IL or missing references)
		//IL_0382: Expected O, but got Unknown
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f0: Expected O, but got Unknown
		//IL_0406: Unknown result type (might be due to invalid IL or missing references)
		//IL_040c: Expected O, but got Unknown
		//IL_0422: Unknown result type (might be due to invalid IL or missing references)
		//IL_0428: Expected O, but got Unknown
		//IL_042a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0434: Expected O, but got Unknown
		//IL_0457: Unknown result type (might be due to invalid IL or missing references)
		//IL_0461: Expected O, but got Unknown
		//IL_045c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0466: Expected O, but got Unknown
		//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cd: Expected O, but got Unknown
		//IL_0501: Unknown result type (might be due to invalid IL or missing references)
		//IL_050b: Expected O, but got Unknown
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_050c: Expected O, but got Unknown
		//IL_0542: Unknown result type (might be due to invalid IL or missing references)
		//IL_054c: Expected O, but got Unknown
		//IL_0547: Unknown result type (might be due to invalid IL or missing references)
		//IL_054d: Expected O, but got Unknown
		//IL_054f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0559: Expected O, but got Unknown
		//IL_057d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0587: Expected O, but got Unknown
		//IL_0582: Unknown result type (might be due to invalid IL or missing references)
		//IL_058c: Expected O, but got Unknown
		//IL_061c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0622: Expected O, but got Unknown
		//IL_0638: Unknown result type (might be due to invalid IL or missing references)
		//IL_063e: Expected O, but got Unknown
		//IL_0640: Unknown result type (might be due to invalid IL or missing references)
		//IL_064a: Expected O, but got Unknown
		//IL_0679: Unknown result type (might be due to invalid IL or missing references)
		//IL_067f: Expected O, but got Unknown
		//IL_068d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0693: Expected O, but got Unknown
		//IL_0695: Unknown result type (might be due to invalid IL or missing references)
		//IL_069f: Expected O, but got Unknown
		//IL_06cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d5: Expected O, but got Unknown
		//IL_06e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e9: Expected O, but got Unknown
		//IL_06eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f5: Expected O, but got Unknown
		//IL_0725: Unknown result type (might be due to invalid IL or missing references)
		//IL_072b: Expected O, but got Unknown
		//IL_073a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0740: Expected O, but got Unknown
		//IL_074d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0753: Expected O, but got Unknown
		//IL_0755: Unknown result type (might be due to invalid IL or missing references)
		//IL_075f: Expected O, but got Unknown
		//IL_078e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0794: Expected O, but got Unknown
		//IL_07a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a8: Expected O, but got Unknown
		//IL_07b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_07bb: Expected O, but got Unknown
		//IL_07bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c7: Expected O, but got Unknown
		//IL_03ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Expected O, but got Unknown
		//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d5: Expected O, but got Unknown
		//IL_05e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e8: Expected O, but got Unknown
		//IL_05ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f4: Expected O, but got Unknown
		Conductor conductor = chart.Conductor;
		float num = conductor.BeatAt(endMs);
		if (!chart.EventNames.Contains("FocusCamera"))
		{
			int num2 = -1;
			for (int i = 0; (float)(i * 4) < num; i++)
			{
				float num3 = conductor.MsAtBeat(i * 4);
				float num4 = conductor.MsAtBeat(i * 4 + 4);
				int num5 = 0;
				int num6 = 0;
				foreach (NoteData note in chart.Notes)
				{
					if (!(note.Time < num3))
					{
						if (note.Time >= num4)
						{
							break;
						}
						if (note.Player)
						{
							num5++;
						}
						else
						{
							num6++;
						}
					}
				}
				if (num5 != 0 || num6 != 0)
				{
					int num7 = ((num5 <= num6) ? 1 : 0);
					if (num7 != num2)
					{
						num2 = num7;
						into.Add(Make(num3, "FocusCamera", (JToken)new JObject((object)new JProperty("char", (object)num7))));
					}
				}
			}
		}
		if (!remix)
		{
			return;
		}
		string[] array = new string[9] { "flash", "shake", "punch", "sway", "lights", "hey", "bop", "glitch", "zoom" };
		for (float num8 = 16f; num8 + 16f <= num; num8 += 16f)
		{
			float num9 = conductor.MsAtBeat(num8);
			bool flag = false;
			foreach (NoteData note2 in chart.Notes)
			{
				if (note2.Time >= num9 && note2.Time < conductor.MsAtBeat(num8 + 16f))
				{
					flag = true;
					break;
				}
			}
			if (!flag || rng.NextDouble() < 0.25)
			{
				continue;
			}
			switch (array[rng.Next(array.Length)])
			{
			case "flash":
				into.Add(Make(num9, "MFFlash", (JToken)new JObject(new object[3]
				{
					(object)new JProperty("color", (object)"#FFFFFF"),
					(object)new JProperty("duration", (object)4),
					(object)new JProperty("strength", (object)0.35)
				})));
				break;
			case "shake":
				into.Add(Make(num9, "MFShake", (JToken)new JObject(new object[2]
				{
					(object)new JProperty("intensity", (object)0.004),
					(object)new JProperty("duration", (object)6)
				})));
				break;
			case "punch":
			{
				for (int j = 0; j < 4; j++)
				{
					into.Add(Make(conductor.MsAtBeat(num8 + (float)(j * 4)), "__ZoomPunch", (JToken)new JValue(0.06)));
				}
				break;
			}
			case "sway":
				into.Add(Make(num9, "MFStrumFX", (JToken)new JObject(new object[3]
				{
					(object)new JProperty("mode", (object)"sway"),
					(object)new JProperty("amount", (object)0.35),
					(object)new JProperty("speed", (object)0.5)
				})));
				into.Add(Make(conductor.MsAtBeat(num8 + 15f), "MFStrumFX", (JToken)new JObject((object)new JProperty("mode", (object)"off"))));
				break;
			case "lights":
			{
				string[] array2 = new string[5] { "#FF6D43FF", "#FFFF43A1", "#FF43FFD2", "#FFFFE943", "#FF8A43FF" };
				into.Add(Make(num9, "sserafimPulseLights", (JToken)new JObject(new object[3]
				{
					(object)new JProperty("enabled", (object)true),
					(object)new JProperty("colors", (object)new JArray(new object[2]
					{
						array2[rng.Next(array2.Length)],
						array2[rng.Next(array2.Length)]
					})),
					(object)new JProperty("intensities", (object)new JArray(new object[2] { 0.6, 0.8 }))
				})));
				into.Add(Make(conductor.MsAtBeat(num8 + 15.5f), "sserafimPulseLights", (JToken)new JObject((object)new JProperty("enabled", (object)false))));
				break;
			}
			case "hey":
				into.Add(Make(conductor.MsAtBeat(num8 + 14f), "PlayAnimation", (JToken)new JObject(new object[2]
				{
					(object)new JProperty("target", (object)((rng.Next(2) == 0) ? "bf" : "dad")),
					(object)new JProperty("anim", (object)"hey")
				})));
				break;
			case "bop":
				into.Add(Make(num9, "SetCameraBop", (JToken)new JObject(new object[2]
				{
					(object)new JProperty("rate", (object)1),
					(object)new JProperty("intensity", (object)1.5)
				})));
				into.Add(Make(conductor.MsAtBeat(num8 + 8f), "SetCameraBop", (JToken)new JObject(new object[2]
				{
					(object)new JProperty("rate", (object)4),
					(object)new JProperty("intensity", (object)1)
				})));
				break;
			case "glitch":
				into.Add(Make(num9, "MFGlitch", (JToken)new JObject(new object[2]
				{
					(object)new JProperty("intensity", (object)0.4),
					(object)new JProperty("duration", (object)4)
				})));
				break;
			case "zoom":
				into.Add(Make(num9, "ZoomCamera", (JToken)new JObject(new object[3]
				{
					(object)new JProperty("zoom", (object)1.25),
					(object)new JProperty("duration", (object)16),
					(object)new JProperty("ease", (object)"expoOut")
				})));
				into.Add(Make(conductor.MsAtBeat(num8 + 8f), "ZoomCamera", (JToken)new JObject(new object[3]
				{
					(object)new JProperty("zoom", (object)1),
					(object)new JProperty("duration", (object)8),
					(object)new JProperty("ease", (object)"quadInOut")
				})));
				break;
			}
		}
	}

	private static EventData Make(float t, string name, JToken value)
	{
		EventData eventData = new EventData();
		eventData.Time = t;
		eventData.Name = name;
		eventData.Value = value;
		return eventData;
	}
}
internal static class EventRunner
{
	internal static void Run(RapBattle b, EventData e)
	{
		//IL_06ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0727: Unknown result type (might be due to invalid IL or missing references)
		//IL_0759: Unknown result type (might be due to invalid IL or missing references)
		//IL_075e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0775: Unknown result type (might be due to invalid IL or missing references)
		//IL_0945: Unknown result type (might be due to invalid IL or missing references)
		//IL_098a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a38: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a3d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a86: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c43: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c48: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d91: Unknown result type (might be due to invalid IL or missing references)
		//IL_0e26: Unknown result type (might be due to invalid IL or missing references)
		//IL_0836: Unknown result type (might be due to invalid IL or missing references)
		//IL_09aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0906: Unknown result type (might be due to invalid IL or missing references)
		//IL_09af: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_09b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0af8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0afd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b02: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
		JToken value = e.Value;
		float stepMs = b.StepMs;
		float songPos = b.SongPos;
		BattleStage stage = b.Stage;
		BattleHud hud = b.Hud;
		switch (e.Name)
		{
		case "FocusCamera":
		{
			float x = 0f;
			float y = 0f;
			float num6 = 4f;
			string ease = "CLASSIC";
			int character;
			if (value is JObject)
			{
				character = (int)Num(value, "char", 0f);
				x = Num(value, "x", 0f);
				y = Num(value, "y", 0f);
				num6 = Num(value, "duration", 4f);
				ease = Ease.Combine(Str(value, "ease", "CLASSIC"), Str(value, "easeDir", null));
			}
			else
			{
				character = (int)SongLibrary.Num(value, 0f);
			}
			stage.Focus(character, x, y, num6 * stepMs, ease, songPos);
			break;
		}
		case "ZoomCamera":
		{
			float value2 = Num(value, "zoom", 1f);
			float num7 = Num(value, "duration", 4f);
			string ease2 = Ease.Combine(Str(value, "ease", "linear"), Str(value, "easeDir", null));
			stage.Zoom(value2, num7 * stepMs, ease2, songPos);
			break;
		}
		case "SetCameraBop":
			b.SetCameraBop(Mathf.RoundToInt(Num(value, "rate", 4f)), Num(value, "intensity", 1f));
			break;
		case "ScrollSpeed":
		{
			float num = Num(value, "scroll", 1f);
			float num2 = (Bool(value, "absolute", fallback: false) ? (num * RapBattlePlugin.ScrollSpeedMultiplier.Value) : (b.ChartScrollSpeed * num));
			float num3 = Num(value, "duration", 4f) * stepMs;
			string text2 = Ease.Combine(Str(value, "ease", "linear"), Str(value, "easeDir", null));
			b.SetScrollSpeed(Mathf.Clamp(num2, 0.3f, 6f), (text2.ToUpperInvariant() == "INSTANT") ? 0f : num3, Ease.Get(text2));
			break;
		}
		case "PlayAnimation":
		{
			string t3 = Str(value, "target", "bf").ToLowerInvariant();
			string text4 = Str(value, "anim", "").ToLowerInvariant();
			Poser poser = (IsPlayer(t3) ? b.V1Poser : (IsEnemy(t3) ? b.EnemyPoser : null));
			poser?.Special(songPos, stepMs * 6f);
			if (IsPlayer(t3) && b.Bf != null)
			{
				b.Bf.Hey(songPos, stepMs * 6f);
			}
			if (poser == null && (!IsPlayer(t3) || b.Bf == null))
			{
				stage.Bop(0.03f);
			}
			if (text4.Contains("hey") || text4.Contains("cheer"))
			{
				hud.Banner("HEY!", IsEnemy(t3) ? BattleHud.EnemyColor : BattleHud.V1Color, 0.6f);
			}
			break;
		}
		case "SetTargetBopSpeed":
		{
			string t2 = Str(value, "target", "").ToLowerInvariant();
			float danceEvery = Mathf.Max(1f, Num(value, "rate", 2f));
			if (IsPlayer(t2) && b.V1Poser != null)
			{
				b.V1Poser.DanceEvery = danceEvery;
			}
			else if (IsEnemy(t2))
			{
				b.EnemyPoser.DanceEvery = danceEvery;
			}
			break;
		}
		case "__ZoomPunch":
			stage.Bop(SongLibrary.Num(value, 0.05f));
			hud.HudBop += 0.03f;
			break;
		case "MFShake":
			stage.Shake(Num(value, "intensity", 0.01f), Num(value, "duration", 4f) * stepMs / 1000f);
			break;
		case "sserafimGuitarVibration":
			stage.Shake(0.004f, Num(value, "duration", 0.5f));
			break;
		case "sserafimKick":
			stage.Bop(0.05f);
			stage.Shake(0.006f, 0.15f);
			break;
		case "MFFlash":
			hud.Flash(ParseColor(Str(value, "color", "#FFFFFF"), Color.white), Num(value, "duration", 4f) * stepMs / 1000f, Num(value, "strength", 0.8f));
			break;
		case "sserafimFlash":
			hud.Flash(Color.white, Num(value, "duration", 1f), 0.8f);
			break;
		case "RemnantsSNES":
			hud.Flash(ParseColor(Str(value, "color", "RED"), Color.red), 0.5f, 0.5f);
			break;
		case "changeStage":
		case "PlayExplVideo":
		case "TankmanAscendsEvent":
			hud.Flash(Color.white, 0.6f, 0.7f);
			stage.Bop(0.06f);
			break;
		case "MFGlitch":
			if (Str(value, "mode", "burst") == "ambient")
			{
				hud.Glitch(9999f, Num(value, "intensity", 0.3f) * 0.5f);
			}
			else
			{
				hud.Glitch(Num(value, "duration", 4f) * stepMs / 1000f, Num(value, "intensity", 0.6f));
			}
			break;
		case "MFInvert":
		{
			string text3 = Str(value, "mode", "pulse");
			if (!(text3 == "off"))
			{
				hud.Flash(new Color(0.4f, 1f, 0.95f), Num(value, "duration", 4f) * stepMs / 1000f, 0.55f);
				hud.Glitch(Num(value, "duration", 4f) * stepMs / 1000f, 0.3f);
			}
			break;
		}
		case "MFLights":
			Darken(hud, Str(value, "mode", "normal") switch
			{
				"dim" => 0.35f, 
				"spotlight" => 0.82f, 
				"blackout" => 0.96f, 
				"dark" => 0.6f, 
				_ => 0f, 
			}, Num(value, "duration", 4f) * stepMs, songPos, Color.black);
			break;
		case "sserafimDark":
			Darken(hud, Mathf.Clamp01(Num(value, "amount", 0.5f)) * 0.8f, Num(value, "duration", 0.5f) * 1000f, songPos, Color.black);
			break;
		case "sserafimLights":
			Darken(hud, Mathf.Clamp01(1f - Num(value, "amount", 1f)) * 0.7f, Num(value, "duration", 0.5f) * 1000f, songPos, Color.black);
			break;
		case "RemnantsOverlay":
		{
			Color darkColor = (Bool(value, "white", fallback: false) ? Color.white : Color.black);
			hud.DarkColor = darkColor;
			hud.Dark.Set(Mathf.Clamp01(Num(value, "startOpacity", 1f)));
			hud.Dark.To(Mathf.Clamp01(Num(value, "endOpacity", 0f)), songPos, Num(value, "duration", 16f) * stepMs, Ease.Get(Ease.Combine(Str(value, "ease", "linear"), Str(value, "easeDir", null))));
			break;
		}
		case "blackIn":
		case "cutsceneVideoOut":
			hud.DarkColor = Color.black;
			hud.Dark.Set(1f);
			hud.Dark.To(0f, songPos, stepMs * 8f, Ease.Get("quadOut"));
			break;
		case "fadeStart":
		case "cutsceneVideo":
			Darken(hud, 0.85f, stepMs * 8f, songPos, Color.black);
			break;
		case "sserafimPulseLights":
		{
			hud.PulseOn = Bool(value, "enabled", fallback: true);
			JArray val = Arr(value, "colors");
			if (val != null && ((JContainer)val).Count > 0)
			{
				hud.PulseColors = (Color[])(object)new Color[((JContainer)val).Count];
				for (int i = 0; i < ((JContainer)val).Count; i++)
				{
					ref Color reference = ref hud.PulseColors[i];
					reference = ParseColor(SongLibrary.Str(val[i], "#FFFFFF"), Color.white);
				}
			}
			JArray val2 = Arr(value, "intensities");
			if (val2 != null && ((JContainer)val2).Count > 0)
			{
				hud.PulseIntensities = new float[((JContainer)val2).Count];
				for (int j = 0; j < ((JContainer)val2).Count; j++)
				{
					hud.PulseIntensities[j] = SongLibrary.Num(val2[j], 0.6f);
				}
			}
			break;
		}
		case "HazierGarcelloVignetteEvent":
			hud.Vignette = (Bool(value, "isActive", fallback: true) ? Mathf.Clamp(Num(value, "strength", 20f) / 30f, 0.2f, 0.9f) : 0f);
			break;
		case "MFHud":
		{
			float num4 = Num(value, "duration", 4f) * stepMs;
			float num5 = Mathf.Clamp01(Num(value, "alpha", 1f));
			if (num4 <= 10f)
			{
				hud.HudAlpha.Set(num5);
			}
			else
			{
				hud.HudAlpha.To(num5, songPos, num4, Ease.Get("quadInOut"));
			}
			break;
		}
		case "MFLyrics":
			hud.Lyrics(Str(value, "text", ""), ParseColor(Str(value, "color", "#FFFFFF"), Color.white), Num(value, "duration", 16f) * stepMs / 1000f, Str(value, "style", "normal") == "glitch");
			break;
		case "MFStrumFX":
		{
			string text = Str(value, "mode", "off");
			hud.SwayAmount = ((text == "off" || text == "none") ? 0f : Num(value, "amount", 1f));
			hud.SwaySpeed = Num(value, "speed", 1f);
			break;
		}
		case "MFStrumSwap":
			hud.Swap.To((hud.Swap.Target > 0.5f) ? 0f : 1f, songPos, Num(value, "duration", 8f) * stepMs, Ease.Get("quadInOut"));
			break;
		case "MFScrollFlip":
			hud.Flip.To((hud.Flip.Target > 0.5f) ? 0f : 1f, songPos, Num(value, "duration", 4f) * stepMs, Ease.Get("quadInOut"));
			break;
		case "SkillIssue":
			hud.Banner("SKILL ISSUE", new Color(1f, 0.3f, 0.3f), 1.5f);
			break;
		case "SetHealthIcon":
			stage.Bop(0.02f);
			break;
		case "MFHealthDrain":
			b.SetDrain(2f * Num(value, "amount", 0f) / 100f, Num(value, "floor", 15f) / 100f);
			break;
		case "HP Gremlin":
			b.Gremlin(0.35f, Mathf.Max(0.5f, SongLibrary.Num(Get(value, "value2"), 1.5f)));
			hud.Banner("HP GREMLIN!", new Color(0.6f, 1f, 0.4f), 1.2f);
			break;
		case "MFCharAlpha":
		{
			string t = Str(value, "target", "dad").ToLowerInvariant();
			bool hidden = Num(value, "alpha", 1f) < 0.5f;
			(IsPlayer(t) ? b.V1Poser : (IsEnemy(t) ? b.EnemyPoser : null))?.SetHidden(hidden);
			break;
		}
		default:
			stage.Bop(0.025f);
			hud.HudBop += 0.015f;
			b.LogUnknownEvent(e.Name);
			break;
		case "sawKB":
		case "MFShatter":
			break;
		}
	}

	private static void Darken(BattleHud hud, float amount, float durationMs, float now, Color color)
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0003: Unknown result type (might be due to invalid IL or missing references)
		hud.DarkColor = color;
		if (durationMs <= 10f)
		{
			hud.Dark.Set(amount);
		}
		else
		{
			hud.Dark.To(amount, now, durationMs, Ease.Get("quadInOut"));
		}
	}

	private static bool IsPlayer(string t)
	{
		switch (t)
		{
		default:
			return t == "0";
		case "bf":
		case "boyfriend":
		case "player":
			return true;
		}
	}

	private static bool IsEnemy(string t)
	{
		switch (t)
		{
		default:
			return t == "1";
		case "dad":
		case "opponent":
		case "enemy":
			return true;
		}
	}

	private static JToken Get(JToken v, string key)
	{
		JObject val = (JObject)(object)((v is JObject) ? v : null);
		if (val == null)
		{
			return null;
		}
		return val[key];
	}

	private static float Num(JToken v, string key, float fallback)
	{
		return SongLibrary.Num(Get(v, key), fallback);
	}

	private static string Str(JToken v, string key, string fallback)
	{
		return SongLibrary.Str(Get(v, key), fallback);
	}

	private static bool Bool(JToken v, string key, bool fallback)
	{
		return SongLibrary.Bool(Get(v, key), fallback);
	}

	private static JArray Arr(JToken v, string key)
	{
		JToken obj = Get(v, key);
		return (JArray)(object)((obj is JArray) ? obj : null);
	}

	internal static Color ParseColor(string s, Color fallback)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: Unknown result type (might be due to invalid IL or missing references)
		if (string.IsNullOrEmpty(s))
		{
			return fallback;
		}
		string text = s.Trim();
		switch (text.ToUpperInvariant())
		{
		case "RED":
			return Color.red;
		case "GREEN":
			return Color.green;
		case "BLUE":
			return new Color(0.2f, 0.4f, 1f);
		case "WHITE":
			return Color.white;
		case "BLACK":
			return Color.black;
		case "YELLOW":
			return Color.yellow;
		case "PURPLE":
			return new Color(0.6f, 0.2f, 1f);
		case "PINK":
			return new Color(1f, 0.4f, 0.75f);
		case "CYAN":
			return Color.cyan;
		case "ORANGE":
			return new Color(1f, 0.55f, 0.1f);
		default:
		{
			if (text.StartsWith("#"))
			{
				text = text.Substring(1);
			}
			else if (text.StartsWith("0x") || text.StartsWith("0X"))
			{
				text = text.Substring(2);
			}
			if (!uint.TryParse(text, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
			{
				return fallback;
			}
			if (text.Length == 6)
			{
				result |= 0xFF000000u;
			}
			return new Color((float)((result >> 16) & 0xFF) / 255f, (float)((result >> 8) & 0xFF) / 255f, (float)(result & 0xFF) / 255f, 1f);
		}
		}
	}
}
internal class AtlasFrame
{
	public Rect Uv;

	public float W;

	public float H;

	public float OffX;

	public float OffY;

	public float FrameW;

	public float FrameH;
}
internal class Atlas
{
	public Texture2D Texture;

	private readonly Dictionary<string, List<AtlasFrame>> anims = new Dictionary<string, List<AtlasFrame>>();

	private static readonly Regex SubTexture = new Regex("<SubTexture\\s+([^>]*?)/?>", RegexOptions.Compiled);

	private static readonly Regex Attr = new Regex("(\\w+)\\s*=\\s*\"([^\"]*)\"", RegexOptions.Compiled);

	private static readonly Regex Spaces = new Regex("\\s+", RegexOptions.Compiled);

	public static Atlas Load(string png, string xml)
	{
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = FnfAssets.LoadTexture(png);
		if ((Object)(object)val == (Object)null || !File.Exists(xml))
		{
			return null;
		}
		Atlas atlas = new Atlas();
		atlas.Texture = val;
		Dictionary<string, SortedList<int, AtlasFrame>> dictionary = new Dictionary<string, SortedList<int, AtlasFrame>>();
		foreach (Match item in SubTexture.Matches(File.ReadAllText(xml)))
		{
			Dictionary<string, string> dictionary2 = new Dictionary<string, string>();
			foreach (Match item2 in Attr.Matches(item.Groups[1].Value))
			{
				dictionary2[item2.Groups[1].Value] = item2.Groups[2].Value;
			}
			if (dictionary2.TryGetValue("name", out var value))
			{
				AtlasFrame atlasFrame = new AtlasFrame();
				float num = F(dictionary2, "x");
				float num2 = F(dictionary2, "y");
				atlasFrame.W = F(dictionary2, "width");
				atlasFrame.H = F(dictionary2, "height");
				atlasFrame.Uv = new Rect(num / (float)((Texture)val).width, 1f - (num2 + atlasFrame.H) / (float)((Texture)val).height, atlasFrame.W / (float)((Texture)val).width, atlasFrame.H / (float)((Texture)val).height);
				atlasFrame.OffX = 0f - F(dictionary2, "frameX");
				atlasFrame.OffY = 0f - F(dictionary2, "frameY");
				atlasFrame.FrameW = (dictionary2.ContainsKey("frameWidth") ? F(dictionary2, "frameWidth") : atlasFrame.W);
				atlasFrame.FrameH = (dictionary2.ContainsKey("frameHeight") ? F(dictionary2, "frameHeight") : atlasFrame.H);
				int i;
				for (i = 0; i < value.Length && char.IsDigit(value[value.Length - 1 - i]); i++)
				{
				}
				string key = Spaces.Replace(value.Substring(0, value.Length - i), " ").Trim();
				int result = 0;
				if (i > 0)
				{
					int.TryParse(value.Substring(value.Length - i), out result);
				}
				if (!dictionary.TryGetValue(key, out var value2))
				{
					value2 = (dictionary[key] = new SortedList<int, AtlasFrame>());
				}
				value2[result] = atlasFrame;
			}
		}
		foreach (KeyValuePair<string, SortedList<int, AtlasFrame>> item3 in dictionary)
		{
			atlas.anims[item3.Key] = new List<AtlasFrame>(item3.Value.Values);
		}
		return atlas;
	}

	private static float F(Dictionary<string, string> a, string key)
	{
		if (a.TryGetValue(key, out var value) && float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
		{
			return result;
		}
		return 0f;
	}

	public List<AtlasFrame> Anim(string prefix)
	{
		if (!anims.TryGetValue(prefix, out var value))
		{
			return null;
		}
		return value;
	}

	public AtlasFrame Frame(string prefix, int index)
	{
		List<AtlasFrame> list = Anim(prefix);
		if (list == null || list.Count == 0)
		{
			return null;
		}
		return list[Mathf.Clamp(index, 0, list.Count - 1)];
	}
}
internal static class FnfAssets
{
	internal static Atlas Notes;

	internal static Atlas Strums;

	internal static Atlas Splashes;

	internal static Texture2D Holds;

	internal static Texture2D HealthBar;

	internal static Texture2D Combo;

	internal static Texture2D[] Ratings = (Texture2D[])(object)new Texture2D[4];

	internal static Texture2D[] Digits = (Texture2D[])(object)new Texture2D[10];

	internal static Texture2D[] Countdown = (Texture2D[])(object)new Texture2D[3];

	internal static AudioClip[] CountdownSounds = (AudioClip[])(object)new AudioClip[4];

	internal static AudioClip[] MissSounds = (AudioClip[])(object)new AudioClip[3];

	internal static AudioClip LossSound;

	internal static Texture2D Vignette;

	internal static Texture2D Ring;

	internal static Font Font;

	private static string loadedFrom;

	private static bool soundsLoaded;

	private static bool fontSearched;

	internal static void EnsureTextures()
	{
		string funkinFolder = SongLibrary.FunkinFolder;
		if (!(loadedFrom == funkinFolder))
		{
			loadedFrom = funkinFolder;
			string path = Path.Combine(Path.Combine(funkinFolder, "assets"), "shared");
			string path2 = Path.Combine(path, "images");
			Notes = Atlas.Load(Path.Combine(path2, "notes.png"), Path.Combine(path2, "notes.xml"));
			Strums = Atlas.Load(Path.Combine(path2, "noteStrumline.png"), Path.Combine(path2, "noteStrumline.xml"));
			Splashes = Atlas.Load(Path.Combine(path2, "noteSplashes.png"), Path.Combine(path2, "noteSplashes.xml"));
			Holds = LoadTexture(Path.Combine(path2, "NOTE_hold_assets.png"));
			HealthBar = LoadTexture(Path.Combine(path2, "healthBar.png"));
			string path3 = Path.Combine(funkinFolder, Path.Combine("assets", Path.Combine("images", Path.Combine("ui", Path.Combine("popup", "funkin")))));
			string[] array = new string[4] { "sick", "good", "bad", "shit" };
			for (int i = 0; i < 4; i++)
			{
				Ratings[i] = LoadTexture(Path.Combine(path3, array[i] + ".png"));
			}
			for (int j = 0; j < 10; j++)
			{
				Digits[j] = LoadTexture(Path.Combine(path3, "num" + j + ".png"));
			}
			Combo = LoadTexture(Path.Combine(path3, "combo.png"));
			string path4 = Path.Combine(path2, Path.Combine("ui", Path.Combine("countdown", "funkin")));
			string[] array2 = new string[3] { "ready", "set", "go" };
			for (int k = 0; k < 3; k++)
			{
				Countdown[k] = LoadTexture(Path.Combine(path4, array2[k] + ".png"));
			}
			if ((Object)(object)Vignette == (Object)null)
			{
				Vignette = MakeRadial(128, ring: false);
			}
			if ((Object)(object)Ring == (Object)null)
			{
				Ring = MakeRadial(128, ring: true);
			}
			if ((Object)(object)Font == (Object)null)
			{
				Font = FindFont();
			}
			RapBattlePlugin.Log.LogInfo((object)("FNF art: notes " + (Notes != null) + ", strums " + (Strums != null) + ", splashes " + (Splashes != null) + ", holds " + ((Object)(object)Holds != (Object)null) + ", font " + (((Object)(object)Font != (Object)null) ? ((Object)Font).name : "default")));
		}
	}

	internal static IEnumerator EnsureSounds()
	{
		if (soundsLoaded)
		{
			yield break;
		}
		soundsLoaded = true;
		string sounds = Path.Combine(Path.Combine(Path.Combine(SongLibrary.FunkinFolder, "assets"), "shared"), "sounds");
		string countdown = Path.Combine(sounds, Path.Combine("gameplay", Path.Combine("countdown", "funkin")));
		string[] cd = new string[4] { "introTHREE", "introTWO", "introONE", "introGO" };
		for (int i = 0; i < 4; i++)
		{
			int slot = i;
			yield return LoadClip(Path.Combine(countdown, cd[i] + ".ogg"), compressed: false, delegate(AudioClip c)
			{
				CountdownSounds[slot] = c;
			});
		}
		for (int i2 = 0; i2 < 3; i2++)
		{
			int slot2 = i2;
			yield return LoadClip(Path.Combine(sounds, "missnote" + (i2 + 1) + ".ogg"), compressed: false, delegate(AudioClip c)
			{
				MissSounds[slot2] = c;
			});
		}
		yield return LoadClip(Path.Combine(sounds, Path.Combine("gameplay", Path.Combine("gameover", "fnf_loss_sfx.ogg"))), compressed: false, delegate(AudioClip c)
		{
			LossSound = c;
		});
	}

	internal static Texture2D LoadTexture(string path)
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		try
		{
			if (!File.Exists(path))
			{
				return null;
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, File.ReadAllBytes(path), false))
			{
				return null;
			}
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Texture)val).filterMode = (FilterMode)1;
			((Object)val).hideFlags = (HideFlags)32;
			return val;
		}
		catch (Exception ex)
		{
			RapBattlePlugin.Log.LogWarning((object)("Could not load " + path + ": " + ex.Message));
			return null;
		}
	}

	internal static IEnumerator LoadClip(string path, bool compressed, Action<AudioClip> done)
	{
		if (string.IsNullOrEmpty(path) || !File.Exists(path))
		{
			done(null);
			yield break;
		}
		UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(FileUrl(path), (AudioType)14);
		DownloadHandler downloadHandler = req.downloadHandler;
		DownloadHandlerAudioClip handler = (DownloadHandlerAudioClip)(object)((downloadHandler is DownloadHandlerAudioClip) ? downloadHandler : null);
		if (handler != null)
		{
			handler.compressed = compressed;
		}
		yield return req.SendWebRequest();
		AudioClip clip = null;
		if ((int)req.result == 1)
		{
			try
			{
				clip = DownloadHandlerAudioClip.GetContent(req);
			}
			catch (Exception ex)
			{
				RapBattlePlugin.Log.LogWarning((object)("Could not decode " + path + ": " + ex.Message));
			}
		}
		else
		{
			RapBattlePlugin.Log.LogWarning((object)("Could not load " + path + ": " + req.error));
		}
		req.Dispose();
		if ((Object)(object)clip != (Object)null)
		{
			((Object)clip).name = Path.GetFileNameWithoutExtension(path);
		}
		done(clip);
	}

	private static string FileUrl(string path)
	{
		string text = Path.GetFullPath(path).Replace('\\', '/');
		string[] array = text.Split('/');
		StringBuilder stringBuilder = new StringBuilder("file:///");
		for (int i = 0; i < array.Length; i++)
		{
			if (i > 0)
			{
				stringBuilder.Append('/');
			}
			stringBuilder.Append((i == 0 && array[i].EndsWith(":")) ? array[i] : Uri.EscapeDataString(array[i]));
		}
		return stringBuilder.ToString();
	}

	private static Texture2D MakeRadial(int size, bool ring)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Expected O, but got Unknown
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
		((Texture)val).wrapMode = (TextureWrapMode)1;
		((Object)val).hideFlags = (HideFlags)32;
		Color[] array = (Color[])(object)new Color[size * size];
		float num = (float)(size - 1) * 0.5f;
		for (int i = 0; i < size; i++)
		{
			for (int j = 0; j < size; j++)
			{
				float num2 = Mathf.Sqrt(((float)j - num) * ((float)j - num) + ((float)i - num) * ((float)i - num)) / num;
				float num3 = ((!ring) ? Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.45f, 1.15f, num2)) : Mathf.Clamp01(1f - Mathf.Abs(num2 - 0.86f) / 0.1f));
				ref Color reference = ref array[i * size + j];
				reference = new Color(1f, 1f, 1f, num3);
			}
		}
		val.SetPixels(array);
		val.Apply();
		return val;
	}

	internal static Font GetFont()
	{
		if ((Object)(object)Font == (Object)null && !fontSearched)
		{
			fontSearched = true;
			Font = FindFont();
		}
		return Font;
	}

	private static Font FindFont()
	{
		Font val = null;
		Font[] array = Resources.FindObjectsOfTypeAll<Font>();
		foreach (Font val2 in array)
		{
			string text = ((Object)val2).name.ToLowerInvariant();
			if (text.Contains("vcr"))
			{
				return val2;
			}
			if ((Object)(object)val == (Object)null && (text.Contains("mono") || text.Contains("pixel")))
			{
				val = val2;
			}
		}
		return val;
	}
}
internal static class FnfLocator
{
	private const int MaxFoldersVisited = 6000;

	internal static bool IsFnfFolder(string path)
	{
		if (string.IsNullOrEmpty(path))
		{
			return false;
		}
		try
		{
			string text = Path.Combine(path, "assets");
			if (!Directory.Exists(text))
			{
				return false;
			}
			return File.Exists(Path.Combine(path, "Funkin.exe")) || Directory.Exists(Path.Combine(Path.Combine(text, "data"), "songs"));
		}
		catch (Exception)
		{
			return false;
		}
	}

	internal static string Resolve(string configured)
	{
		string text = (configured ?? "").Trim().Trim('"');
		if (text.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
		{
			text = Path.GetDirectoryName(text);
		}
		if (IsFnfFolder(text))
		{
			return text;
		}
		List<KeyValuePair<string, int>> list = new List<KeyValuePair<string, int>>();
		string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
		Add(list, Path.Combine(folderPath, "Downloads"), 3);
		Add(list, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), 3);
		Add(list, Environment.GetFolderPath(Environment.SpecialFolder.Personal), 3);
		Add(list, Path.Combine(Path.Combine(folderPath, "OneDrive"), "Desktop"), 3);
		Add(list, Path.Combine(Path.Combine(folderPath, "OneDrive"), "Documents"), 3);
		Add(list, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "itch\\apps"), 2);
		Add(list, Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), 2);
		Add(list, Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), 2);
		Add(list, "C:\\Program Files (x86)\\Steam\\steamapps\\common", 2);
		foreach (DriveInfo item in SafeDrives())
		{
			Add(list, Path.Combine(item.RootDirectory.FullName, "Games"), 2);
			Add(list, Path.Combine(item.RootDirectory.FullName, "SteamLibrary\\steamapps\\common"), 2);
		}
		Add(list, folderPath, 1);
		int visited = 0;
		foreach (KeyValuePair<string, int> item2 in list)
		{
			string text2 = Search(item2.Key, item2.Value, ref visited);
			if (text2 != null)
			{
				RapBattlePlugin.Log.LogInfo((object)("Found Friday Night Funkin' at " + text2));
				return text2;
			}
			if (visited > 6000)
			{
				break;
			}
		}
		return null;
	}

	private static void Add(List<KeyValuePair<string, int>> roots, string path, int depth)
	{
		if (!string.IsNullOrEmpty(path))
		{
			roots.Add(new KeyValuePair<string, int>(path, depth));
		}
	}

	private static IEnumerable<DriveInfo> SafeDrives()
	{
		DriveInfo[] drives;
		try
		{
			drives = DriveInfo.GetDrives();
		}
		catch (Exception)
		{
			yield break;
		}
		try
		{
			DriveInfo[] array = drives;
			foreach (DriveInfo d in array)
			{
				bool ok;
				try
				{
					ok = d.DriveType == DriveType.Fixed && d.IsReady;
				}
				catch (Exception)
				{
					ok = false;
				}
				if (ok)
				{
					yield return d;
				}
			}
		}
		finally
		{
		}
	}

	private static string Search(string dir, int depth, ref int visited)
	{
		if (visited > 6000)
		{
			return null;
		}
		visited++;
		try
		{
			if (!Directory.Exists(dir))
			{
				return null;
			}
			if (File.Exists(Path.Combine(dir, "Funkin.exe")) && IsFnfFolder(dir))
			{
				return dir;
			}
			if (depth <= 0)
			{
				return null;
			}
			string[] directories = Directory.GetDirectories(dir);
			foreach (string text in directories)
			{
				string fileName = Path.GetFileName(text);
				if (!fileName.StartsWith(".") && !fileName.StartsWith("$") && !(fileName == "node_modules") && !(fileName == "Windows"))
				{
					string text2 = Search(text, depth - 1, ref visited);
					if (text2 != null)
					{
						return text2;
					}
				}
			}
		}
		catch (Exception)
		{
		}
		return null;
	}
}
internal class BattleHud
{
	private class Splash
	{
		public int Lane;

		public float T0;

		public int Variant;
	}

	private class Popup
	{
		public Texture2D Tex;

		public string Text;

		public Color Color;

		public float X;

		public float Y;

		public float Vy;

		public float T0;

		public float Life;

		public float Scale;

		public int Size;

		public bool Rating;
	}

	private const float NoteScale = 0.7f;

	private static readonly string[] Dirs = new string[4] { "Left", "Down", "Up", "Right" };

	private static readonly string[] SplashColors = new string[4] { "purple", "blue", "green", "red" };

	private static readonly Color[] NoteColors = (Color[])(object)new Color[4]
	{
		new Color(0.76f, 0.29f, 0.6f),
		new Color(0f, 1f, 1f),
		new Color(0.07f, 0.98f, 0.02f),
		new Color(0.98f, 0.22f, 0.25f)
	};

	internal static readonly Color EnemyColor = new Color(0.9f, 0.16f, 0.2f);

	internal static readonly Color V1Color = new Color(0.2f, 0.6f, 1f);

	private readonly RapBattle b;

	private GUIStyle style;

	private readonly int[] strumAnim = new int[8];

	private readonly float[] strumT0 = new float[8];

	private readonly float[] confirmUntil = new float[8];

	private readonly bool[] held = new bool[4];

	private readonly List<Splash> splashes = new List<Splash>();

	private readonly List<Popup> popups = new List<Popup>();

	public float HudBop;

	private float iconBop;

	private Color flashColor;

	private float flashAlpha;

	private float flashFade = 3f;

	public readonly FloatTween Dark = new FloatTween(0f);

	public Color DarkColor = Color.black;

	public readonly FloatTween HudAlpha = new FloatTween(1f);

	public readonly FloatTween Swap = new FloatTween(0f);

	public readonly FloatTween Flip = new FloatTween(0f);

	public float Vignette;

	public float SwayAmount;

	public float SwaySpeed = 0.5f;

	private float glitchUntil;

	private float glitchIntensity;

	private string lyrics;

	private Color lyricsColor;

	private float lyricsUntil;

	private bool lyricsGlitch;

	private string banner;

	private Color bannerColor;

	private float bannerT0;

	private float bannerUntil;

	public Color[] PulseColors;

	public float[] PulseIntensities;

	public bool PulseOn;

	private int pulseIndex;

	private float pulseAlpha;

	private Color pulseColor;

	private int countdownImage = -1;

	private float countdownT0;

	private string infoTitle;

	private string infoSub;

	private float infoT0 = -100f;

	private int result;

	private float resultT0;

	private int drawStart;

	public bool Boss;

	private float bossPulse;

	private float Now => b.SongPos;

	public BattleHud(RapBattle battle)
	{
		//IL_0062: 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)
		b = battle;
	}

	public void Press(int lane)
	{
		if (strumAnim[lane + 4] == 0)
		{
			strumAnim[lane + 4] = 1;
			strumT0[lane + 4] = Time.unscaledTime;
		}
	}

	public void SetHeld(int lane, bool down)
	{
		held[lane] = down;
	}

	public void PlayerHit(NoteData n, int rating)
	{
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Unknown result type (might be due to invalid IL or missing references)
		//IL_017f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_022c: Unknown result type (might be due to invalid IL or missing references)
		int num = n.Lane + 4;
		strumAnim[num] = 2;
		strumT0[num] = Time.unscaledTime;
		confirmUntil[num] = Time.unscaledTime + 0.12f;
		if (rating == 0)
		{
			splashes.Add(new Splash
			{
				Lane = n.Lane,
				T0 = Time.unscaledTime,
				Variant = Random.Range(1, 3)
			});
		}
		if (!RatingSpot(out var at, out var scale))
		{
			return;
		}
		for (int num2 = popups.Count - 1; num2 >= 0; num2--)
		{
			if (popups[num2].Rating)
			{
				popups.RemoveAt(num2);
			}
		}
		Texture2D tex = ((rating >= 0 && rating < 4) ? FnfAssets.Ratings[rating] : null);
		string[] array = new string[4] { "SICK!!", "GOOD!", "BAD", "SHIT" };
		Color[] array2 = (Color[])(object)new Color[4]
		{
			new Color(0.4f, 0.9f, 1f),
			new Color(0.4f, 1f, 0.5f),
			new Color(1f, 0.7f, 0.3f),
			new Color(0.7f, 0.5f, 0.4f)
		};
		popups.Add(new Popup
		{
			Tex = tex,
			Text = array[rating],
			Color = array2[rating],
			X = at.x,
			Y = at.y,
			Vy = -90f * scale,
			T0 = Time.unscaledTime,
			Life = 0.32f,
			Scale = 0.62f * scale,
			Size = (int)(40f * scale),
			Rating = true
		});
		AddComboNumbers(at, scale);
	}

	private bool RatingSpot(out Vector2 at, out float scale)
	{
		//IL_0016: 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_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		string value = RapBattlePlugin.RatingsPosition.Value;
		at = new Vector2(560f, 300f);
		scale = 0.75f;
		if (value == "Off")
		{
			return false;
		}
		if (value == "Center")
		{
			return true;
		}
		float num = DownAmount();
		float num2 = Mathf.Lerp(100f, 620f, num);
		float num3 = num2 + Mathf.Lerp(75f, -75f, num);
		float num4 = (RapBattlePlugin.Middlescroll.Value ? 300f : 640f);
		at = new Vector2(num4, num3);
		scale = 0.5f;
		return true;
	}

	private void AddComboNumbers(Vector2 at, float scale)
	{
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		int combo = b.Combo;
		if (combo >= 1)
		{
			string text = combo.ToString("000");
			float num = 40f * scale / 0.75f;
			float num2 = at.x - num * (float)(text.Length - 1) * 0.5f;
			for (int i = 0; i < text.Length; i++)
			{
				int num3 = text[i] - 48;
				popups.Add(new Popup
				{
					Tex = FnfAssets.Digits[num3],
					Text = text[i].ToString(),
					Color = Color.white,
					X = num2 + (float)i * num,
					Y = at.y + 60f * scale / 0.75f,
					Vy = -70f * scale,
					T0 = Time.unscaledTime,
					Life = 0.3f,
					Scale = 0.45f * scale / 0.75f,
					Size = (int)(34f * scale),
					Rating = true
				});
			}
		}
	}

	public void EnemyHit(NoteData n)
	{
		int lane = n.Lane;
		strumAnim[lane] = ((n.Length > 0f) ? 3 : 2);
		strumT0[lane] = Time.unscaledTime;
		confirmUntil[lane] = n.Time + Mathf.Max(n.Length, 150f);
	}

	public void Miss()
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		if (!RatingSpot(out var at, out var scale))
		{
			return;
		}
		for (int num = popups.Count - 1; num >= 0; num--)
		{
			if (popups[num].Rating)
			{
				popups.RemoveAt(num);
			}
		}
		popups.Add(new Popup
		{
			Text = "MISS",
			Color = new Color(0.75f, 0.4f, 1f),
			X = at.x,
			Y = at.y,
			Vy = -60f * scale,
			T0 = Time.unscaledTime,
			Life = 0.35f,
			Scale = 1f,
			Size = (int)(34f * scale),
			Rating = true
		});
	}

	public void Message(string text, Color color, float x, float y, int size)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		popups.Add(new Popup
		{
			Text = text,
			Color = color,
			X = x,
			Y = y,
			Vy = -60f,
			T0 = Time.unscaledTime,
			Life = 0.9f,
			Scale = 1f,
			Size = size
		});
	}

	public void Flash(Color color, float seconds, float strength)
	{
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp01(strength) * (RapBattlePlugin.ScreenFlashes.Value ? 1f : 0.15f);
		if (!(num < flashAlpha) || !(flashAlpha > 0.05f))
		{
			flashColor = color;
			flashAlpha = num;
			flashFade = num / Mathf.Max(0.05f, seconds);
		}
	}

	public void Glitch(float seconds, float intensity)
	{
		glitchUntil = Time.unscaledTime + seconds;
		glitchIntensity = Mathf.Clamp01(intensity);
	}

	public void Lyrics(string text, Color color, float seconds, bool glitch)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		lyrics = text;
		lyricsColor = color;
		lyricsUntil = Time.unscaledTime + seconds;
		lyricsGlitch = glitch;
	}

	public void Banner(string text, Color color, float seconds)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		banner = text;
		bannerColor = color;
		bannerT0 = Time.unscaledTime;
		bannerUntil = Time.unscaledTime + seconds;
	}

	public void Countdown(int image)
	{
		countdownImage = image;
		countdownT0 = Time.unscaledTime;
	}

	public void SongInfo(string title, string sub)
	{
		infoTitle = title;
		infoSub = sub;
		infoT0 = Time.unscaledTime;
	}

	public void Result(bool won)
	{
		result = (won ? 1 : 2);
		resultT0 = Time.unscaledTime;
	}

	public void Beat(int beat)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		iconBop = 1f;
		if (Boss)
		{
			bossPulse = 1f;
		}
		if (PulseOn && PulseColors != null && PulseColors.Length > 0)
		{
			pulseIndex = (pulseIndex + 1) % PulseColors.Length;
			pulseColor = PulseColors[pulseIndex];
			float num = ((PulseIntensities != null && PulseIntensities.Length > 0) ? PulseIntensities[pulseIndex % PulseIntensities.Length] : 0.6f);
			pulseAlpha = 0.28f * num * (RapBattlePlugin.ScreenFlashes.Value ? 1f : 0.3f);
		}
	}

	public void Tick(float dt)
	{
		HudBop *= Mathf.Exp(-3.1f * dt);
		iconBop = Mathf.MoveTowards(iconBop, 0f, dt * 6f);
		bossPulse = Mathf.MoveTowards(bossPulse, 0f, dt * 3f);
		flashAlpha = Mathf.MoveTowards(flashAlpha, 0f, flashFade * dt);
		pulseAlpha = Mathf.MoveTowards(pulseAlpha, 0f, dt * 0.9f);
		for (int i = 0; i < 4; i++)
		{
			int num = i + 4;
			if (strumAnim[num] != 0 && !held[i] && Time.unscaledTime >= confirmUntil[num])
			{
				strumAnim[num] = 0;
			}
			if (strumAnim[num] == 2 && b.IsHolding(i) && Time.unscaledTime - strumT0[num] > 1f / 6f)
			{
				strumAnim[num] = 3;
				strumT0[num] = Time.unscaledTime;
			}
			if (strumAnim[i] != 0 && Now > confirmUntil[i])
			{
				strumAnim[i] = 0;
			}
		}
		for (int num2 = splashes.Count - 1; num2 >= 0; num2--)
		{
			if (Time.unscaledTime - splashes[num2].T0 > 0.3f)
			{
				splashes.RemoveAt(num2);
			}
		}
		for (int num3 = popups.Count - 1; num3 >= 0; num3--)
		{
			Popup popup = popups[num3];
			if (Time.unscaledTime - popup.T0 > popup.Life + 0.25f)
			{
				popups.RemoveAt(num3);
			}
			else
			{
				popup.Vy += (popup.Rating ? 240f : 550f) * dt;
				popup.Y += popup.Vy * dt;
			}
		}
	}

	private void InitStyle()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0015: Expected O, but got Unknown
		style = new GUIStyle(GUI.skin.label);
		style.richText = false;
		style.wordWrap = false;
		style.clipping = (TextClipping)0;
		if ((Object)(object)FnfAssets.Font != (Object)null)
		{
			style.font = FnfAssets.Font;
		}
	}

	public void Draw()
	{
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		if (style == null)
		{
			InitStyle();
		}
		float num = (float)Screen.height / 720f;
		float num2 = (float)Screen.width / num;
		float num3 = (num2 - 1280f) * 0.5f;
		Matrix4x4 val = (GUI.matrix = Matrix4x4.Scale(new Vector3(num, num, 1f)) * Matrix4x4.Translate(new Vector3(num3, 0f, 0f)));
		DrawOverlays(new Rect(0f - num3 - 2f, -2f, num2 + 4f, 724f));
		Vector2 val3 = Vector2.zero;
		if (Time.unscaledTime < glitchUntil)
		{
			val3 = new Vector2(Random.Range(-1f, 1f), Random.Range(-1f, 1f)) * 14f * glitchIntensity;
		}
		float num4 = 1f + HudBop;
		GUI.matrix = val * Matrix4x4.Translate(new Vector3(640f + val3.x, 360f + val3.y, 0f)) * Matrix4x4.Scale(new Vector3(num4, num4, 1f)) * Matrix4x4.Translate(new Vector3(-640f, -360f, 0f));
		float num5 = Mathf.Clamp01(HudAlpha.Value(Now));
		if (b.Chart != null && num5 > 0.01f)
		{
			DrawStrumline(player: false, num5);
			DrawStrumline(player: true, num5);
			DrawHealth(num5);
		}
		DrawPopups();
		DrawCountdown();
		DrawAttack();
		DrawLyrics();
		DrawBanner();
		DrawInfo();
		DrawResult();
		DrawLoading();
		GUI.matrix = Matrix4x4.identity;
		GUI.color = Color.white;
	}

	private void DrawOverlays(Rect full)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Clamp01(Dark.Value(Now));
		if (num > 0.005f)
		{
			Fill(full, new Color(DarkColor.r, DarkColor.g, DarkColor.b, num));
		}
		if (pulseAlpha > 0.005f)
		{
			Fill(full, new Color(pulseColor.r, pulseColor.g, pulseColor.b, pulseAlpha));
		}
		if (Vignette > 0.01f && (Object)(object)FnfAssets.Vignette != (Object)null)
		{
			GUI.color = new Color(0f, 0f, 0f, Mathf.Clamp01(Vignette));
			GUI.DrawTexture(full, (Texture)(object)FnfAssets.Vignette, (ScaleMode)0, true);
		}
		if (Boss && (Object)(object)FnfAssets.Vignette != (Object)null)
		{
			float num2 = (RapBattlePlugin.ScreenFlashes.Value ? 1f : 0.4f);
			GUI.color = new Color(0.85f, 0f, 0.05f, (0.3f + 0.35f * bossPulse) * num2);
			GUI.DrawTexture(full, (Texture)(object)FnfAssets.Vignette, (ScaleMode)0, true);
		}
		if (Time.unscaledTime < glitchUntil && RapBattlePlugin.ScreenFlashes.Value)
		{
			int num3 = 2 + (int)(glitchIntensity * 6f);
			for (int i = 0; i < num3; i++)
			{
				float num4 = Random.Range(0f, 720f);
				Color c = ((Random.value > 0.5f) ? new Color(1f, 0f, 0.4f, 0.25f) : new Color(0f, 1f, 1f, 0.25f));
				Fill(new Rect(((Rect)(ref full)).x, num4, ((Rect)(ref full)).width, Random.Range(2f, 18f) * (0.5f + glitchIntensity)), c);
			}
		}
		if (flashAlpha > 0.005f)
		{
			Fill(full, new Color(flashColor.r, flashColor.g, flashColor.b, flashAlpha));
		}
	}

	private float StrumX(bool player, int lane)
	{
		float num = 112f + (float)lane * 112f;
		float num2 = (RapBattlePlugin.Middlescroll.Value ? (472f + (float)lane * 112f) : (832f + (float)lane * 112f));
		float num3 = Mathf.Clamp01(Swap.Value(Now));
		float num4 = (player ? Mathf.Lerp(num2, num, num3) : Mathf.Lerp(num, num2, num3));
		if (SwayAmount > 0.001f)
		{
			num4 += Mathf.Sin(Now / 1000f * (float)Math.PI * 2f * SwaySpeed + (float)lane * 0.8f + (player ? 0f : 2f)) * SwayAmount * 70f;
		}
		return num4;
	}

	private float DownAmount()
	{
		float num = Mathf.Clamp01(Flip.Value(Now));
		if (!RapBattlePlugin.Downscroll.Value)
		{
			return num;
		}
		return 1f - num;
	}

	private void DrawStrumline(bool player, float alpha)
	{
		//IL_038a: Unknown result type (might be due to invalid IL or missing references)
		if (!player && RapBattlePlugin.Middlescroll.Value)
		{
			return;
		}
		float num = DownAmount();
		float num2 = Mathf.Lerp(100f, 620f, num);
		float num3 = Mathf.Lerp(1f, -1f, num);
		float num4 = 0.45f * b.ScrollSpeed;
		for (int i = 0; i < 4; i++)
		{
			DrawStrum(player, i, StrumX(player, i), num2, alpha);
		}
		List<NoteData> notes = b.Chart.Notes;
		float now = Now;
		float num5 = 900f / Mathf.Max(0.1f, num4);
		while (drawStart < notes.Count && notes[drawStart].Time + notes[drawStart].Length < now - 2000f)
		{
			drawStart++;
		}
		for (int j = drawStart; j < notes.Count; j++)
		{
			NoteData noteData = notes[j];
			if (noteData.Time > now + num5)
			{
				break;
			}
			if (noteData.Player != player || noteData.Length <= 0f || noteData.HoldDone)
			{
				continue;
			}
			float num6 = noteData.Time + noteData.Length;
			if (!(num6 < now - 200f))
			{
				float x = StrumX(player, noteData.Lane);
				bool flag = noteData.Hit && (noteData.Holding || (!player && now < num6));
				if (!noteData.Hit || flag || noteData.Dropped)
				{
					float headY = (flag ? num2 : (num2 + num3 * (noteData.Time - now) * num4));
					float tailY = num2 + num3 * (num6 - now) * num4;
					float alpha2 = alpha * ((noteData.Dropped || noteData.Missed) ? 0.3f : 0.75f);
					DrawHold(noteData.Lane, x, headY, tailY, num3, alpha2);
				}
			}
		}
		for (int k = drawStart; k < notes.Count; k++)
		{
			NoteData noteData2 = notes[k];
			if (noteData2.Time > now + num5)
			{
				break;
			}
			if (noteData2.Player == player && !noteData2.Hit)
			{
				float num7 = num2 + num3 * (noteData2.Time - now) * num4;
				if (!(num7 < -120f) && !(num7 > 840f))
				{
					float alpha3 = alpha * (noteData2.Missed ? 0.35f : 1f);
					DrawNote(noteData2, StrumX(player, noteData2.Lane), num7, alpha3);
				}
			}
		}
		if (!player)
		{
			return;
		}
		foreach (Splash splash in splashes)
		{
			int index = (int)((Time.unscaledTime - splash.T0) * 24f);
			AtlasFrame atlasFrame = ((FnfAssets.Splashes != null) ? FnfAssets.Splashes.Frame("note impact " + splash.Variant + " " + SplashColors[splash.Lane], index) : null);
			if (atlasFrame != null)
			{
				DrawFrame(FnfAssets.Splashes.Texture, atlasFrame, StrumX(player: true, splash.Lane), num2, 0.8f, new Color(1f, 1f, 1f, 0.75f * alpha), flipY: false);
			}
		}
	}

	private void DrawStrum(bool player, int lane, float x, float y, float alpha)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		int num = (player ? (lane + 4) : lane);
		Atlas strums = FnfAssets.Strums;
		if (strums == null)
		{
			Fill(Centered(x, y, 100f, 100f), new Color(0.6f, 0.6f, 0.65f, 0.6f * alpha));
			return;
		}
		int num2 = (int)((Time.unscaledTime - strumT0[num]) * 24f);
		AtlasFrame atlasFrame = strumAnim[num] switch
		{
			1 => strums.Frame("press" + Dirs[lane], Mathf.Min(num2, 3)), 
			2 => strums.Frame("confirm" + Dirs[lane], Mathf.Min(num2, 3)), 
			3 => strums.Frame("confirmHold" + Dirs[lane], num2 % 4), 
			_ => strums.Frame("static" + Dirs[lane], 0), 
		};
		if (atlasFrame != null)
		{
			DrawFrame(strums.Texture, atlasFrame, x, y, 0.7f, new Color(1f, 1f, 1f, alpha), flipY: false);
		}
	}

	private void DrawNote(NoteData n, float x, float y, float alpha)
	{
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_016f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		AtlasFrame atlasFrame = ((FnfAssets.Notes != null) ? FnfAssets.Notes.Frame("note" + Dirs[n.Lane], 0) : null);
		if (n.Avoid)
		{
			float num = 0.75f + 0.25f * Mathf.Sin(Time.unscaledTime * 12f);
			if (atlasFrame != null)
			{
				DrawFrame(FnfAssets.Notes.Texture, atlasFrame, x, y, 0.7f, new Color(0.32f * num, 0.04f, 0.08f, alpha), flipY: false);
			}
			else
			{
				Fill(Centered(x, y, 96f, 96f), new Color(0.3f, 0f, 0f, alpha));
			}
			Text(Centered(x, y, 100f, 100f), "X", 64, new Color(1f, 0.15f, 0.15f, alpha), (TextAnchor)4);
		}
		else if (atlasFrame != null)
		{
			DrawFrame(FnfAssets.Notes.Texture, atlasFrame, x, y, 0.7f, new Color(1f, 1f, 1f, alpha), flipY: false);
		}
		else
		{
			Fill(Centered(x, y, 96f, 96f), new Color(NoteColors[n.Lane].r, NoteColors[n.Lane].g, NoteColors[n.Lane].b, alpha));
		}
	}

	private void DrawHold(int lane, float x, float headY, float tailY, float sign, float alpha)
	{
		//IL_013d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		float num = (tailY - headY) * sign;
		if (num <= 1f)
		{
			return;
		}
		float num2 = 36.399998f;
		Texture2D holds = FnfAssets.Holds;
		if ((Object)(object)holds == (Object)null)
		{
			Color val = NoteColors[lane];
			Fill((sign > 0f) ? new Rect(x - num2 * 0.35f, headY, num2 * 0.7f, num) : new Rect(x - num2 * 0.35f, headY - num, num2 * 0.7f, num), new Color(val.r, val.g, val.b, alpha));
			return;
		}
		float num3 = 52f / (float)((Texture)holds).width;
		float num4 = 64f;
		float num5 = num4 * 0.7f;
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(num3 * (float)(lane * 2), 2f / (float)((Texture)holds).height, num3, ((float)((Texture)holds).height - 4f) / (float)((Texture)holds).height);
		float num6 = Mathf.Min(num5, num);
		float num7 = num - num6;
		float num8 = num6 / num5;
		Rect val3 = default(Rect);
		((Rect)(ref val3))..ctor(num3 * (float)(lane * 2 + 1), 1f - num4 / (float)((Texture)holds).height, num3, num4 / (float)((Texture)holds).height * num8);
		GUI.color = new Color(1f, 1f, 1f, alpha);
		if (sign > 0f)
		{
			if (num7 > 0f)
			{
				GUI.DrawTextureWithTexCoords(new Rect(x - num2 * 0.5f, headY, num2, num7), (Texture)(object)holds, val2);
			}
			GUI.DrawTextureWithTexCoords(new Rect(x - num2 * 0.5f, headY + num7, num2, num6), (Texture)(object)holds, val3);
			return;
		}
		if (num7 > 0f)
		{
			GUI.DrawTextureWithTexCoords(new Rect(x - num2 * 0.5f, headY - num7, num2, num7), (Texture)(object)holds, val2);
		}
		Rect val4 = default(Rect);
		((Rect)(ref val4))..ctor(((Rect)(ref val3)).x, ((Rect)(ref val3)).y + ((Rect)(ref val3)).height, ((Rect)(ref val3)).width, 0f - ((Rect)(ref val3)).height);
		GUI.DrawTextureWithTexCoords(new Rect(x - num2 * 0.5f, headY - num, num2, num6), (Texture)(object)holds, val4);
	}

	private void DrawHealth(float alpha)
	{
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0124: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_027a: Unknown result type (might be due to invalid IL or missing references)
		//IL_038d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		float num = DownAmount();
		float num2 = ((num > 0.5f) ? 79.2f : 640.8f);
		float num3 = (((Object)(object)FnfAssets.HealthBar != (Object)null) ? ((float)((Texture)FnfAssets.HealthBar).width) : 601f);
		float num4 = (((Object)(object)FnfAssets.HealthBar != (Object)null) ? ((float)((Texture)FnfAssets.HealthBar).height) : 19f);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(640f - num3 * 0.5f, num2 - num4 * 0.5f, num3, num4);
		Fill(new Rect(((Rect)(ref val)).x - 4f, ((Rect)(ref val)).y - 4f, ((Rect)(ref val)).width + 8f, ((Rect)(ref val)).height + 8f), new Color(0f, 0f, 0f, alpha));
		float num5 = Mathf.Clamp01(b.Health / 2f);
		float num6 = ((Rect)(ref val)).x + ((Rect)(ref val)).width * (1f - num5);
		Fill(new Rect(((Rect)(ref val)).x, ((Rect)(ref val)).y, num6 - ((Rect)(ref val)).x, ((Rect)(ref val)).height), new Color(EnemyColor.r, EnemyColor.g, EnemyColor.b, alpha));
		Fill(new Rect(num6, ((Rect)(ref val)).y, ((Rect)(ref val)).xMax - num6, ((Rect)(ref val)).height), new Color(V1Color.r, V1Color.g, V1Color.b, alpha));
		float num7 = 1f + 0.2f * iconBop * iconBop;
		int size = (int)(26f * num7);
		bool flag = num5 < 0.2f;
		bool flag2 = num5 > 0.8f;
		Text(new Rect(num6 - 330f, num2 - 30f, 316f, 60f), b.EnemyName, size, new Color(1f, flag2 ? 0.55f : 1f, flag2 ? 0.55f : 1f, alpha), (TextAnchor)5);
		Text(new Rect(num6 + 14f, num2 - 30f, 200f, 60f), "V1", size, new Color(1f, flag ? 0.55f : 1f, flag ? 0.55f : 1f, alpha), (TextAnchor)3);
		string text = ((b.Misses != 0) ? "" : ((b.Judged[1] + b.Judged[2] + b.Judged[3] == 0) ? " [SFC]" : " [FC]"));
		string s = "Score: " + b.Score.ToString("N0") + "   Misses: " + b.Misses + "   Accuracy: " + (b.Accuracy * 100f).ToString("0.00") + "%" + ((b.Accuracy