Decompiled source of TracerFXX v1.3.0

Mods/TracerFX.dll

Decompiled 16 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using BoneLib.Notifications;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.Data;
using LabFusion.Entities;
using LabFusion.Network;
using LabFusion.Network.Serialization;
using LabFusion.Player;
using LabFusion.SDK.Modules;
using LabFusion.Utilities;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using TracerFX;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "TracerFX", "1.3.0", "abbigail", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: MelonAdditionalDependencies(new string[] { "BoneLib" })]
[assembly: MelonOptionalDependencies(new string[] { "LabFusion" })]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("TracerFX")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0")]
[assembly: AssemblyProduct("TracerFX")]
[assembly: AssemblyTitle("TracerFX")]
[assembly: AssemblyVersion("1.3.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TracerFX
{
	public class Core : MelonMod
	{
		public static Instance Log;

		private static int _shotCounter;

		public override void OnInitializeMelon()
		{
			Log = ((MelonBase)this).LoggerInstance;
			Settings.Init();
			Menu.Build();
			Hooking.OnLevelLoaded += delegate
			{
				Mats.EnsureBase();
				OrangeTips.ScanScene();
			};
			Hooking.OnLevelUnloaded += delegate
			{
				TracerManager.ClearAll();
				OrangeTips.OnLevelUnloaded();
			};
			Hooking.OnGripAttached += delegate(Grip grip, Hand _)
			{
				try
				{
					if ((Object)(object)grip != (Object)null)
					{
						OrangeTips.Register(((Component)grip).GetComponentInParent<Gun>());
					}
				}
				catch
				{
				}
			};
			Log.Msg($"TracerFX loaded - airsoft tracers ready. Performance profile: {Perf.Resolved}" + (Perf.IsStandaloneDevice ? " (standalone device detected)" : ""));
		}

		public override void OnLateInitializeMelon()
		{
			FusionCompat.Init();
		}

		public override void OnUpdate()
		{
			try
			{
				TracerManager.Tick();
			}
			catch (Exception ex)
			{
				Log.Error("Tick: " + ex);
			}
			try
			{
				OrangeTips.Tick();
			}
			catch (Exception ex2)
			{
				Log.Error("OrangeTips: " + ex2);
			}
			FusionCompat.Tick();
		}

		public static bool SafeRaycast(Vector3 from, Vector3 dir, float dist, Transform ignA, Transform ignB, out RaycastHit hit)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_0092: Unknown result type (might be due to invalid IL or missing references)
			int maxRayHops = Perf.MaxRayHops;
			for (int i = 0; i < maxRayHops; i++)
			{
				if (!Physics.Raycast(from, dir, ref hit, dist, -5, (QueryTriggerInteraction)1))
				{
					return false;
				}
				Transform val = (((Object)(object)((RaycastHit)(ref hit)).collider != (Object)null) ? ((Component)((RaycastHit)(ref hit)).collider).transform : null);
				if (!((Object)(object)val != (Object)null) || ((!((Object)(object)ignA != (Object)null) || !val.IsChildOf(ignA)) && (!((Object)(object)ignB != (Object)null) || !val.IsChildOf(ignB))))
				{
					return true;
				}
				float num = ((RaycastHit)(ref hit)).distance + 0.002f;
				from += dir * num;
				dist -= num;
				if (dist <= 0f)
				{
					break;
				}
			}
			hit = default(RaycastHit);
			return false;
		}

		private static RigManager Holder(Gun gun, out int hand)
		{
			hand = -1;
			try
			{
				Grip triggerGrip = gun.triggerGrip;
				if ((Object)(object)triggerGrip != (Object)null && triggerGrip.attachedHands != null && triggerGrip.attachedHands.Count > 0)
				{
					Hand val = triggerGrip.attachedHands[0];
					if ((Object)(object)val != (Object)null && (Object)(object)val.manager != (Object)null)
					{
						PhysicsRig physicsRig = val.manager.physicsRig;
						if ((Object)(object)physicsRig != (Object)null && (Object)(object)physicsRig.leftHand != (Object)null && ((Il2CppObjectBase)physicsRig.leftHand).Pointer == ((Il2CppObjectBase)val).Pointer)
						{
							hand = 0;
						}
						else if ((Object)(object)physicsRig != (Object)null && (Object)(object)physicsRig.rightHand != (Object)null && ((Il2CppObjectBase)physicsRig.rightHand).Pointer == ((Il2CppObjectBase)val).Pointer)
						{
							hand = 1;
						}
						return val.manager;
					}
				}
				if (Player.HandsExist)
				{
					Gun componentInHand = Player.GetComponentInHand<Gun>(Player.LeftHand);
					if ((Object)(object)componentInHand != (Object)null && ((Il2CppObjectBase)componentInHand).Pointer == ((Il2CppObjectBase)gun).Pointer)
					{
						hand = 0;
						return Player.RigManager;
					}
					Gun componentInHand2 = Player.GetComponentInHand<Gun>(Player.RightHand);
					if ((Object)(object)componentInHand2 != (Object)null && ((Il2CppObjectBase)componentInHand2).Pointer == ((Il2CppObjectBase)gun).Pointer)
					{
						hand = 1;
						return Player.RigManager;
					}
				}
			}
			catch
			{
			}
			return null;
		}

		internal static Transform GunRoot(Gun gun)
		{
			if ((Object)(object)gun == (Object)null)
			{
				return null;
			}
			try
			{
				return ((Object)(object)gun.entity != (Object)null) ? ((Component)gun.entity).transform : ((Component)gun).transform.root;
			}
			catch
			{
				return ((Component)gun).transform.root;
			}
		}

		internal static void OnGunFired(Gun gun)
		{
			//IL_0166: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_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_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gun == (Object)null)
			{
				return;
			}
			OrangeTips.Register(gun);
			int hand;
			RigManager val = Holder(gun, out hand);
			RigManager rigManager = Player.RigManager;
			bool flag = (Object)(object)val != (Object)null && (Object)(object)rigManager != (Object)null && ((Il2CppObjectBase)val).Pointer == ((Il2CppObjectBase)rigManager).Pointer;
			if (((Object)(object)val != (Object)null && !flag && FusionCompat.IsRemotePlayerWithMod(val)) || !Settings.Enabled.Value || (Settings.PlayerGunsOnly.Value && !flag))
			{
				return;
			}
			_shotCounter++;
			if (_shotCounter % Mathf.Max(1, Settings.EveryNthShot.Value) != 0)
			{
				return;
			}
			Transform val2 = (((Object)(object)gun.firePointTransform != (Object)null) ? gun.firePointTransform : ((Component)gun).transform);
			int num = 1;
			float num2 = 0f;
			try
			{
				ProjectileData val3 = (((Object)(object)gun.chamberedCartridge != (Object)null) ? gun.chamberedCartridge.projectile : null);
				if ((Object)(object)val3 == (Object)null && (Object)(object)gun.defaultCartridge != (Object)null)
				{
					val3 = gun.defaultCartridge.projectile;
				}
				if ((Object)(object)val3 != (Object)null && Settings.Pellets.Value)
				{
					num = Mathf.Clamp(val3.count, 1, 12);
					num2 = ((num > 1) ? Mathf.Clamp(val3.angle, 1f, 20f) : 0f);
				}
			}
			catch
			{
			}
			TracerStyle style = TracerStyle.FromSettings();
			Color color = Settings.PickColor(flag ? hand : (-1));
			Vector3 origin = val2.position + val2.forward * 0.02f;
			FireShots(origin, val2.forward, val2.up, color, num, num2, style, GunRoot(gun), ((Object)(object)val != (Object)null) ? ((Component)val).transform : null);
			if (flag)
			{
				FusionCompat.SendShot(origin, val2.forward, val2.up, color, hand, num, num2, style);
			}
		}

		internal static void FireShots(Vector3 origin, Vector3 fwd, Vector3 up, Color color, int pellets, float coneDeg, TracerStyle style, Transform ignA, Transform ignB)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: 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_003d: 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_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: 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)
			fwd = ((Vector3)(ref fwd)).normalized;
			Vector3 val = Vector3.Cross(up, fwd);
			Vector3 normalized = ((Vector3)(ref val)).normalized;
			if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f)
			{
				val = Vector3.Cross(Vector3.up, fwd);
				normalized = ((Vector3)(ref val)).normalized;
			}
			Vector3 up2 = Vector3.Cross(fwd, normalized);
			pellets = Mathf.Clamp(pellets, 1, Perf.PelletCap);
			float deg = style.Spread + coneDeg * 0.5f;
			for (int i = 0; i < pellets; i++)
			{
				TracerManager.Fire(new ShotInfo
				{
					Origin = origin,
					Direction = Jitter(fwd, up2, normalized, deg),
					GunUp = up,
					Color = color,
					IgnoreA = ignA,
					IgnoreB = ignB,
					Style = style
				});
			}
		}

		private static Vector3 Jitter(Vector3 fwd, Vector3 up, Vector3 right, float deg)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			if (deg <= 0f)
			{
				return fwd;
			}
			Vector2 val = Random.insideUnitCircle * Mathf.Tan(deg * ((float)Math.PI / 180f));
			Vector3 val2 = fwd + up * val.y + right * val.x;
			return ((Vector3)(ref val2)).normalized;
		}

		public static void TestShot()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			Transform head = Player.Head;
			if (!((Object)(object)head == (Object)null))
			{
				TracerStyle style = TracerStyle.FromSettings();
				Color color = Settings.PickColor(1);
				Vector3 origin = head.position + head.forward * 0.4f - head.up * 0.1f;
				FireShots(ignB: ((Object)(object)Player.RigManager != (Object)null) ? ((Component)Player.RigManager).transform : null, origin: origin, fwd: head.forward, up: head.up, color: color, pellets: 1, coneDeg: 0f, style: style, ignA: null);
				FusionCompat.SendShot(origin, head.forward, head.up, color, -1, 1, 0f, style);
			}
		}
	}
	[HarmonyPatch(typeof(Gun), "Awake")]
	internal static class GunAwakePatch
	{
		private static void Postfix(Gun __instance)
		{
			try
			{
				OrangeTips.Register(__instance);
			}
			catch
			{
			}
		}
	}
	[HarmonyPatch(typeof(Gun), "OnFire")]
	internal static class GunOnFirePatch
	{
		private static void Prefix(Gun __instance)
		{
			try
			{
				Core.OnGunFired(__instance);
			}
			catch (Exception ex)
			{
				Core.Log.Error("OnFire: " + ex);
			}
		}
	}
	internal static class FusionBridge
	{
		private class PeerState
		{
			public bool TracersOn;

			public bool TipOn;

			public Color TipColor;

			public float LastSeen;
		}

		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ServerEvent <>9__6_0;

			public static ServerEvent <>9__6_1;

			public static PlayerUpdate <>9__6_2;

			internal void <Init>b__6_0()
			{
				_peers.Clear();
				_nextPresence = 0f;
			}

			internal void <Init>b__6_1()
			{
				_peers.Clear();
			}

			internal void <Init>b__6_2(PlayerID _)
			{
				_nextPresence = 0f;
			}
		}

		private static readonly Dictionary<byte, PeerState> _peers = new Dictionary<byte, PeerState>();

		private static readonly List<RemoteTipHolder> _tipHolders = new List<RemoteTipHolder>();

		private static float _nextPresence;

		private const float PresenceInterval = 4f;

		private const float PeerTimeout = 15f;

		public static void Init()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_003d: 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_0048: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			ModuleManager.RegisterModule<TracerFXModule>();
			object obj = <>c.<>9__6_0;
			if (obj == null)
			{
				ServerEvent val = delegate
				{
					_peers.Clear();
					_nextPresence = 0f;
				};
				<>c.<>9__6_0 = val;
				obj = (object)val;
			}
			MultiplayerHooking.OnJoinedServer += (ServerEvent)obj;
			object obj2 = <>c.<>9__6_1;
			if (obj2 == null)
			{
				ServerEvent val2 = delegate
				{
					_peers.Clear();
				};
				<>c.<>9__6_1 = val2;
				obj2 = (object)val2;
			}
			MultiplayerHooking.OnDisconnected += (ServerEvent)obj2;
			object obj3 = <>c.<>9__6_2;
			if (obj3 == null)
			{
				PlayerUpdate val3 = delegate
				{
					_nextPresence = 0f;
				};
				<>c.<>9__6_2 = val3;
				obj3 = (object)val3;
			}
			MultiplayerHooking.OnPlayerJoined += (PlayerUpdate)obj3;
		}

		public static bool InServer()
		{
			return NetworkInfo.HasServer;
		}

		public static int ModdedPlayerCount()
		{
			Prune();
			return _peers.Count;
		}

		public static bool IsRemotePlayerWithMod(RigManager rig)
		{
			if (!NetworkInfo.HasServer)
			{
				return false;
			}
			NetworkPlayer val = default(NetworkPlayer);
			if (!NetworkPlayerManager.TryGetPlayer(rig, ref val) || val == null || val.PlayerID == null)
			{
				return false;
			}
			if (val.PlayerID.IsMe)
			{
				return false;
			}
			if (_peers.TryGetValue(val.PlayerID.SmallID, out var value))
			{
				return Time.unscaledTime - value.LastSeen < 15f;
			}
			return false;
		}

		public static void SendShot(Vector3 o, Vector3 d, Vector3 u, Color c, int hand, int pellets, float cone, TracerStyle s)
		{
			//IL_000e: 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)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkInfo.HasServer)
			{
				MessageRelay.RelayModule<TracerShotMessage, TracerShotData>(new TracerShotData
				{
					Origin = o,
					Direction = d,
					Up = u,
					Color = c,
					Hand = (byte)((hand < 0) ? 255u : ((uint)hand)),
					Pellets = (byte)Mathf.Clamp(pellets, 1, 12),
					Cone = cone,
					Style = s
				}, CommonMessageRoutes.UnreliableToOtherClients);
			}
		}

		public static void AnnounceNow()
		{
			_nextPresence = 0f;
		}

		public static void Tick()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkInfo.HasServer && !(Time.unscaledTime < _nextPresence))
			{
				_nextPresence = Time.unscaledTime + 4f;
				MessageRelay.RelayModule<TracerPresenceMessage, TracerPresenceData>(new TracerPresenceData
				{
					TracersOn = (Settings.Enabled.Value && Settings.FusionSync.Value),
					TipOn = (Settings.OrangeTip.Value && Settings.FusionSync.Value),
					TipColor = OrangeTips.LocalTipColor
				}, CommonMessageRoutes.ReliableToOtherClients);
				Prune();
			}
		}

		private static void Prune()
		{
			List<byte> list = null;
			foreach (KeyValuePair<byte, PeerState> peer in _peers)
			{
				if (Time.unscaledTime - peer.Value.LastSeen > 15f)
				{
					(list ?? (list = new List<byte>())).Add(peer.Key);
				}
			}
			if (list == null)
			{
				return;
			}
			foreach (byte item in list)
			{
				_peers.Remove(item);
			}
		}

		private static PeerState Peer(byte id)
		{
			if (!_peers.TryGetValue(id, out var value))
			{
				value = new PeerState();
				_peers[id] = value;
			}
			value.LastSeen = Time.unscaledTime;
			return value;
		}

		internal static void OnPresence(byte sender, TracerPresenceData d)
		{
			//IL_001f: 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)
			PeerState peerState = Peer(sender);
			peerState.TracersOn = d.TracersOn;
			peerState.TipOn = d.TipOn;
			peerState.TipColor = d.TipColor;
		}

		internal static void OnShot(byte sender, TracerShotData d)
		{
			//IL_00be: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			Peer(sender).TracersOn = true;
			if (!Settings.Enabled.Value || !Settings.FusionShowOthers.Value)
			{
				return;
			}
			Transform ignA = null;
			Transform ignB = null;
			NetworkPlayer val = default(NetworkPlayer);
			if (NetworkPlayerManager.TryGetPlayer(sender, ref val) && val != null && val.HasRig && val.RigRefs != null)
			{
				RigManager rigManager = val.RigRefs.RigManager;
				if ((Object)(object)rigManager != (Object)null)
				{
					ignB = ((Component)rigManager).transform;
				}
				Hand val2 = ((d.Hand == 0) ? val.RigRefs.LeftHand : ((d.Hand == 1) ? val.RigRefs.RightHand : null));
				if ((Object)(object)val2 != (Object)null)
				{
					try
					{
						ignA = Core.GunRoot(Player.GetComponentInHand<Gun>(val2));
					}
					catch
					{
					}
				}
			}
			TracerStyle style = d.Style;
			style.Clamp();
			Core.FireShots(d.Origin, d.Direction, d.Up, d.Color, d.Pellets, Mathf.Clamp(d.Cone, 0f, 20f), style, ignA, ignB);
		}

		public static List<RemoteTipHolder> RemoteTipHolders()
		{
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			_tipHolders.Clear();
			if (!NetworkInfo.HasServer || !Settings.FusionShowOthersTips.Value)
			{
				return _tipHolders;
			}
			Prune();
			NetworkPlayer val = default(NetworkPlayer);
			foreach (KeyValuePair<byte, PeerState> peer in _peers)
			{
				if (peer.Value.TipOn && NetworkPlayerManager.TryGetPlayer(peer.Key, ref val) && val != null && val.HasRig && val.RigRefs != null)
				{
					_tipHolders.Add(new RemoteTipHolder
					{
						Left = val.RigRefs.LeftHand,
						Right = val.RigRefs.RightHand,
						Color = peer.Value.TipColor
					});
				}
			}
			return _tipHolders;
		}
	}
	public class TracerFXModule : Module
	{
		public override string Name => "TracerFX";

		public override string Author => "abbigail";

		public override Version Version => new Version(1, 3, 0);

		public override ConsoleColor Color => ConsoleColor.Green;

		protected override void OnModuleRegistered()
		{
			ModuleMessageManager.RegisterHandler<TracerShotMessage>();
			ModuleMessageManager.RegisterHandler<TracerPresenceMessage>();
		}
	}
	public class TracerShotData : INetSerializable
	{
		public Vector3 Origin;

		public Vector3 Direction;

		public Vector3 Up;

		public Color Color;

		public byte Hand;

		public byte Pellets;

		public float Cone;

		public TracerStyle Style;

		public int? GetSize()
		{
			return null;
		}

		public void Serialize(INetSerializer s)
		{
			NetSerializerUnityExtensions.SerializeValue(s, ref Origin);
			NetSerializerUnityExtensions.SerializeValue(s, ref Direction);
			NetSerializerUnityExtensions.SerializeValue(s, ref Up);
			NetSerializerUnityExtensions.SerializeValue(s, ref Color);
			s.SerializeValue(ref Hand);
			s.SerializeValue(ref Pellets);
			s.SerializeValue(ref Cone);
			s.SerializeValue(ref Style.Mode);
			s.SerializeValue(ref Style.SpeedMs);
			s.SerializeValue(ref Style.Gravity);
			s.SerializeValue(ref Style.HopUp);
			s.SerializeValue(ref Style.Drag);
			s.SerializeValue(ref Style.Spread);
			s.SerializeValue(ref Style.Bounces);
			s.SerializeValue(ref Style.Restitution);
			s.SerializeValue(ref Style.BBSize);
			s.SerializeValue(ref Style.TrailTime);
			s.SerializeValue(ref Style.TrailWidth);
			s.SerializeValue(ref Style.Intensity);
			s.SerializeValue(ref Style.LightRange);
			s.SerializeValue(ref Style.ImpactSize);
			s.SerializeValue(ref Style.GlowFade);
			s.SerializeValue(ref Style.Light);
			s.SerializeValue(ref Style.ImpactFlash);
			s.SerializeValue(ref Style.MuzzleFlash);
		}
	}
	public class TracerShotMessage : ModuleMessageHandler
	{
		protected override void OnHandleMessage(ReceivedMessage received)
		{
			byte? sender = ((ReceivedMessage)(ref received)).Sender;
			if (sender.HasValue)
			{
				TracerShotData d = ((ReceivedMessage)(ref received)).ReadData<TracerShotData>();
				FusionBridge.OnShot(sender.Value, d);
			}
		}
	}
	public class TracerPresenceData : INetSerializable
	{
		public bool TracersOn;

		public bool TipOn;

		public Color TipColor;

		public int? GetSize()
		{
			return null;
		}

		public void Serialize(INetSerializer s)
		{
			s.SerializeValue(ref TracersOn);
			s.SerializeValue(ref TipOn);
			NetSerializerUnityExtensions.SerializeValue(s, ref TipColor);
		}
	}
	public class TracerPresenceMessage : ModuleMessageHandler
	{
		protected override void OnHandleMessage(ReceivedMessage received)
		{
			byte? sender = ((ReceivedMessage)(ref received)).Sender;
			if (sender.HasValue)
			{
				TracerPresenceData d = ((ReceivedMessage)(ref received)).ReadData<TracerPresenceData>();
				FusionBridge.OnPresence(sender.Value, d);
			}
		}
	}
	public struct RemoteTipHolder
	{
		public Hand Left;

		public Hand Right;

		public Color Color;
	}
	public static class FusionCompat
	{
		private static bool _warnedSend;

		private static readonly List<RemoteTipHolder> _empty = new List<RemoteTipHolder>();

		public static bool Present { get; private set; }

		public static bool InServer
		{
			get
			{
				if (!Present)
				{
					return false;
				}
				try
				{
					return BridgeInServer();
				}
				catch
				{
					return false;
				}
			}
		}

		public static int ModdedPlayerCount
		{
			get
			{
				if (!Present)
				{
					return 0;
				}
				try
				{
					return BridgeCount();
				}
				catch
				{
					return 0;
				}
			}
		}

		public static void Init()
		{
			Present = MelonBase.RegisteredMelons.Any((MelonBase m) => m.Info != null && m.Info.Name == "LabFusion");
			if (!Present)
			{
				Core.Log.Msg("LabFusion not found - running in singleplayer mode.");
				return;
			}
			try
			{
				InitBridge();
				Core.Log.Msg("LabFusion detected - tracers and orange tips will sync to other TracerFX players.");
			}
			catch (Exception ex)
			{
				Present = false;
				Core.Log.Warning("LabFusion found but its API didn't match; Fusion sync is off. " + ex.Message);
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void InitBridge()
		{
			FusionBridge.Init();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool BridgeInServer()
		{
			return FusionBridge.InServer();
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static int BridgeCount()
		{
			return FusionBridge.ModdedPlayerCount();
		}

		public static bool IsRemotePlayerWithMod(RigManager rig)
		{
			if (!Present || (Object)(object)rig == (Object)null)
			{
				return false;
			}
			try
			{
				return BridgeIsRemote(rig);
			}
			catch
			{
				return false;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool BridgeIsRemote(RigManager rig)
		{
			return FusionBridge.IsRemotePlayerWithMod(rig);
		}

		public static void SendShot(Vector3 origin, Vector3 dir, Vector3 up, Color color, int hand, int pellets, float cone, TracerStyle style)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!Present || !Settings.FusionSync.Value)
			{
				return;
			}
			try
			{
				BridgeSend(origin, dir, up, color, hand, pellets, cone, style);
			}
			catch (Exception ex)
			{
				if (!_warnedSend)
				{
					Core.Log.Warning("Fusion shot sync failed: " + ex.Message);
					_warnedSend = true;
				}
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void BridgeSend(Vector3 o, Vector3 d, Vector3 u, Color c, int h, int p, float cone, TracerStyle s)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: 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)
			FusionBridge.SendShot(o, d, u, c, h, p, cone, s);
		}

		public static void AnnounceNow()
		{
			if (!Present)
			{
				return;
			}
			try
			{
				BridgeAnnounce();
			}
			catch
			{
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void BridgeAnnounce()
		{
			FusionBridge.AnnounceNow();
		}

		public static List<RemoteTipHolder> RemoteTipHolders()
		{
			if (!Present)
			{
				return _empty;
			}
			try
			{
				return BridgeTips();
			}
			catch
			{
				return _empty;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static List<RemoteTipHolder> BridgeTips()
		{
			return FusionBridge.RemoteTipHolders();
		}

		public static void Tick()
		{
			if (!Present)
			{
				return;
			}
			try
			{
				BridgeTick();
			}
			catch
			{
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static void BridgeTick()
		{
			FusionBridge.Tick();
		}
	}
	public static class Menu
	{
		private static Page _root;

		private static readonly Color Accent = new Color(0.2f, 1f, 0.35f);

		private static readonly Color Sub = new Color(0.75f, 0.95f, 1f);

		private static readonly Color Warn = new Color(1f, 0.45f, 0.35f);

		public static void Build()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			_root = Page.Root.CreatePage("TracerFX", Accent, 0, true);
			Populate();
		}

		private static void Rebuild()
		{
			_root.RemoveAll();
			Populate();
		}

		private static void Populate()
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: 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_00f9: 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_0149: 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_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_037e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_041f: Unknown result type (might be due to invalid IL or missing references)
			//IL_045e: Unknown result type (might be due to invalid IL or missing references)
			//IL_049d: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_052e: Unknown result type (might be due to invalid IL or missing references)
			//IL_056d: Unknown result type (might be due to invalid IL or missing references)
			//IL_057f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0611: Unknown result type (might be due to invalid IL or missing references)
			//IL_065a: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_0729: Unknown result type (might be due to invalid IL or missing references)
			//IL_0772: Unknown result type (might be due to invalid IL or missing references)
			//IL_07bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0804: Unknown result type (might be due to invalid IL or missing references)
			//IL_0834: Unknown result type (might be due to invalid IL or missing references)
			//IL_0864: Unknown result type (might be due to invalid IL or missing references)
			//IL_0893: Unknown result type (might be due to invalid IL or missing references)
			//IL_08d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0931: Unknown result type (might be due to invalid IL or missing references)
			//IL_097a: Unknown result type (might be due to invalid IL or missing references)
			//IL_09c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_09fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a37: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a70: Unknown result type (might be due to invalid IL or missing references)
			//IL_0acc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ade: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b18: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b60: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bbf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0bf9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c33: Unknown result type (might be due to invalid IL or missing references)
			//IL_0c6c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0caf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0cc1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d00: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d30: Unknown result type (might be due to invalid IL or missing references)
			//IL_0d6a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0da8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0de2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e25: Unknown result type (might be due to invalid IL or missing references)
			//IL_0e6e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ea7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0edb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0f0f: Unknown result type (might be due to invalid IL or missing references)
			_root.CreateBool("Tracers Enabled", Accent, Settings.Enabled.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.Enabled, v);
				if (!v)
				{
					TracerManager.ClearAll();
				}
				FusionCompat.AnnounceNow();
				Notify(v ? "Tracers ON" : "Tracers OFF", (NotificationType)((!v) ? 1 : 3));
			});
			_root.CreateEnum("Mode", Sub, (Enum)Settings.CurrentMode, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.Mode, (int)(TracerMode)(object)v);
			});
			_root.CreateEnum("Color", Sub, (Enum)(TracerColor)Settings.Preset.Value, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.Preset, (int)(TracerColor)(object)v);
				OrangeTips.ApplyColor();
				if (Settings.CurrentColorMode != ColorMode.Preset && Settings.CurrentColorMode != ColorMode.PerHand)
				{
					Set(Settings.ColorModeE, 0);
				}
			});
			_root.CreateFunction("Test Shot", Color.white, (Action)Core.TestShot);
			_root.CreateBool("Orange Tip", OrangeTips.BlazeOrange, Settings.OrangeTip.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.OrangeTip, v);
				OrangeTips.Refresh();
				Notify(v ? "Orange tips ON" : "Orange tips OFF", (NotificationType)((!v) ? 1 : 3));
			});
			Page obj = _root.CreatePage("Orange Tip", OrangeTips.BlazeOrange, 0, true);
			obj.CreateBool("Orange Tip", OrangeTips.BlazeOrange, Settings.OrangeTip.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.OrangeTip, v);
				OrangeTips.Refresh();
			});
			obj.CreateFloat("Tip Diameter (cm)", Sub, Settings.TipDiameterCm.Value, 0.25f, 0.5f, 10f, (Action<float>)delegate(float v)
			{
				Set(Settings.TipDiameterCm, v);
				OrangeTips.Refresh();
			});
			obj.CreateFloat("Tip Length (cm)", Sub, Settings.TipLengthCm.Value, 0.25f, 0.25f, 10f, (Action<float>)delegate(float v)
			{
				Set(Settings.TipLengthCm, v);
				OrangeTips.Refresh();
			});
			obj.CreateFloat("Tip Offset (cm)", Sub, Settings.TipOffsetCm.Value, 0.25f, -10f, 10f, (Action<float>)delegate(float v)
			{
				Set(Settings.TipOffsetCm, v);
				OrangeTips.Refresh();
			});
			obj.CreateBool("Match Tracer Color", Sub, Settings.TipMatchTracer.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.TipMatchTracer, v);
				OrangeTips.Refresh();
			});
			Page obj2 = _root.CreatePage("Color", new Color(1f, 0.8f, 0.2f), 0, true);
			obj2.CreateEnum("Color Mode", Sub, (Enum)Settings.CurrentColorMode, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.ColorModeE, (int)(ColorMode)(object)v);
			});
			obj2.CreateEnum("Preset", Sub, (Enum)(TracerColor)Settings.Preset.Value, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.Preset, (int)(TracerColor)(object)v);
				OrangeTips.ApplyColor();
			});
			obj2.CreateFloat("Custom Red", Color.red, Settings.CustomR.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Set(Settings.CustomR, v);
			});
			obj2.CreateFloat("Custom Green", Color.green, Settings.CustomG.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Set(Settings.CustomG, v);
			});
			obj2.CreateFloat("Custom Blue", new Color(0.3f, 0.5f, 1f), Settings.CustomB.Value, 0.05f, 0f, 1f, (Action<float>)delegate(float v)
			{
				Set(Settings.CustomB, v);
			});
			obj2.CreateEnum("Left Hand Color", Sub, (Enum)(TracerColor)Settings.LeftPreset.Value, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.LeftPreset, (int)(TracerColor)(object)v);
			});
			obj2.CreateEnum("Right Hand Color", Sub, (Enum)(TracerColor)Settings.RightPreset.Value, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.RightPreset, (int)(TracerColor)(object)v);
			});
			obj2.CreateFloat("Rainbow Speed", Sub, Settings.RainbowSpeed.Value, 0.1f, 0.1f, 5f, (Action<float>)delegate(float v)
			{
				Set(Settings.RainbowSpeed, v);
			});
			obj2.CreateFloat("Glow Intensity", Sub, Settings.Intensity.Value, 0.25f, 0.25f, 10f, (Action<float>)delegate(float v)
			{
				Set(Settings.Intensity, v);
			});
			obj2.CreateFunction("Test Shot", Color.white, (Action)Core.TestShot);
			Page obj3 = _root.CreatePage("Ballistics", new Color(0.4f, 0.8f, 1f), 0, true);
			obj3.CreateFloat("BB Speed (FPS)", Sub, Settings.SpeedFps.Value, 25f, 100f, 700f, (Action<float>)delegate(float v)
			{
				Set(Settings.SpeedFps, v);
			});
			obj3.CreateFloat("Gravity", Sub, Settings.GravityScale.Value, 0.1f, 0f, 3f, (Action<float>)delegate(float v)
			{
				Set(Settings.GravityScale, v);
			});
			obj3.CreateFloat("Hop-Up", Sub, Settings.HopUp.Value, 0.1f, 0f, 2f, (Action<float>)delegate(float v)
			{
				Set(Settings.HopUp, v);
			});
			obj3.CreateFloat("Air Drag", Sub, Settings.Drag.Value, 0.1f, 0f, 3f, (Action<float>)delegate(float v)
			{
				Set(Settings.Drag, v);
			});
			obj3.CreateFloat("Spread (deg)", Sub, Settings.SpreadDeg.Value, 0.1f, 0f, 5f, (Action<float>)delegate(float v)
			{
				Set(Settings.SpreadDeg, v);
			});
			obj3.CreateInt("Ricochets", Sub, Settings.Bounces.Value, 1, 0, 5, (Action<int>)delegate(int v)
			{
				Set(Settings.Bounces, v);
			});
			obj3.CreateFloat("Bounciness", Sub, Settings.Restitution.Value, 0.05f, 0.05f, 0.9f, (Action<float>)delegate(float v)
			{
				Set(Settings.Restitution, v);
			});
			obj3.CreateFloat("Tracer Time Scale", Sub, Settings.TracerTimeScale.Value, 0.05f, 0.05f, 1f, (Action<float>)delegate(float v)
			{
				Set(Settings.TracerTimeScale, v);
			});
			obj3.CreateFloat("Bullet Mode Speed", Sub, Settings.BulletSpeed.Value, 25f, 50f, 1000f, (Action<float>)delegate(float v)
			{
				Set(Settings.BulletSpeed, v);
			});
			obj3.CreateFunction("Preset: Stock AEG", Color.white, (Action)delegate
			{
				ApplyBallistics(330f, 1f, 1f, 1f, 0.6f, "Stock AEG");
			});
			obj3.CreateFunction("Preset: Sniper", Color.white, (Action)delegate
			{
				ApplyBallistics(500f, 1f, 1.1f, 0.7f, 0.1f, "Sniper");
			});
			obj3.CreateFunction("Preset: Pistol", Color.white, (Action)delegate
			{
				ApplyBallistics(280f, 1f, 0.8f, 1.2f, 1f, "Pistol");
			});
			obj3.CreateFunction("Preset: Moon Gravity", Color.white, (Action)delegate
			{
				ApplyBallistics(350f, 0.17f, 0.15f, 0.3f, 0.6f, "Moon Gravity");
			});
			Page obj4 = _root.CreatePage("Visuals", new Color(0.9f, 0.5f, 1f), 0, true);
			obj4.CreateFloat("BB Size", Sub, Settings.BBSize.Value, 0.25f, 0.5f, 10f, (Action<float>)delegate(float v)
			{
				Set(Settings.BBSize, v);
			});
			obj4.CreateFloat("Trail Length (s)", Sub, Settings.TrailTime.Value, 0.05f, 0.02f, 2f, (Action<float>)delegate(float v)
			{
				Set(Settings.TrailTime, v);
			});
			obj4.CreateFloat("Trail Width", Sub, Settings.TrailWidth.Value, 0.1f, 0.1f, 5f, (Action<float>)delegate(float v)
			{
				Set(Settings.TrailWidth, v);
			});
			obj4.CreateBool("Glow-in-the-Dark Fade", Sub, Settings.GlowFade.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.GlowFade, v);
			});
			obj4.CreateBool("Tracer Unit Flash", Sub, Settings.MuzzleFlash.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.MuzzleFlash, v);
			});
			obj4.CreateBool("BB Casts Light", Sub, Settings.GlowLight.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.GlowLight, v);
			});
			obj4.CreateFloat("BB Light Range", Sub, Settings.LightRange.Value, 0.25f, 0.25f, 6f, (Action<float>)delegate(float v)
			{
				Set(Settings.LightRange, v);
			});
			Page obj5 = _root.CreatePage("Impacts", new Color(1f, 0.6f, 0.3f), 0, true);
			obj5.CreateBool("Impact Flash", Sub, Settings.ImpactFlash.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.ImpactFlash, v);
			});
			obj5.CreateFloat("Impact Size", Sub, Settings.ImpactSize.Value, 0.1f, 0.1f, 5f, (Action<float>)delegate(float v)
			{
				Set(Settings.ImpactSize, v);
			});
			obj5.CreateBool("Impact Light", Sub, Settings.ImpactLight.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.ImpactLight, v);
			});
			Page obj6 = _root.CreatePage("Fusion", new Color(0.55f, 0.6f, 1f), 0, true);
			obj6.CreateBool("Share My Tracers & Tip", Sub, Settings.FusionSync.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.FusionSync, v);
				FusionCompat.AnnounceNow();
			});
			obj6.CreateBool("Show Others' Tracers", Sub, Settings.FusionShowOthers.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.FusionShowOthers, v);
			});
			obj6.CreateBool("Show Others' Orange Tips", Sub, Settings.FusionShowOthersTips.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.FusionShowOthersTips, v);
				OrangeTips.Refresh();
			});
			obj6.CreateFunction("Fusion Status", Color.white, (Action)delegate
			{
				Notify((!FusionCompat.Present) ? "LabFusion is not installed" : ((!FusionCompat.InServer) ? "Not in a Fusion lobby" : $"{FusionCompat.ModdedPlayerCount} other player(s) running TracerFX"), (NotificationType)0, force: true);
			});
			Page obj7 = _root.CreatePage("Filters & Performance", new Color(0.7f, 0.7f, 0.7f), 0, true);
			obj7.CreateEnum("Performance Profile", Accent, (Enum)(PerfProfile)Settings.Profile.Value, (Action<Enum>)delegate(Enum v)
			{
				Set(Settings.Profile, (int)(PerfProfile)(object)v);
				TracerManager.ClearAll();
				Notify($"Profile: {Perf.Resolved}", (NotificationType)0);
			});
			obj7.CreateFunction("Show Active Profile", Color.white, (Action)delegate
			{
				Notify($"{Perf.Resolved}{(Perf.IsStandaloneDevice ? " (standalone)" : " (PC)")} - max {Perf.MaxTracers} tracers, lights {(Perf.AllowLights ? "on" : "off")}", (NotificationType)0, force: true);
			});
			obj7.CreateBool("Player Guns Only", Sub, Settings.PlayerGunsOnly.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.PlayerGunsOnly, v);
			});
			obj7.CreateInt("Tracer Every Nth Shot", Sub, Settings.EveryNthShot.Value, 1, 1, 10, (Action<int>)delegate(int v)
			{
				Set(Settings.EveryNthShot, v);
			});
			obj7.CreateBool("Shotgun Pellet Tracers", Sub, Settings.Pellets.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.Pellets, v);
			});
			obj7.CreateInt("Max Tracers", Sub, Settings.MaxTracers.Value, 25, 25, 500, (Action<int>)delegate(int v)
			{
				Set(Settings.MaxTracers, v);
			});
			obj7.CreateFloat("Max Lifetime (s)", Sub, Settings.MaxLifetime.Value, 0.5f, 0.5f, 15f, (Action<float>)delegate(float v)
			{
				Set(Settings.MaxLifetime, v);
			});
			obj7.CreateBool("Notifications", Sub, Settings.Notifications.Value, (Action<bool>)delegate(bool v)
			{
				Set(Settings.Notifications, v);
			});
			obj7.CreateFunction("Show Active Count", Color.white, (Action)delegate
			{
				Notify($"{TracerManager.ActiveCount} tracers in flight", (NotificationType)0, force: true);
			});
			_root.CreateFunction("Clear All Tracers", Warn, (Action)delegate
			{
				TracerManager.ClearAll();
				Notify("Tracers cleared", (NotificationType)0);
			});
			_root.CreateFunction("Reset To Defaults", Warn, (Action)delegate
			{
				Menu_ResetDialog();
			});
		}

		private static void Menu_ResetDialog()
		{
			try
			{
				Menu.DisplayDialog("Reset TracerFX?", "All tracer settings will go back to default.", (Texture2D)null, (Action)delegate
				{
					Settings.ResetAll();
					TracerManager.ClearAll();
					OrangeTips.Refresh();
					Rebuild();
					Menu.OpenPage(_root);
					Notify("Settings reset", (NotificationType)3);
				}, (Action)null);
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Dialog failed, resetting directly: " + ex.Message);
				Settings.ResetAll();
				OrangeTips.Refresh();
				Rebuild();
			}
		}

		private static void ApplyBallistics(float fps, float grav, float hop, float drag, float spread, string name)
		{
			Settings.SpeedFps.Value = fps;
			Settings.GravityScale.Value = grav;
			Settings.HopUp.Value = hop;
			Settings.Drag.Value = drag;
			Settings.SpreadDeg.Value = spread;
			Settings.Save();
			Rebuild();
			Notify("Ballistics: " + name, (NotificationType)3);
		}

		private static void Set<T>(MelonPreferences_Entry<T> entry, T value)
		{
			entry.Value = value;
			Settings.Save();
		}

		private static void Notify(string msg, NotificationType type, bool force = false)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: 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)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			if (!force && !Settings.Notifications.Value)
			{
				return;
			}
			try
			{
				Notifier.Send(new Notification
				{
					Title = NotificationText.op_Implicit("TracerFX"),
					Message = NotificationText.op_Implicit(msg),
					ShowTitleOnPopup = true,
					PopupLength = 1.5f,
					Type = type
				});
			}
			catch
			{
			}
		}
	}
	public static class OrangeTips
	{
		private class Tip
		{
			public GameObject Go;

			public MeshRenderer R;
		}

		private const string TipName = "TracerFX_OrangeTip";

		public static readonly Color BlazeOrange = new Color(1f, 0.36f, 0.02f);

		private static readonly Dictionary<IntPtr, Tip> _tips = new Dictionary<IntPtr, Tip>();

		private static readonly Dictionary<IntPtr, Gun> _known = new Dictionary<IntPtr, Gun>();

		private static bool _layoutDirty = true;

		private static readonly Dictionary<IntPtr, Color> _remote = new Dictionary<IntPtr, Color>();

		private static readonly HashSet<IntPtr> _failed = new HashSet<IntPtr>();

		private static readonly List<IntPtr> _dead = new List<IntPtr>();

		private static readonly Dictionary<int, Material> _mats = new Dictionary<int, Material>();

		private static Material _template;

		private static float _nextScan;

		public static Color LocalTipColor
		{
			get
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				if (!Settings.TipMatchTracer.Value)
				{
					return BlazeOrange;
				}
				return Settings.PresetToColor((TracerColor)Settings.Preset.Value);
			}
		}

		public static void Register(Gun gun)
		{
			if (!((Object)(object)gun == (Object)null))
			{
				_known[((Il2CppObjectBase)gun).Pointer] = gun;
			}
		}

		public static void ScanScene()
		{
			try
			{
				foreach (Gun item in Object.FindObjectsOfType<Gun>())
				{
					Register(item);
				}
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Gun scan failed: " + ex.Message);
			}
			_nextScan = 0f;
		}

		public static void OnLevelUnloaded()
		{
			_known.Clear();
			_tips.Clear();
			_failed.Clear();
		}

		public static void Tick()
		{
			//IL_0176: 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)
			if (Time.unscaledTime < _nextScan)
			{
				return;
			}
			_nextScan = Time.unscaledTime + 1f;
			_dead.Clear();
			foreach (KeyValuePair<IntPtr, Tip> tip in _tips)
			{
				if ((Object)(object)tip.Value.Go == (Object)null)
				{
					_dead.Add(tip.Key);
				}
			}
			foreach (IntPtr item in _dead)
			{
				_tips.Remove(item);
			}
			_dead.Clear();
			foreach (KeyValuePair<IntPtr, Gun> item2 in _known)
			{
				if ((Object)(object)item2.Value == (Object)null)
				{
					_dead.Add(item2.Key);
				}
			}
			foreach (IntPtr item3 in _dead)
			{
				_known.Remove(item3);
			}
			_remote.Clear();
			foreach (RemoteTipHolder item4 in FusionCompat.RemoteTipHolders())
			{
				AddRemote(item4.Left, item4.Color);
				AddRemote(item4.Right, item4.Color);
			}
			bool value = Settings.OrangeTip.Value;
			if (value)
			{
				foreach (Gun value2 in _known.Values)
				{
					Ensure(value2);
				}
			}
			foreach (KeyValuePair<IntPtr, Tip> tip2 in _tips)
			{
				Apply(tip2.Key, tip2.Value, value);
			}
			_layoutDirty = false;
		}

		private static void AddRemote(Hand hand, Color c)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)hand == (Object)null))
			{
				Gun val = null;
				try
				{
					val = Player.GetComponentInHand<Gun>(hand);
				}
				catch
				{
				}
				if (!((Object)(object)val == (Object)null))
				{
					_remote[((Il2CppObjectBase)val).Pointer] = c;
					Ensure(val);
				}
			}
		}

		private static void Ensure(Gun gun)
		{
			if ((Object)(object)gun == (Object)null || _tips.ContainsKey(((Il2CppObjectBase)gun).Pointer) || _failed.Contains(((Il2CppObjectBase)gun).Pointer))
			{
				return;
			}
			try
			{
				_tips[((Il2CppObjectBase)gun).Pointer] = Attach(gun);
			}
			catch (Exception ex)
			{
				Core.Log.Warning("Orange tip attach failed: " + ex.Message);
				_failed.Add(((Il2CppObjectBase)gun).Pointer);
			}
		}

		private static void Apply(IntPtr gun, Tip tip, bool localOn)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)tip.Go == (Object)null)
			{
				return;
			}
			Color value;
			bool flag = _remote.TryGetValue(gun, out value);
			bool flag2 = flag || localOn;
			if (flag2)
			{
				if (_layoutDirty || !tip.Go.activeSelf)
				{
					Layout(tip.Go);
				}
				Material val = MaterialFor(flag ? value : LocalTipColor);
				if ((Object)(object)val != (Object)null && (Object)(object)((Renderer)tip.R).sharedMaterial != (Object)(object)val)
				{
					((Renderer)tip.R).sharedMaterial = val;
				}
			}
			if (tip.Go.activeSelf != flag2)
			{
				tip.Go.SetActive(flag2);
			}
		}

		private static Tip Attach(Gun gun)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			Transform val = (((Object)(object)gun.firePointTransform != (Object)null) ? gun.firePointTransform : ((Component)gun).transform);
			EnsureTemplate(gun);
			Transform val2 = val.Find("TracerFX_OrangeTip");
			GameObject val3;
			if ((Object)(object)val2 != (Object)null)
			{
				val3 = ((Component)val2).gameObject;
			}
			else
			{
				val3 = new GameObject("TracerFX_OrangeTip");
				val3.transform.SetParent(val, false);
				val3.AddComponent<MeshFilter>().sharedMesh = LowPoly.Cylinder;
				val3.AddComponent<MeshRenderer>();
			}
			MeshRenderer component = val3.GetComponent<MeshRenderer>();
			((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)component).receiveShadows = !Perf.IsStandaloneDevice;
			((Renderer)component).reflectionProbeUsage = (ReflectionProbeUsage)0;
			Layout(val3);
			val3.SetActive(false);
			return new Tip
			{
				Go = val3,
				R = component
			};
		}

		private static void Layout(GameObject tip)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = tip.transform;
			Transform parent = transform.parent;
			float num = Settings.TipDiameterCm.Value * 0.01f;
			float num2 = Settings.TipLengthCm.Value * 0.01f;
			float num3 = Settings.TipOffsetCm.Value * 0.01f;
			Vector3 val = (((Object)(object)parent != (Object)null) ? parent.lossyScale : Vector3.one);
			float num4 = ((Mathf.Abs(val.x) > 0.0001f) ? Mathf.Abs(val.x) : 1f);
			float num5 = ((Mathf.Abs(val.y) > 0.0001f) ? Mathf.Abs(val.y) : 1f);
			float num6 = ((Mathf.Abs(val.z) > 0.0001f) ? Mathf.Abs(val.z) : 1f);
			transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			transform.localScale = new Vector3(num / num4, num2 * 0.5f / num6, num / num5);
			transform.localPosition = new Vector3(0f, 0f, (num3 - num2 * 0.5f) / num6);
		}

		private static void EnsureTemplate(Gun gun)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Expected O, but got Unknown
			if ((Object)(object)_template != (Object)null)
			{
				return;
			}
			string[] array = new string[4] { "Universal Render Pipeline/Lit", "Universal Render Pipeline/Simple Lit", "SLZ/SLZ Standard", "Universal Render Pipeline/Unlit" };
			for (int i = 0; i < array.Length; i++)
			{
				Shader val = Shader.Find(array[i]);
				if ((Object)(object)val != (Object)null)
				{
					_template = new Material(val);
					break;
				}
			}
			if ((Object)(object)_template == (Object)null)
			{
				MeshRenderer componentInChildren = ((Component)gun).GetComponentInChildren<MeshRenderer>();
				if ((Object)(object)componentInChildren != (Object)null && (Object)(object)((Renderer)componentInChildren).sharedMaterial != (Object)null)
				{
					_template = new Material(((Renderer)componentInChildren).sharedMaterial);
					array = new string[8] { "_BaseMap", "_MainTex", "_BumpMap", "_MetallicGlossMap", "_OcclusionMap", "_EmissionMap", "_DetailAlbedoMap", "_DetailNormalMap" };
					foreach (string text in array)
					{
						if (_template.HasProperty(text))
						{
							_template.SetTexture(text, (Texture)null);
						}
					}
				}
			}
			if ((Object)(object)_template == (Object)null && Mats.EnsureBase())
			{
				_template = Mats.New();
			}
			if (!((Object)(object)_template == (Object)null))
			{
				((Object)_template).hideFlags = (HideFlags)32;
				if (_template.HasProperty("_Metallic"))
				{
					_template.SetFloat("_Metallic", 0f);
				}
				if (_template.HasProperty("_Smoothness"))
				{
					_template.SetFloat("_Smoothness", 0.35f);
				}
				if (_template.HasProperty("_Glossiness"))
				{
					_template.SetFloat("_Glossiness", 0.35f);
				}
				Core.Log.Msg("Orange tip shader: " + ((Object)_template.shader).name);
			}
		}

		private static Material MaterialFor(Color c)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: 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)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Expected O, but got Unknown
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_template == (Object)null)
			{
				return null;
			}
			Color32 val = Color32.op_Implicit(c);
			int key = (val.r << 16) | (val.g << 8) | val.b;
			if (_mats.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			value = new Material(_template)
			{
				hideFlags = (HideFlags)32
			};
			value.color = c;
			if (value.HasProperty("_BaseColor"))
			{
				value.SetColor("_BaseColor", c);
			}
			if (value.HasProperty("_EmissionColor"))
			{
				value.SetColor("_EmissionColor", Color.black);
			}
			_mats[key] = value;
			return value;
		}

		public static void Refresh()
		{
			_nextScan = 0f;
			_layoutDirty = true;
			bool value = Settings.OrangeTip.Value;
			foreach (KeyValuePair<IntPtr, Tip> tip in _tips)
			{
				Apply(tip.Key, tip.Value, value);
			}
			_layoutDirty = false;
			FusionCompat.AnnounceNow();
		}

		public static void ApplyColor()
		{
			Refresh();
		}
	}
	public enum PerfProfile
	{
		Auto,
		High,
		Standalone,
		Low
	}
	public static class Perf
	{
		public static bool IsStandaloneDevice
		{
			get
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				if ((int)Application.platform != 11)
				{
					return Application.isMobilePlatform;
				}
				return true;
			}
		}

		public static PerfProfile Resolved
		{
			get
			{
				PerfProfile perfProfile = (PerfProfile)Mathf.Clamp(Settings.Profile.Value, 0, 3);
				if (perfProfile == PerfProfile.Auto)
				{
					perfProfile = ((!IsStandaloneDevice) ? PerfProfile.High : PerfProfile.Standalone);
				}
				return perfProfile;
			}
		}

		private static bool High => Resolved == PerfProfile.High;

		private static bool Low => Resolved == PerfProfile.Low;

		public static int MaxTracers => Mathf.Min(Settings.MaxTracers.Value, High ? 500 : (Low ? 24 : 60));

		public static int PoolCap
		{
			get
			{
				if (!High)
				{
					if (!Low)
					{
						return 32;
					}
					return 12;
				}
				return 128;
			}
		}

		public static bool AllowLights => High;

		public static int MaxSubsteps
		{
			get
			{
				if (!High)
				{
					if (!Low)
					{
						return 3;
					}
					return 2;
				}
				return 8;
			}
		}

		public static float StepLength
		{
			get
			{
				if (!High)
				{
					if (!Low)
					{
						return 1.25f;
					}
					return 2f;
				}
				return 0.5f;
			}
		}

		public static int MaxRayHops
		{
			get
			{
				if (!High)
				{
					return 3;
				}
				return 6;
			}
		}

		public static int PelletCap
		{
			get
			{
				if (!High)
				{
					if (!Low)
					{
						return 4;
					}
					return 2;
				}
				return 12;
			}
		}

		public static float TrailMinVertexDistance
		{
			get
			{
				if (!High)
				{
					if (!Low)
					{
						return 0.06f;
					}
					return 0.12f;
				}
				return 0.02f;
			}
		}

		public static int TrailCapVertices
		{
			get
			{
				if (!High)
				{
					return 0;
				}
				return 2;
			}
		}

		public static float MaxTrailTime
		{
			get
			{
				if (!High)
				{
					if (!Low)
					{
						return 0.4f;
					}
					return 0.2f;
				}
				return 2f;
			}
		}

		public static float GlowInterval
		{
			get
			{
				if (!High)
				{
					return 0.1f;
				}
				return 0f;
			}
		}

		public static bool AllowMuzzleFlash => !Low;

		public static float LaserRange
		{
			get
			{
				if (!High)
				{
					return 120f;
				}
				return 300f;
			}
		}
	}
	public enum TracerMode
	{
		Airsoft,
		Bullet,
		Laser
	}
	public enum ColorMode
	{
		Preset,
		Custom,
		Rainbow,
		RandomPerShot,
		PerHand
	}
	public enum TracerColor
	{
		Green,
		Red,
		Orange,
		Yellow,
		Lime,
		Cyan,
		Blue,
		Purple,
		Pink,
		White
	}
	public static class Settings
	{
		private static MelonPreferences_Category _cat;

		private static readonly List<MelonPreferences_Entry> _all = new List<MelonPreferences_Entry>();

		public static MelonPreferences_Entry<bool> Enabled;

		public static MelonPreferences_Entry<int> Mode;

		public static MelonPreferences_Entry<bool> PlayerGunsOnly;

		public static MelonPreferences_Entry<int> EveryNthShot;

		public static MelonPreferences_Entry<bool> Pellets;

		public static MelonPreferences_Entry<bool> Notifications;

		public static MelonPreferences_Entry<int> ColorModeE;

		public static MelonPreferences_Entry<int> Preset;

		public static MelonPreferences_Entry<int> LeftPreset;

		public static MelonPreferences_Entry<int> RightPreset;

		public static MelonPreferences_Entry<float> CustomR;

		public static MelonPreferences_Entry<float> CustomG;

		public static MelonPreferences_Entry<float> CustomB;

		public static MelonPreferences_Entry<float> RainbowSpeed;

		public static MelonPreferences_Entry<float> Intensity;

		public static MelonPreferences_Entry<float> SpeedFps;

		public static MelonPreferences_Entry<float> GravityScale;

		public static MelonPreferences_Entry<float> HopUp;

		public static MelonPreferences_Entry<float> Drag;

		public static MelonPreferences_Entry<float> SpreadDeg;

		public static MelonPreferences_Entry<int> Bounces;

		public static MelonPreferences_Entry<float> Restitution;

		public static MelonPreferences_Entry<float> TracerTimeScale;

		public static MelonPreferences_Entry<float> BulletSpeed;

		public static MelonPreferences_Entry<float> BBSize;

		public static MelonPreferences_Entry<float> TrailTime;

		public static MelonPreferences_Entry<float> TrailWidth;

		public static MelonPreferences_Entry<bool> GlowFade;

		public static MelonPreferences_Entry<bool> GlowLight;

		public static MelonPreferences_Entry<float> LightRange;

		public static MelonPreferences_Entry<bool> MuzzleFlash;

		public static MelonPreferences_Entry<bool> ImpactFlash;

		public static MelonPreferences_Entry<float> ImpactSize;

		public static MelonPreferences_Entry<bool> ImpactLight;

		public static MelonPreferences_Entry<bool> OrangeTip;

		public static MelonPreferences_Entry<float> TipDiameterCm;

		public static MelonPreferences_Entry<float> TipLengthCm;

		public static MelonPreferences_Entry<float> TipOffsetCm;

		public static MelonPreferences_Entry<bool> TipMatchTracer;

		public static MelonPreferences_Entry<bool> FusionSync;

		public static MelonPreferences_Entry<bool> FusionShowOthers;

		public static MelonPreferences_Entry<bool> FusionShowOthersTips;

		public static MelonPreferences_Entry<int> Profile;

		public static MelonPreferences_Entry<int> MaxTracers;

		public static MelonPreferences_Entry<float> MaxLifetime;

		private static int _shotIndex;

		public static TracerMode CurrentMode => (TracerMode)Mathf.Clamp(Mode.Value, 0, 2);

		public static ColorMode CurrentColorMode => (ColorMode)Mathf.Clamp(ColorModeE.Value, 0, 4);

		public static void Init()
		{
			_cat = MelonPreferences.CreateCategory("TracerFX", "TracerFX - Airsoft Tracers");
			Enabled = E("Enabled", def: true);
			Mode = E("Mode", 0);
			PlayerGunsOnly = E("PlayerGunsOnly", def: false);
			EveryNthShot = E("EveryNthShot", 1);
			Pellets = E("ShotgunPellets", def: true);
			Notifications = E("Notifications", def: true);
			ColorModeE = E("ColorMode", 0);
			Preset = E("Preset", 0);
			LeftPreset = E("LeftHandPreset", 1);
			RightPreset = E("RightHandPreset", 0);
			CustomR = E("CustomR", 0.2f);
			CustomG = E("CustomG", 1f);
			CustomB = E("CustomB", 0.3f);
			RainbowSpeed = E("RainbowSpeed", 0.5f);
			Intensity = E("Intensity", 2.5f);
			SpeedFps = E("SpeedFPS", 350f);
			GravityScale = E("GravityScale", 1f);
			HopUp = E("HopUp", 1f);
			Drag = E("Drag", 1f);
			SpreadDeg = E("SpreadDegrees", 0.6f);
			Bounces = E("Bounces", 1);
			Restitution = E("Restitution", 0.35f);
			TracerTimeScale = E("TracerTimeScale", 1f);
			BulletSpeed = E("BulletModeSpeed", 250f);
			BBSize = E("BBSizeMultiplier", 2f);
			TrailTime = E("TrailTime", 0.25f);
			TrailWidth = E("TrailWidthMultiplier", 1f);
			GlowFade = E("GlowInTheDarkFade", def: true);
			GlowLight = E("BBLight", def: false);
			LightRange = E("BBLightRange", 1.5f);
			MuzzleFlash = E("TracerUnitFlash", def: true);
			ImpactFlash = E("ImpactFlash", def: true);
			ImpactSize = E("ImpactSize", 1f);
			ImpactLight = E("ImpactLight", def: false);
			OrangeTip = E("OrangeTip", def: false);
			TipDiameterCm = E("TipDiameterCm", 2.5f);
			TipLengthCm = E("TipLengthCm", 2f);
			TipOffsetCm = E("TipOffsetCm", 0f);
			TipMatchTracer = E("TipMatchTracerColor", def: false);
			FusionSync = E("FusionShareMyTracers", def: true);
			FusionShowOthers = E("FusionShowOthersTracers", def: true);
			FusionShowOthersTips = E("FusionShowOthersTips", def: true);
			Profile = E("PerformanceProfile", 0);
			MaxTracers = E("MaxTracers", 200);
			MaxLifetime = E("MaxLifetime", 4f);
		}

		private static MelonPreferences_Entry<T> E<T>(string id, T def)
		{
			MelonPreferences_Entry<T> val = _cat.CreateEntry<T>(id, def, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
			_all.Add((MelonPreferences_Entry)(object)val);
			return val;
		}

		public static void Save()
		{
			_cat.SaveToFile(false);
		}

		public static void ResetAll()
		{
			foreach (MelonPreferences_Entry item in _all)
			{
				item.ResetToDefault();
			}
			Save();
		}

		public static Color PresetToColor(TracerColor c)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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_00ba: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(c switch
			{
				TracerColor.Green => new Color(0.1f, 1f, 0.2f), 
				TracerColor.Red => new Color(1f, 0.08f, 0.05f), 
				TracerColor.Orange => new Color(1f, 0.45f, 0.05f), 
				TracerColor.Yellow => new Color(1f, 0.92f, 0.1f), 
				TracerColor.Lime => new Color(0.6f, 1f, 0.05f), 
				TracerColor.Cyan => new Color(0.05f, 0.95f, 1f), 
				TracerColor.Blue => new Color(0.1f, 0.3f, 1f), 
				TracerColor.Purple => new Color(0.6f, 0.15f, 1f), 
				TracerColor.Pink => new Color(1f, 0.25f, 0.75f), 
				_ => Color.white, 
			});
		}

		public static Color PickColor(int hand)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			_shotIndex++;
			return (Color)(CurrentColorMode switch
			{
				ColorMode.Custom => new Color(CustomR.Value, CustomG.Value, CustomB.Value), 
				ColorMode.Rainbow => Color.HSVToRGB((Time.unscaledTime * RainbowSpeed.Value + (float)_shotIndex * 0.03f) % 1f, 1f, 1f), 
				ColorMode.RandomPerShot => Color.HSVToRGB(Random.value, 0.9f, 1f), 
				ColorMode.PerHand => hand switch
				{
					0 => PresetToColor((TracerColor)LeftPreset.Value), 
					1 => PresetToColor((TracerColor)RightPreset.Value), 
					_ => PresetToColor((TracerColor)Preset.Value), 
				}, 
				_ => PresetToColor((TracerColor)Preset.Value), 
			});
		}
	}
	public struct TracerStyle
	{
		public byte Mode;

		public float SpeedMs;

		public float Gravity;

		public float HopUp;

		public float Drag;

		public float Spread;

		public byte Bounces;

		public float Restitution;

		public float BBSize;

		public float TrailTime;

		public float TrailWidth;

		public float Intensity;

		public float LightRange;

		public float ImpactSize;

		public bool GlowFade;

		public bool Light;

		public bool ImpactFlash;

		public bool MuzzleFlash;

		public TracerMode TMode => (TracerMode)Mathf.Clamp((int)Mode, 0, 2);

		public static TracerStyle FromSettings()
		{
			TracerMode currentMode = Settings.CurrentMode;
			return new TracerStyle
			{
				Mode = (byte)currentMode,
				SpeedMs = ((currentMode == TracerMode.Bullet) ? Settings.BulletSpeed.Value : (Settings.SpeedFps.Value * 0.3048f)),
				Gravity = Settings.GravityScale.Value,
				HopUp = Settings.HopUp.Value,
				Drag = Settings.Drag.Value,
				Spread = Settings.SpreadDeg.Value,
				Bounces = (byte)Mathf.Clamp(Settings.Bounces.Value, 0, 5),
				Restitution = Settings.Restitution.Value,
				BBSize = Settings.BBSize.Value,
				TrailTime = Settings.TrailTime.Value,
				TrailWidth = Settings.TrailWidth.Value,
				Intensity = Settings.Intensity.Value,
				LightRange = Settings.LightRange.Value,
				ImpactSize = Settings.ImpactSize.Value,
				GlowFade = Settings.GlowFade.Value,
				Light = Settings.GlowLight.Value,
				ImpactFlash = Settings.ImpactFlash.Value,
				MuzzleFlash = Settings.MuzzleFlash.Value
			};
		}

		public void Clamp()
		{
			Mode = (byte)Mathf.Clamp((int)Mode, 0, 2);
			SpeedMs = Mathf.Clamp(SpeedMs, 1f, 1000f);
			Gravity = Mathf.Clamp(Gravity, 0f, 3f);
			HopUp = Mathf.Clamp(HopUp, 0f, 2f);
			Drag = Mathf.Clamp(Drag, 0f, 3f);
			Spread = Mathf.Clamp(Spread, 0f, 25f);
			Bounces = (byte)Mathf.Clamp((int)Bounces, 0, 5);
			Restitution = Mathf.Clamp(Restitution, 0.05f, 0.9f);
			BBSize = Mathf.Clamp(BBSize, 0.5f, 10f);
			TrailTime = Mathf.Clamp(TrailTime, 0.02f, 2f);
			TrailWidth = Mathf.Clamp(TrailWidth, 0.1f, 5f);
			Intensity = Mathf.Clamp(Intensity, 0.25f, 10f);
			LightRange = Mathf.Clamp(LightRange, 0.25f, 6f);
			ImpactSize = Mathf.Clamp(ImpactSize, 0.1f, 5f);
		}
	}
	public struct ShotInfo
	{
		public Vector3 Origin;

		public Vector3 Direction;

		public Vector3 GunUp;

		public Color Color;

		public Transform IgnoreA;

		public Transform IgnoreB;

		public TracerStyle Style;
	}
	internal class Tracer
	{
		public GameObject Root;

		public GameObject BB;

		private Material _bbMat;

		private Material _trailMat;

		private TrailRenderer _trail;

		private Light _light;

		public bool Active;

		private bool _flying;

		private Vector3 _pos;

		private Vector3 _vel;

		private Vector3 _lift;

		private float _v0;

		private float _age;

		private float _fadeLeft;

		private float _nextGlow;

		private int _bouncesLeft;

		private Color _color;

		private Transform _ignA;

		private Transform _ignB;

		private TracerStyle _st;

		public float Age => _age;

		public bool Alive => (Object)(object)Root != (Object)null;

		public Tracer()
		{
			Root = Build.Root("TracerFX_BB");
			(GameObject, MeshRenderer, Material) tuple = Build.Sphere(Root.transform);
			BB = tuple.Item1;
			_bbMat = tuple.Item3;
			_trail = Root.AddComponent<TrailRenderer>();
			_trailMat = Mats.New();
			((Renderer)_trail).sharedMaterial = _trailMat;
			((Renderer)_trail).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)_trail).receiveShadows = false;
			_trail.minVertexDistance = 0.02f;
			_trail.numCapVertices = 2;
			_trail.autodestruct = false;
			_light = Build.PointLight(Root);
			Root.SetActive(false);
		}

		public void Launch(in ShotInfo s)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: 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_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: 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)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			_st = s.Style;
			_v0 = Mathf.Max(1f, _st.SpeedMs);
			_pos = s.Origin;
			Vector3 val = s.Direction;
			_vel = ((Vector3)(ref val)).normalized * _v0;
			val = Vector3.ProjectOnPlane(s.GunUp, s.Direction);
			_lift = ((Vector3)(ref val)).normalized;
			if (((Vector3)(ref _lift)).sqrMagnitude < 0.01f)
			{
				_lift = Vector3.up;
			}
			_ignA = s.IgnoreA;
			_ignB = s.IgnoreB;
			_bouncesLeft = ((_st.TMode != TracerMode.Bullet) ? _st.Bounces : 0);
			_color = s.Color;
			_age = 0f;
			_flying = true;
			Active = true;
			float num = 0.006f * _st.BBSize;
			BB.transform.localScale = Vector3.one * num;
			BB.SetActive(true);
			Mats.SetColor(_bbMat, _color, _st.Intensity * 1.5f);
			float num2 = num * 0.9f * _st.TrailWidth;
			_trail.time = Mathf.Min(_st.TrailTime, Perf.MaxTrailTime);
			_trail.minVertexDistance = Perf.TrailMinVertexDistance;
			_trail.numCapVertices = Perf.TrailCapVertices;
			_nextGlow = 0f;
			_trail.startWidth = num2;
			_trail.endWidth = num2 * 0.15f;
			Color color = _color;
			color.a = 1f;
			Color color2 = _color;
			color2.a = 0f;
			_trail.startColor = color;
			_trail.endColor = color2;
			Mats.SetColor(_trailMat, Color.white, _st.Intensity);
			Root.transform.position = _pos;
			Root.SetActive(true);
			_trail.Clear();
			_trail.emitting = true;
			((Behaviour)_light).enabled = _st.Light && Perf.AllowLights;
			if (((Behaviour)_light).enabled)
			{
				_light.color = _color;
				_light.range = _st.LightRange;
				_light.intensity = 1.5f * _st.Intensity;
			}
		}

		public void Tick(float dt)
		{
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			if (!Active)
			{
				return;
			}
			_age += dt;
			if (!_flying)
			{
				_fadeLeft -= dt;
				if (_fadeLeft <= 0f)
				{
					Retire();
				}
				return;
			}
			if (_age > Settings.MaxLifetime.Value || _pos.y < -500f)
			{
				Stop();
				return;
			}
			if (_st.GlowFade && _st.TMode == TracerMode.Airsoft && _age >= _nextGlow)
			{
				_nextGlow = _age + Perf.GlowInterval;
				float num = Mathf.Lerp(1f, 0.35f, Mathf.Clamp01(_age / 1.5f));
				Mats.SetColor(_bbMat, _color, _st.Intensity * 1.5f * num);
				if (((Behaviour)_light).enabled)
				{
					_light.intensity = 1.5f * _st.Intensity * num;
				}
			}
			int num2 = Mathf.Clamp(Mathf.CeilToInt(((Vector3)(ref _vel)).magnitude * dt / Perf.StepLength), 1, Perf.MaxSubsteps);
			float h = dt / (float)num2;
			for (int i = 0; i < num2; i++)
			{
				if (!_flying)
				{
					break;
				}
				Step(h);
			}
			Root.transform.position = _pos;
		}

		private void Step(float h)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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)
			//IL_0034: 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)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0211: 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_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: 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_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = Vector3.zero;
			if (_st.TMode == TracerMode.Airsoft)
			{
				float magnitude = ((Vector3)(ref _vel)).magnitude;
				val += Physics.gravity * _st.Gravity;
				float num = magnitude / _v0;
				val += _lift * (_st.HopUp * 9.81f * 0.95f * num * num);
				val += -_vel * (0.012f * _st.Drag * magnitude);
			}
			Vector3 val2 = _vel + val * h;
			Vector3 val3 = val2 * h;
			float magnitude2 = ((Vector3)(ref val3)).magnitude;
			RaycastHit hit;
			if (magnitude2 < 1E-06f)
			{
				_vel = val2;
			}
			else if (Core.SafeRaycast(_pos, val3 / magnitude2, magnitude2, _ignA, _ignB, out hit))
			{
				if (_bouncesLeft > 0 && _st.TMode == TracerMode.Airsoft)
				{
					_bouncesLeft--;
					Vector3 val4 = Vector3.Reflect(val2, ((RaycastHit)(ref hit)).normal) * _st.Restitution;
					_pos = ((RaycastHit)(ref hit)).point + ((RaycastHit)(ref hit)).normal * 0.003f;
					_vel = val4;
					Vector3 val5 = Vector3.ProjectOnPlane(_lift, val4);
					_lift = ((Vector3)(ref val5)).normalized;
					TracerManager.Impact(((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, _color, 0.45f, in _st);
					if (((Vector3)(ref _vel)).magnitude < 1.5f)
					{
						Stop();
					}
				}
				else
				{
					_pos = ((RaycastHit)(ref hit)).point;
					TracerManager.Impact(((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, _color, 1f, in _st);
					Stop();
				}
			}
			else
			{
				_pos += val3;
				_vel = val2;
			}
		}

		private void Stop()
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			_flying = false;
			BB.SetActive(false);
			((Behaviour)_light).enabled = false;
			_trail.emitting = false;
			Root.transform.position = _pos;
			_fadeLeft = _trail.time + 0.05f;
		}

		public void Retire()
		{
			Active = false;
			_flying = false;
			if (!((Object)(object)Root == (Object)null))
			{
				_trail.emitting = false;
				_trail.Clear();
				Root.SetActive(false);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)Root != (Object)null)
			{
				Object.Destroy((Object)(object)Root);
			}
			if ((Object)(object)_bbMat != (Object)null)
			{
				Object.Destroy((Object)(object)_bbMat);
			}
			if ((Object)(object)_trailMat != (Object)null)
			{
				Object.Destroy((Object)(object)_trailMat);
			}
		}
	}
	internal class Beam
	{
		public GameObject Root;

		private LineRenderer _line;

		private Material _mat;

		public bool Active;

		private float _t;

		private float _life;

		private float _width;

		private Color _color;

		public bool Alive => (Object)(object)Root != (Object)null;

		public Beam()
		{
			Root = Build.Root("TracerFX_Beam");
			_line = Root.AddComponent<LineRenderer>();
			_mat = Mats.New();
			((Renderer)_line).sharedMaterial = _mat;
			_line.positionCount = 2;
			_line.useWorldSpace = true;
			_line.numCapVertices = 2;
			((Renderer)_line).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)_line).receiveShadows = false;
			Root.SetActive(false);
		}

		public void Show(Vector3 a, Vector3 b, Color c, in TracerStyle st)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: 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_006a: Unknown result type (might be due to invalid IL or missing references)
			_color = c;
			_life = Mathf.Max(0.05f, st.TrailTime * 1.5f);
			_t = 0f;
			_width = 0.004f * st.BBSize * st.TrailWidth;
			_line.SetPosition(0, a);
			_line.SetPosition(1, b);
			Mats.SetColor(_mat, Color.white, st.Intensity);
			Apply(1f);
			Root.SetActive(true);
			Active = true;
		}

		private void Apply(float k)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			//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_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			Color color = _color;
			color.a = k;
			_line.startColor = color;
			_line.endColor = new Color(color.r, color.g, color.b, k * 0.6f);
			_line.startWidth = _width * k;
			_line.endWidth = _width * k * 0.7f;
		}

		public void Tick(float dt)
		{
			if (Active)
			{
				_t += dt;
				float num = 1f - _t / _life;
				if (num <= 0f)
				{
					Retire();
				}
				else
				{
					Apply(num);
				}
			}
		}

		public void Retire()
		{
			Active = false;
			if ((Object)(object)Root != (Object)null)
			{
				Root.SetActive(false);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)Root != (Object)null)
			{
				Object.Destroy((Object)(object)Root);
			}
			if ((Object)(object)_mat != (Object)null)
			{
				Object.Destroy((Object)(object)_mat);
			}
		}
	}
	internal class Flash
	{
		public GameObject Root;

		private GameObject _sphere;

		private Material _mat;

		private Light _light;

		public bool Active;

		private float _t;

		private float _life;

		private float _size;

		private float _intensity;

		private Color _color;

		public bool Alive => (Object)(object)Root != (Object)null;

		public Flash()
		{
			Root = Build.Root("TracerFX_Impact");
			(GameObject, MeshRenderer, Material) tuple = Build.Sphere(Root.transform);
			_sphere = tuple.Item1;
			_mat = tuple.Item3;
			_light = Build.PointLight(Root);
			Root.SetActive(false);
		}

		public void Show(Vector3 p, Color c, float scale, in TracerStyle st)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			_color = c;
			_t = 0f;
			_life = 0.18f;
			_intensity = st.Intensity;
			_size = 0.035f * st.ImpactSize * scale * Mathf.Max(0.5f, st.BBSize * 0.5f);
			Root.transform.position = p;
			((Behaviour)_light).enabled = Settings.ImpactLight.Value && Perf.AllowLights;
			if (((Behaviour)_light).enabled)
			{
				_light.color = c;
				_light.range = 1.2f * st.ImpactSize;
			}
			Apply(0f);
			Root.SetActive(true);
			Active = true;
		}

		private void Apply(float t)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			float num = 1f - t;
			_sphere.transform.localScale = Vector3.one * (_size * (0.4f + t));
			Mats.SetColor(_mat, _color, _intensity * 2f * num * num);
			if (((Behaviour)_light).enabled)
			{
				_light.intensity = 3f * num;
			}
		}

		public void Tick(float dt)
		{
			if (Active)
			{
				_t += dt;
				float num = _t / _life;
				if (num >= 1f)
				{
					Retire();
				}
				else
				{
					Apply(num);
				}
			}
		}

		public void Retire()
		{
			Active = false;
			if ((Object)(object)Root != (Object)null)
			{
				Root.SetActive(false);
			}
		}

		public void Destroy()
		{
			if ((Object)(object)Root != (Object)null)
			{
				Object.Destroy((Object)(object)Root);
			}
			if ((Object)(object)_mat != (Object)null)
			{
				Object.Destroy((Object)(object)_mat);
			}
		}
	}
	public static class TracerManager
	{
		private static readonly List<Tracer> _tracers = new List<Tracer>();

		private static readonly List<Beam> _beams = new List<Beam>();

		private static readonly List<Flash> _flashes = new List<Flash>();

		public static int ActiveCount
		{
			get
			{
				int num = 0;
				foreach (Tracer tracer in _tracers)
				{
					if (tracer.Active)
					{
						num++;
					}
				}
				return num;
			}
		}

		public static void Fire(in ShotInfo s)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: 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)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			if (!Mats.EnsureBase())
			{
				return;
			}
			TracerStyle st = s.Style;
			if (st.MuzzleFlash && st.TMode == TracerMode.Airsoft && Perf.AllowMuzzleFlash)
			{
				Impact(s.Origin, -s.Direction, s.Color, 0.35f, in st, force: true);
			}
			if (st.TMode == TracerMode.Laser)
			{
				float laserRange = Perf.LaserRange;
				Vector3 b = s.Origin + s.Direction * laserRange;
				if (Core.SafeRaycast(s.Origin, s.Direction, laserRange, s.IgnoreA, s.IgnoreB, out var hit))
				{
					b = ((RaycastHit)(ref hit)).point;
					Impact(((RaycastHit)(ref hit)).point, ((RaycastHit)(ref hit)).normal, s.Color, 1f, in st);
				}
				Get(_beams, () => new Beam(), (Beam x) => x.Active, (Beam x) => x.Alive)?.Show(s.Origin, b, s.Color, in st);
			}
			else
			{
				GetTracer()?.Launch(in s);
			}
		}

		private static Tracer GetTracer()
		{
			int num = 0;
			Tracer tracer = null;
			for (int num2 = _tracers.Count - 1; num2 >= 0; num2--)
			{
				Tracer tracer2 = _tracers[num2];
				if (!tracer2.Alive)
				{
					_tracers.RemoveAt(num2);
				}
				else
				{
					if (!tracer2.Active)
					{
						return tracer2;
					}
					num++;
					if (tracer == null || tracer2.Age > tracer.Age)
					{
						tracer = tracer2;
					}
				}
			}
			if (num >= Perf.MaxTracers && tracer != null)
			{
				tracer.Retire();
				return tracer;
			}
			Tracer tracer3 = new Tracer();
			_tracers.Add(tracer3);
			return tracer3;
		}

		private static T Get<T>(List<T> list, Func<T> make, Func<T, bool> isActive, Func<T, bool> isAlive) where T : class
		{
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (!isAlive(list[num]))
				{
					list.RemoveAt(num);
				}
				else if (!isActive(list[num]))
				{
					return list[num];
				}
			}
			if (list.Count >= Perf.PoolCap)
			{
				return null;
			}
			T val = make();
			list.Add(val);
			return val;
		}

		internal static void Impact(Vector3 p, Vector3 n, Color c, float scale, in TracerStyle st, bool force = false)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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)
			if ((force || st.ImpactFlash) && Mats.Ready)
			{
				Get(_flashes, () => new Flash(), (Fl