Decompiled source of SandevistanAfterimage v0.9.4

Mods/SandevistanAfterimage.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using SandevistanAfterimage;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Main), "Sandevistan Afterimage", "0.9.7", "OpenAI", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SandevistanAfterimage")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SandevistanAfterimage")]
[assembly: AssemblyTitle("SandevistanAfterimage")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SandevistanAfterimage
{
	public class Main : MelonMod
	{
		private class TintOverlay
		{
			public Camera camera;

			public GameObject quad;

			public Material material;
		}

		private class GhostSnapshot
		{
			public readonly float created;

			public readonly float lifetime;

			public readonly Vector3 origin;

			public readonly Material bodyMaterial;

			public readonly Material shellMaterial;

			public readonly List<GhostPart> parts = new List<GhostPart>();

			public GhostSnapshot(float createdTime, float life, Vector3 originPosition, Material body, Material shell)
			{
				//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)
				created = createdTime;
				lifetime = life;
				origin = originPosition;
				bodyMaterial = body;
				shellMaterial = shell;
			}
		}

		private class GhostPart
		{
			public readonly GameObject bodyObject;

			public readonly GameObject shellObject;

			public readonly Mesh mesh;

			public readonly Mesh shellMesh;

			public GhostPart(GameObject body, GameObject shell, Mesh meshValue, Mesh shellMeshValue)
			{
				bodyObject = body;
				shellObject = shell;
				mesh = meshValue;
				shellMesh = shellMeshValue;
			}
		}

		private static readonly Color BodyNear = new Color(0.05f, 0.95f, 0.9f, 1f);

		private static readonly Color BodyFar = new Color(0.02f, 0.5f, 0.4f, 1f);

		private static readonly Color RimNear = new Color(0.55f, 1f, 0.95f, 1f);

		private static readonly Color RimFar = new Color(0.05f, 0.85f, 0.65f, 1f);

		private static readonly Color TintColor = new Color(0.04f, 0.68f, 0.18f, 1f);

		private static readonly Color AfterimageFadeGreen = new Color(0.08f, 0.88f, 0.24f, 1f);

		private MelonPreferences_Category prefs;

		private MelonPreferences_Entry<bool> enabledPref;

		private MelonPreferences_Entry<bool> slowMoPref;

		private MelonPreferences_Entry<float> thresholdPref;

		private MelonPreferences_Entry<int> ghostCountPref;

		private MelonPreferences_Entry<float> spawnIntervalPref;

		private MelonPreferences_Entry<float> lifetimePref;

		private MelonPreferences_Entry<float> alphaPref;

		private MelonPreferences_Entry<bool> movementOnlyPref;

		private MelonPreferences_Entry<float> spawnDistancePref;

		private MelonPreferences_Entry<float> trailLengthPref;

		private MelonPreferences_Entry<bool> rimPref;

		private MelonPreferences_Entry<float> rimWidthPref;

		private MelonPreferences_Entry<bool> additivePref;

		private MelonPreferences_Entry<bool> worldTintPref;

		private MelonPreferences_Entry<float> worldTintStrengthPref;

		private MelonPreferences_Entry<bool> debugPref;

		private MelonPreferences_Entry<bool> hotkeyPref;

		private readonly List<GhostSnapshot> snapshots = new List<GhostSnapshot>();

		private SkinnedMeshRenderer[] avatarRenderers = (SkinnedMeshRenderer[])(object)new SkinnedMeshRenderer[0];

		private GameObject avatarObject;

		private Vector3 lastSpawnPosition;

		private Vector3 lastMovementDirection = Vector3.forward;

		private float spawnTimer;

		private float scanTimer;

		private bool wasSlow;

		private bool lastEnabled;

		private bool announcedAvatar;

		private Material ghostMaterialTemplate;

		private bool blendControllable;

		private readonly List<TintOverlay> tintOverlays = new List<TintOverlay>();

		private Material tintMaterialTemplate;

		private bool tintActive;

		private float tintFade;

		private const float TintFadeDuration = 0.12f;

		private bool fogSaved;

		private bool savedFog;

		private Color savedFogColor;

		private float savedFogDensity;

		private FogMode savedFogMode;

		private Color savedAmbient;

		private float savedAmbientIntensity;

		private static Mesh unitQuadMesh;

		public override void OnInitializeMelon()
		{
			prefs = MelonPreferences.CreateCategory("SandevistanAfterimage", "Sandevistan Afterimage");
			enabledPref = prefs.CreateEntry<bool>("Enabled", true, "Enabled", "Master switch.", false, false, (ValueValidator)null, (string)null);
			slowMoPref = prefs.CreateEntry<bool>("TriggerOnSlowMotion", true, "Trigger on slow motion", "Activate when Time.timeScale is below threshold (Quicksilver compatible).", false, false, (ValueValidator)null, (string)null);
			thresholdPref = prefs.CreateEntry<float>("SlowMotionThreshold", 0.92f, "Slow-motion threshold", "Below this timeScale the effect runs.", false, false, (ValueValidator)null, (string)null);
			ghostCountPref = prefs.CreateEntry<int>("GhostCount", 64, "Ghost count", "Max simultaneous afterimages.", false, false, (ValueValidator)null, (string)null);
			spawnIntervalPref = prefs.CreateEntry<float>("SpawnInterval", 0.02f, "Min spawn interval", "Min unscaled seconds between snapshots.", false, false, (ValueValidator)null, (string)null);
			lifetimePref = prefs.CreateEntry<float>("Lifetime", 8f, "Lifetime", "Unscaled seconds until a ghost fully fades.", false, false, (ValueValidator)null, (string)null);
			alphaPref = prefs.CreateEntry<float>("Alpha", 0.55f, "Alpha", "Starting intensity of each ghost.", false, false, (ValueValidator)null, (string)null);
			movementOnlyPref = prefs.CreateEntry<bool>("MovementOnly", true, "Movement only", "Only spawn after moving SpawnDistance.", false, false, (ValueValidator)null, (string)null);
			spawnDistancePref = prefs.CreateEntry<float>("SpawnDistance", 0.55f, "Spawn distance", "Meters between ghosts.", false, false, (ValueValidator)null, (string)null);
			trailLengthPref = prefs.CreateEntry<float>("TrailLength", 18f, "Trail length", "Meters until fully faded.", false, false, (ValueValidator)null, (string)null);
			rimPref = prefs.CreateEntry<bool>("RimGlow", true, "Rim glow", "Bright inverted-hull outline.", false, false, (ValueValidator)null, (string)null);
			rimWidthPref = prefs.CreateEntry<float>("RimWidth", 0.016f, "Rim width", "Outline thickness in meters.", false, false, (ValueValidator)null, (string)null);
			additivePref = prefs.CreateEntry<bool>("Additive", true, "Additive glow", "Additive blending for brighter overlaps.", false, false, (ValueValidator)null, (string)null);
			worldTintPref = prefs.CreateEntry<bool>("WorldTint", true, "World green tint", "Full-screen green overlay + ambient while slow-mo is active.", false, false, (ValueValidator)null, (string)null);
			worldTintStrengthPref = prefs.CreateEntry<float>("WorldTintStrength", 0.25f, "World tint strength", "0 = off, 1 = heavy green. Affects only your view.", false, false, (ValueValidator)null, (string)null);
			debugPref = prefs.CreateEntry<bool>("DebugLogging", true, "Debug logging", "Console diagnostics.", false, false, (ValueValidator)null, (string)null);
			hotkeyPref = prefs.CreateEntry<bool>("F8Toggle", true, "F8 toggle", "Press F8 to toggle.", false, false, (ValueValidator)null, (string)null);
			prefs.SaveToFile(false);
			lastEnabled = enabledPref.Value;
			MelonLogger.Msg("Sandevistan Afterimage 0.9.6 loaded.");
			MelonLogger.Msg("Afterimages + full-screen green tint are client-side only (Fusion-safe).");
			MelonLogger.Msg("Settings: UserData/MelonPreferences.cfg [SandevistanAfterimage]");
		}

		public override void OnUpdate()
		{
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_0222: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: 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_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			if (hotkeyPref.Value && Input.GetKeyDown((KeyCode)289))
			{
				enabledPref.Value = !enabledPref.Value;
				prefs.SaveToFile(false);
				if (!enabledPref.Value)
				{
					ClearSnapshots();
					SetTintActive(active: false);
				}
				MelonLogger.Msg("Sandevistan Afterimage: " + (enabledPref.Value ? "ON" : "OFF"));
			}
			if (lastEnabled != enabledPref.Value)
			{
				lastEnabled = enabledPref.Value;
				if (!lastEnabled)
				{
					ClearSnapshots();
					SetTintActive(active: false);
				}
			}
			UpdateSnapshots();
			if (!enabledPref.Value)
			{
				SetTintActive(active: false);
				return;
			}
			scanTimer -= Time.unscaledDeltaTime;
			if (scanTimer <= 0f)
			{
				scanTimer = 0.4f;
				RefreshAvatar();
				RefreshTintCameras();
			}
			if ((Object)(object)avatarObject == (Object)null || avatarRenderers.Length == 0)
			{
				SetTintActive(active: false);
				return;
			}
			bool flag = slowMoPref.Value && Time.timeScale < Mathf.Clamp(thresholdPref.Value, 0.01f, 1f);
			if (flag && !wasSlow)
			{
				lastSpawnPosition = avatarObject.transform.position;
				if (debugPref.Value)
				{
					MelonLogger.Msg("Slow motion ON  timeScale=" + Time.timeScale.ToString("0.000"));
				}
			}
			if (!flag && wasSlow && debugPref.Value)
			{
				MelonLogger.Msg("Slow motion OFF");
			}
			wasSlow = flag;
			SetTintActive(flag && worldTintPref.Value);
			if (!flag)
			{
				return;
			}
			spawnTimer -= Time.unscaledDeltaTime;
			if (spawnTimer > 0f)
			{
				return;
			}
			Vector3 position = avatarObject.transform.position;
			Vector3 val = position - lastSpawnPosition;
			float num = Mathf.Max(0.02f, spawnDistancePref.Value);
			if (movementOnlyPref.Value && ((Vector3)(ref val)).sqrMagnitude < num * num)
			{
				return;
			}
			if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
			{
				lastMovementDirection = ((Vector3)(ref val)).normalized;
			}
			else
			{
				Vector3 forward = avatarObject.transform.forward;
				if (((Vector3)(ref forward)).sqrMagnitude > 0.0001f)
				{
					forward = avatarObject.transform.forward;
					lastMovementDirection = ((Vector3)(ref forward)).normalized;
				}
			}
			spawnTimer = Mathf.Max(0.008f, spawnIntervalPref.Value);
			lastSpawnPosition = position;
			CreateSnapshot(lastMovementDirection);
		}

		private void RefreshAvatar()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.RigManager == (Object)null)
			{
				if (debugPref.Value && !announcedAvatar)
				{
					MelonLogger.Msg("Waiting for BoneLib player...");
				}
				return;
			}
			GameObject val = null;
			try
			{
				if ((Object)(object)Player.Avatar != (Object)null)
				{
					val = ((Component)Player.Avatar).gameObject;
				}
			}
			catch (Exception ex)
			{
				if (debugPref.Value)
				{
					MelonLogger.Warning("Player.Avatar read failed: " + ex.Message);
				}
				return;
			}
			if (!((Object)(object)val == (Object)null) && (Object)(object)avatarObject != (Object)(object)val)
			{
				avatarObject = val;
				avatarRenderers = Il2CppArrayBase<SkinnedMeshRenderer>.op_Implicit(avatarObject.GetComponentsInChildren<SkinnedMeshRenderer>(true));
				lastSpawnPosition = avatarObject.transform.position;
				ClearSnapshots();
				announcedAvatar = true;
				string[] obj = new string[6]
				{
					"Avatar: ",
					((Object)avatarObject).name,
					"  renderers=",
					avatarRenderers.Length.ToString(),
					"  rootLossyScale=",
					null
				};
				Vector3 lossyScale = avatarObject.transform.lossyScale;
				obj[5] = ((Vector3)(ref lossyScale)).ToString("F3");
				MelonLogger.Msg(string.Concat(obj));
			}
		}

		private void CreateSnapshot(Vector3 movementDirection)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: 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_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			Material val = CreateGhostMaterial(shell: false);
			if ((Object)(object)val == (Object)null)
			{
				if (debugPref.Value)
				{
					MelonLogger.Warning("No usable shader for ghost material.");
				}
				return;
			}
			Material val2 = ((rimPref.Value && (Object)(object)ghostMaterialTemplate != (Object)null && ghostMaterialTemplate.HasProperty("_Cull")) ? CreateGhostMaterial(shell: true) : null);
			float width = Mathf.Clamp(rimWidthPref.Value, 0.001f, 0.08f);
			GhostSnapshot ghostSnapshot = new GhostSnapshot(Time.unscaledTime, Mathf.Max(0.02f, lifetimePref.Value), avatarObject.transform.position, val, val2);
			int num = 0;
			for (int i = 0; i < avatarRenderers.Length; i++)
			{
				SkinnedMeshRenderer val3 = avatarRenderers[i];
				if ((Object)(object)val3 == (Object)null || !((Renderer)val3).enabled || (Object)(object)val3.sharedMesh == (Object)null || val3.sharedMesh.vertexCount < 12)
				{
					continue;
				}
				GameObject val4 = null;
				GameObject val5 = null;
				Mesh val6 = null;
				Mesh val7 = null;
				try
				{
					val6 = new Mesh();
					((Object)val6).name = "SandevistanAfterimageMesh";
					val3.BakeMesh(val6, true);
					val4 = SpawnGhostPart("SandevistanAfterimagePart", ((Component)val3).transform, val6, val, -movementDirection * 0.25f);
					if ((Object)(object)val2 != (Object)null)
					{
						val7 = BuildShellMesh(val6, width);
						if ((Object)(object)val7 != (Object)null)
						{
							val5 = SpawnGhostPart("SandevistanAfterimageRim", ((Component)val3).transform, val7, val2, -movementDirection * 0.25f);
						}
					}
					ghostSnapshot.parts.Add(new GhostPart(val4, val5, val6, val7));
					num++;
				}
				catch (Exception ex)
				{
					if ((Object)(object)val4 != (Object)null)
					{
						Object.Destroy((Object)(object)val4);
					}
					if ((Object)(object)val5 != (Object)null)
					{
						Object.Destroy((Object)(object)val5);
					}
					if ((Object)(object)val6 != (Object)null)
					{
						Object.Destroy((Object)(object)val6);
					}
					if ((Object)(object)val7 != (Object)null)
					{
						Object.Destroy((Object)(object)val7);
					}
					if (debugPref.Value)
					{
						MelonLogger.Warning("Bake failed on " + ((Object)val3).name + ": " + ex.Message);
					}
				}
			}
			if (num == 0)
			{
				DestroySnapshot(ghostSnapshot);
				if (debugPref.Value)
				{
					MelonLogger.Warning("Snapshot produced 0 mesh parts.");
				}
				return;
			}
			ApplySnapshotColors(ghostSnapshot, 0f);
			snapshots.Add(ghostSnapshot);
			TrimSnapshots();
			if (debugPref.Value)
			{
				MelonLogger.Msg("Snapshot: " + num + " parts" + (((Object)(object)val2 != (Object)null) ? " +rim" : ""));
			}
		}

		private static GameObject SpawnGhostPart(string name, Transform source, Mesh mesh, Material material, Vector3 worldOffset)
		{
			//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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: 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_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_0069: Expected O, but got Unknown
			GameObject val = new GameObject(name);
			val.transform.position = source.position + worldOffset;
			val.transform.rotation = source.rotation;
			val.transform.localScale = source.lossyScale;
			MeshFilter val2 = val.AddComponent<MeshFilter>();
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			val2.sharedMesh = mesh;
			((Renderer)obj).sharedMaterial = material;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			return val;
		}

		private static Mesh BuildShellMesh(Mesh baked, float width)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_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)
			Mesh val = Object.Instantiate<Mesh>(baked);
			((Object)val).name = "SandevistanAfterimageRimMesh";
			Vector3[] array = Il2CppArrayBase<Vector3>.op_Implicit((Il2CppArrayBase<Vector3>)(object)val.vertices);
			Vector3[] array2 = Il2CppArrayBase<Vector3>.op_Implicit((Il2CppArrayBase<Vector3>)(object)val.normals);
			if (array == null || array2 == null || array2.Length != array.Length)
			{
				Object.Destroy((Object)(object)val);
				return null;
			}
			for (int i = 0; i < array.Length; i++)
			{
				Vector3 val2 = array2[i];
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (magnitude > 1E-05f)
				{
					array[i] += val2 * (width / magnitude);
				}
			}
			val.vertices = Il2CppStructArray<Vector3>.op_Implicit(array);
			val.RecalculateBounds();
			return val;
		}

		private Material CreateGhostMaterial(bool shell)
		{
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Expected O, but got Unknown
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ghostMaterialTemplate == (Object)null)
			{
				Shader val = Shader.Find("Universal Render Pipeline/Unlit");
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Unlit/Transparent");
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Sprites/Default");
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Standard");
				}
				if ((Object)(object)val == (Object)null)
				{
					return null;
				}
				ghostMaterialTemplate = new Material(val);
				((Object)ghostMaterialTemplate).name = "SandevistanAfterimageMatTemplate";
				blendControllable = ghostMaterialTemplate.HasProperty("_SrcBlend") && ghostMaterialTemplate.HasProperty("_DstBlend");
				if (debugPref.Value)
				{
					MelonLogger.Msg("Ghost shader: " + ((Object)val).name + "  blend=" + blendControllable + "  _Cull=" + ghostMaterialTemplate.HasProperty("_Cull"));
				}
			}
			Material val2 = new Material(ghostMaterialTemplate);
			bool flag = additivePref.Value && blendControllable;
			if (val2.HasProperty("_Surface"))
			{
				val2.SetFloat("_Surface", 1f);
				val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
				val2.SetOverrideTag("RenderType", "Transparent");
			}
			if (val2.HasProperty("_Blend"))
			{
				val2.SetFloat("_Blend", flag ? 2f : 0f);
			}
			if (val2.HasProperty("_SrcBlend"))
			{
				val2.SetFloat("_SrcBlend", flag ? 1f : 5f);
			}
			if (val2.HasProperty("_DstBlend"))
			{
				val2.SetFloat("_DstBlend", flag ? 1f : 10f);
			}
			if (val2.HasProperty("_ZWrite"))
			{
				val2.SetFloat("_ZWrite", 0f);
			}
			if (val2.HasProperty("_Cull"))
			{
				val2.SetFloat("_Cull", shell ? 1f : 0f);
			}
			val2.renderQueue = (shell ? 3001 : 3000);
			SetMaterialColor(val2, Compose(shell ? RimNear : BodyNear, Mathf.Clamp01(alphaPref.Value)));
			return val2;
		}

		private Color Compose(Color rgb, float intensity)
		{
			//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_0040: 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_0015: 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_0025: 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)
			if (additivePref.Value && blendControllable)
			{
				return new Color(rgb.r * intensity, rgb.g * intensity, rgb.b * intensity, intensity);
			}
			return new Color(rgb.r, rgb.g, rgb.b, intensity);
		}

		private static void SetMaterialColor(Material material, Color color)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)material == (Object)null))
			{
				if (material.HasProperty("_Color"))
				{
					material.SetColor("_Color", color);
				}
				if (material.HasProperty("_BaseColor"))
				{
					material.SetColor("_BaseColor", color);
				}
			}
		}

		private void ApplySnapshotColors(GhostSnapshot snapshot, float t)
		{
			//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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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_006f: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(alphaPref.Value) * Mathf.Pow(1f - t, 1.35f);
			float num2 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.65f, 1f, t));
			Color rgb = Color.Lerp(Color.Lerp(BodyNear, BodyFar, t), AfterimageFadeGreen, num2);
			Color rgb2 = Color.Lerp(Color.Lerp(RimNear, RimFar, t), AfterimageFadeGreen, num2);
			SetMaterialColor(snapshot.bodyMaterial, Compose(rgb, num));
			if ((Object)(object)snapshot.shellMaterial != (Object)null)
			{
				SetMaterialColor(snapshot.shellMaterial, Compose(rgb2, Mathf.Clamp01(num * 1.7f)));
			}
		}

		private void UpdateSnapshots()
		{
			//IL_0034: 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_0039: 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_009a: Unknown result type (might be due to invalid IL or missing references)
			float unscaledTime = Time.unscaledTime;
			float value = trailLengthPref.Value;
			bool flag = (Object)(object)avatarObject != (Object)null;
			Vector3 val = (flag ? avatarObject.transform.position : Vector3.zero);
			for (int num = snapshots.Count - 1; num >= 0; num--)
			{
				GhostSnapshot ghostSnapshot = snapshots[num];
				if (ghostSnapshot == null)
				{
					snapshots.RemoveAt(num);
				}
				else
				{
					float num2 = (unscaledTime - ghostSnapshot.created) / ghostSnapshot.lifetime;
					float num3 = 0f;
					if (flag && value > 0.05f)
					{
						num3 = Vector3.Distance(ghostSnapshot.origin, val) / value;
					}
					float num4 = Mathf.Clamp01(Mathf.Max(num2, num3));
					ApplySnapshotColors(ghostSnapshot, num4);
					if (num4 >= 1f)
					{
						DestroySnapshot(ghostSnapshot);
						snapshots.RemoveAt(num);
					}
				}
			}
		}

		private void TrimSnapshots()
		{
			int num = Mathf.Clamp(ghostCountPref.Value, 1, 64);
			while (snapshots.Count > num)
			{
				DestroySnapshot(snapshots[0]);
				snapshots.RemoveAt(0);
			}
		}

		private void DestroySnapshot(GhostSnapshot snapshot)
		{
			for (int i = 0; i < snapshot.parts.Count; i++)
			{
				GhostPart ghostPart = snapshot.parts[i];
				if (ghostPart != null)
				{
					if ((Object)(object)ghostPart.mesh != (Object)null)
					{
						Object.Destroy((Object)(object)ghostPart.mesh);
					}
					if ((Object)(object)ghostPart.shellMesh != (Object)null)
					{
						Object.Destroy((Object)(object)ghostPart.shellMesh);
					}
					if ((Object)(object)ghostPart.bodyObject != (Object)null)
					{
						Object.Destroy((Object)(object)ghostPart.bodyObject);
					}
					if ((Object)(object)ghostPart.shellObject != (Object)null)
					{
						Object.Destroy((Object)(object)ghostPart.shellObject);
					}
				}
			}
			snapshot.parts.Clear();
			if ((Object)(object)snapshot.bodyMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)snapshot.bodyMaterial);
			}
			if ((Object)(object)snapshot.shellMaterial != (Object)null)
			{
				Object.Destroy((Object)(object)snapshot.shellMaterial);
			}
		}

		private void ClearSnapshots()
		{
			for (int i = 0; i < snapshots.Count; i++)
			{
				DestroySnapshot(snapshots[i]);
			}
			snapshots.Clear();
			wasSlow = false;
		}

		private void RefreshTintCameras()
		{
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Expected O, but got Unknown
			//IL_0167: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
			for (int num = tintOverlays.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)tintOverlays[num].camera == (Object)null || (Object)(object)tintOverlays[num].quad == (Object)null)
				{
					if ((Object)(object)tintOverlays[num].quad != (Object)null)
					{
						Object.Destroy((Object)(object)tintOverlays[num].quad);
					}
					tintOverlays.RemoveAt(num);
				}
			}
			Camera[] array = Il2CppArrayBase<Camera>.op_Implicit((Il2CppArrayBase<Camera>)(object)Camera.allCameras);
			foreach (Camera val in array)
			{
				if ((Object)(object)val == (Object)null || !((Behaviour)val).enabled || !((Component)val).gameObject.activeInHierarchy || (val.orthographic && val.depth < 0f))
				{
					continue;
				}
				bool flag = false;
				for (int j = 0; j < tintOverlays.Count; j++)
				{
					if ((Object)(object)tintOverlays[j].camera == (Object)(object)val)
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					GameObject val2 = new GameObject("SandevistanTintOverlay");
					val2.transform.SetParent(((Component)val).transform, false);
					float num2 = Mathf.Max(0.01f, val.nearClipPlane + 0.02f);
					val2.transform.localPosition = new Vector3(0f, 0f, num2);
					val2.transform.localRotation = Quaternion.identity;
					float num3 = val.fieldOfView * 0.5f * ((float)Math.PI / 180f);
					float num4 = 2f * num2 * Mathf.Tan(num3);
					float num5 = num4 * val.aspect;
					val2.transform.localScale = new Vector3(num5 * 1.25f, num4 * 1.25f, 1f);
					val2.AddComponent<MeshFilter>().sharedMesh = BuildUnitQuad();
					MeshRenderer obj = val2.AddComponent<MeshRenderer>();
					Material material = (((Renderer)obj).sharedMaterial = CreateTintMaterial());
					((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
					((Renderer)obj).receiveShadows = false;
					((Renderer)obj).sortingOrder = 32767;
					val2.SetActive(false);
					tintOverlays.Add(new TintOverlay
					{
						camera = val,
						quad = val2,
						material = material
					});
					if (debugPref.Value)
					{
						MelonLogger.Msg("Tint overlay attached to camera: " + ((Object)val).name);
					}
				}
			}
		}

		private static Mesh BuildUnitQuad()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: 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_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_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_00c4: 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_00da: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)unitQuadMesh != (Object)null)
			{
				return unitQuadMesh;
			}
			unitQuadMesh = new Mesh();
			((Object)unitQuadMesh).name = "SandevistanTintQuad";
			unitQuadMesh.vertices = Il2CppStructArray<Vector3>.op_Implicit((Vector3[])(object)new Vector3[4]
			{
				new Vector3(-0.5f, -0.5f, 0f),
				new Vector3(0.5f, -0.5f, 0f),
				new Vector3(-0.5f, 0.5f, 0f),
				new Vector3(0.5f, 0.5f, 0f)
			});
			unitQuadMesh.uv = Il2CppStructArray<Vector2>.op_Implicit((Vector2[])(object)new Vector2[4]
			{
				new Vector2(0f, 0f),
				new Vector2(1f, 0f),
				new Vector2(0f, 1f),
				new Vector2(1f, 1f)
			});
			unitQuadMesh.triangles = Il2CppStructArray<int>.op_Implicit(new int[6] { 0, 2, 1, 2, 3, 1 });
			unitQuadMesh.RecalculateNormals();
			unitQuadMesh.RecalculateBounds();
			return unitQuadMesh;
		}

		private Material CreateTintMaterial()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)tintMaterialTemplate == (Object)null)
			{
				Shader val = Shader.Find("Universal Render Pipeline/Unlit");
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Unlit/Transparent");
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Sprites/Default");
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("UI/Default");
				}
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Standard");
				}
				tintMaterialTemplate = new Material(val);
				((Object)tintMaterialTemplate).name = "SandevistanTintMatTemplate";
			}
			Material val2 = new Material(tintMaterialTemplate);
			if (val2.HasProperty("_Surface"))
			{
				val2.SetFloat("_Surface", 1f);
				val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
				val2.SetOverrideTag("RenderType", "Transparent");
			}
			if (val2.HasProperty("_SrcBlend"))
			{
				val2.SetFloat("_SrcBlend", 5f);
			}
			if (val2.HasProperty("_DstBlend"))
			{
				val2.SetFloat("_DstBlend", 10f);
			}
			if (val2.HasProperty("_ZWrite"))
			{
				val2.SetFloat("_ZWrite", 0f);
			}
			if (val2.HasProperty("_Cull"))
			{
				val2.SetFloat("_Cull", 0f);
			}
			val2.renderQueue = 5000;
			SetMaterialColor(val2, new Color(TintColor.r, TintColor.g, TintColor.b, 0f));
			return val2;
		}

		private void SetTintActive(bool active)
		{
			//IL_0037: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_027f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: 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_0201: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp01(worldTintStrengthPref.Value);
			bool flag = active && num > 0.01f;
			if (flag && !fogSaved)
			{
				savedFog = RenderSettings.fog;
				savedFogColor = RenderSettings.fogColor;
				savedFogDensity = RenderSettings.fogDensity;
				savedFogMode = RenderSettings.fogMode;
				savedAmbient = RenderSettings.ambientLight;
				savedAmbientIntensity = RenderSettings.ambientIntensity;
				fogSaved = true;
			}
			float num2 = Time.unscaledDeltaTime / Mathf.Max(0.01f, 0.12f);
			tintFade = Mathf.MoveTowards(tintFade, flag ? 1f : 0f, num2);
			if (tintFade > 0.001f && fogSaved)
			{
				float num3 = num * tintFade;
				Color color = default(Color);
				((Color)(ref color))..ctor(TintColor.r, TintColor.g, TintColor.b, num3 * 0.32f);
				for (int i = 0; i < tintOverlays.Count; i++)
				{
					TintOverlay tintOverlay = tintOverlays[i];
					if (!((Object)(object)tintOverlay.quad == (Object)null))
					{
						tintOverlay.quad.SetActive(true);
						if ((Object)(object)tintOverlay.camera != (Object)null)
						{
							float num4 = Mathf.Max(0.01f, tintOverlay.camera.nearClipPlane + 0.02f);
							tintOverlay.quad.transform.localPosition = new Vector3(0f, 0f, num4);
							float num5 = tintOverlay.camera.fieldOfView * 0.5f * ((float)Math.PI / 180f);
							float num6 = 2f * num4 * Mathf.Tan(num5);
							float num7 = num6 * tintOverlay.camera.aspect;
							tintOverlay.quad.transform.localScale = new Vector3(num7 * 1.25f, num6 * 1.25f, 1f);
						}
						if ((Object)(object)tintOverlay.material != (Object)null)
						{
							SetMaterialColor(tintOverlay.material, color);
						}
					}
				}
				RenderSettings.ambientLight = Color.Lerp(savedAmbient, new Color(0.08f, 0.42f, 0.16f), num3 * 0.45f);
				RenderSettings.ambientIntensity = Mathf.Lerp(savedAmbientIntensity, Mathf.Max(savedAmbientIntensity, 1.08f), num3 * 0.25f);
				RenderSettings.fog = true;
				RenderSettings.fogMode = (FogMode)3;
				RenderSettings.fogColor = Color.Lerp(savedFogColor, new Color(0.025f, 0.3f, 0.1f), num3 * 0.45f);
				RenderSettings.fogDensity = Mathf.Lerp(0.003f, 0.0098f, num3 * 0.45f);
				if (!tintActive && debugPref.Value)
				{
					MelonLogger.Msg("World tint ON (smooth fade) strength=" + num.ToString("0.00") + " overlays=" + tintOverlays.Count);
				}
				tintActive = true;
			}
			else
			{
				if (flag || !(tintFade <= 0.001f))
				{
					return;
				}
				for (int j = 0; j < tintOverlays.Count; j++)
				{
					if ((Object)(object)tintOverlays[j].quad != (Object)null)
					{
						tintOverlays[j].quad.SetActive(false);
					}
				}
				if (fogSaved)
				{
					RenderSettings.fog = savedFog;
					RenderSettings.fogColor = savedFogColor;
					RenderSettings.fogDensity = savedFogDensity;
					RenderSettings.fogMode = savedFogMode;
					RenderSettings.ambientLight = savedAmbient;
					RenderSettings.ambientIntensity = savedAmbientIntensity;
					fogSaved = false;
				}
				if (tintActive && debugPref.Value)
				{
					MelonLogger.Msg("World tint OFF");
				}
				tintActive = false;
			}
		}

		private void DestroyAllTintOverlays()
		{
			for (int i = 0; i < tintOverlays.Count; i++)
			{
				if ((Object)(object)tintOverlays[i].quad != (Object)null)
				{
					Object.Destroy((Object)(object)tintOverlays[i].quad);
				}
				if ((Object)(object)tintOverlays[i].material != (Object)null)
				{
					Object.Destroy((Object)(object)tintOverlays[i].material);
				}
			}
			tintOverlays.Clear();
		}

		public override void OnDeinitializeMelon()
		{
			//IL_0025: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			ClearSnapshots();
			tintFade = 0f;
			if (fogSaved)
			{
				RenderSettings.fog = savedFog;
				RenderSettings.fogColor = savedFogColor;
				RenderSettings.fogDensity = savedFogDensity;
				RenderSettings.fogMode = savedFogMode;
				RenderSettings.ambientLight = savedAmbient;
				RenderSettings.ambientIntensity = savedAmbientIntensity;
				fogSaved = false;
			}
			DestroyAllTintOverlays();
			if ((Object)(object)ghostMaterialTemplate != (Object)null)
			{
				Object.Destroy((Object)(object)ghostMaterialTemplate);
			}
			if ((Object)(object)tintMaterialTemplate != (Object)null)
			{
				Object.Destroy((Object)(object)tintMaterialTemplate);
			}
			if ((Object)(object)unitQuadMesh != (Object)null)
			{
				Object.Destroy((Object)(object)unitQuadMesh);
			}
			ghostMaterialTemplate = null;
			tintMaterialTemplate = null;
			unitQuadMesh = null;
		}
	}
}