Decompiled source of TunedSupercar v1.0.0

Mods/TunedSupercar.dll

Decompiled a week 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 MelonLoader;
using Microsoft.CodeAnalysis;
using ScheduleOne.DevUtilities;
using ScheduleOne.Map;
using ScheduleOne.Money;
using ScheduleOne.Vehicles;
using ScheduleOne.Vehicles.Modification;
using TunedSupercar;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(TunedSupercarMod), "Tuned Supercar", "1.0.0", "You", null)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("TunedSupercar")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5b8bfea65b08fe9810ef21cd116fad8f5be354cf")]
[assembly: AssemblyProduct("TunedSupercar")]
[assembly: AssemblyTitle("TunedSupercar")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TunedSupercar
{
	public sealed class TunedSupercarMod : MelonMod
	{
		private const string SUPERCAR_CODE = "supercar";

		private const string SUPERCAR_NAME = "Supercar";

		private const float SUPERCAR_PRICE = 100000f;

		private const float SPEED_MULTIPLIER = 1.4f;

		private const KeyCode PURCHASE_KEY = 289;

		private bool _vehicleAdded = false;

		private bool _showPurchaseUI = false;

		private Rect _windowRect = new Rect((float)(Screen.width / 2 - 200), (float)(Screen.height / 2 - 175), 400f, 350f);

		private Dealership _nearbyDealership = null;

		private CursorLockMode _previousLockState = (CursorLockMode)1;

		private bool _previousCursorVisible = false;

		public override void OnInitializeMelon()
		{
			MelonLogger.Msg("[TunedSupercar] Loaded! Press F8 near the dealership to purchase the Supercar ($100,000).");
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				_vehicleAdded = false;
				_showPurchaseUI = false;
			}
		}

		public override void OnUpdate()
		{
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Invalid comparison between Unknown and I4
			//IL_0096: 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 (!_vehicleAdded && NetworkSingleton<VehicleManager>.InstanceExists)
			{
				TryAddSupercar();
			}
			CheckForNearbyDealership();
			if (Input.GetKeyDown((KeyCode)289))
			{
				if ((Object)(object)_nearbyDealership != (Object)null && _vehicleAdded)
				{
					_showPurchaseUI = !_showPurchaseUI;
					if (_showPurchaseUI)
					{
						_previousLockState = Cursor.lockState;
						_previousCursorVisible = Cursor.visible;
						Cursor.lockState = (CursorLockMode)0;
						Cursor.visible = true;
					}
					else
					{
						Cursor.lockState = _previousLockState;
						Cursor.visible = _previousCursorVisible;
					}
				}
				else if ((Object)(object)_nearbyDealership == (Object)null)
				{
					MelonLogger.Msg("[TunedSupercar] You need to be near the dealership to purchase the Supercar!");
				}
			}
			if (_showPurchaseUI)
			{
				if ((int)Cursor.lockState > 0)
				{
					Cursor.lockState = (CursorLockMode)0;
				}
				if (!Cursor.visible)
				{
					Cursor.visible = true;
				}
			}
			if (_showPurchaseUI && (Object)(object)_nearbyDealership == (Object)null)
			{
				CloseUI();
			}
		}

		private void CloseUI()
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			_showPurchaseUI = false;
			Cursor.lockState = _previousLockState;
			Cursor.visible = _previousCursorVisible;
		}

		private void CheckForNearbyDealership()
		{
			//IL_0034: 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_0039: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			_nearbyDealership = null;
			Dealership[] array = Object.FindObjectsOfType<Dealership>();
			if (array == null || array.Length == 0)
			{
				return;
			}
			Camera main = Camera.main;
			Vector3 val = ((main != null) ? ((Component)main).transform.position : Vector3.zero);
			Dealership[] array2 = array;
			foreach (Dealership val2 in array2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					float num = Vector3.Distance(val, ((Component)val2).transform.position);
					if (num < 30f)
					{
						_nearbyDealership = val2;
						break;
					}
				}
			}
		}

		public override void OnGUI()
		{
			//IL_004d: 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_0068: Expected O, but got Unknown
			//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)
			if (_showPurchaseUI)
			{
				GUI.skin.window.fontSize = 16;
				GUI.skin.label.fontSize = 14;
				GUI.skin.button.fontSize = 14;
				_windowRect = GUI.Window(54321, _windowRect, new WindowFunction(DrawPurchaseWindow), "Purchase Supercar");
			}
		}

		private void DrawPurchaseWindow(int windowId)
		{
			//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_0019: 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_002a: Expected O, but got Unknown
			//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_0043: Expected O, but got Unknown
			//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_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: 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_0271: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = new GUIStyle(GUI.skin.label)
			{
				fontSize = 20,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)4
			};
			GUIStyle val2 = new GUIStyle(GUI.skin.label)
			{
				fontSize = 16
			};
			GUIStyle val3 = new GUIStyle(GUI.skin.button)
			{
				fontSize = 16,
				fontStyle = (FontStyle)1
			};
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Space(15f);
			GUILayout.Label("SUPERCAR - $100,000", val, Array.Empty<GUILayoutOption>());
			GUILayout.Space(15f);
			GUILayout.Label("• 40% faster top speed & acceleration", val2, Array.Empty<GUILayoutOption>());
			GUILayout.Label("• Enhanced handling & grip", val2, Array.Empty<GUILayoutOption>());
			GUILayout.Label("• Bright purple color", val2, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			float num = 0f;
			float num2 = 0f;
			if (NetworkSingleton<MoneyManager>.InstanceExists)
			{
				num = NetworkSingleton<MoneyManager>.Instance.cashBalance;
				num2 = NetworkSingleton<MoneyManager>.Instance.onlineBalance;
			}
			GUILayout.Label($"Your Cash: ${num:N0}  |  Online: ${num2:N0}", val2, Array.Empty<GUILayoutOption>());
			GUILayout.Space(20f);
			bool flag2 = (GUI.enabled = num >= 100000f);
			GUI.backgroundColor = (flag2 ? Color.green : Color.gray);
			if (GUILayout.Button($"BUY WITH CASH (${100000f:N0})", val3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) }))
			{
				PurchaseWithCash();
			}
			GUILayout.Space(10f);
			bool flag4 = (GUI.enabled = num2 >= 100000f);
			GUI.backgroundColor = (flag4 ? Color.cyan : Color.gray);
			if (GUILayout.Button($"BUY ONLINE (${100000f:N0})", val3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(50f) }))
			{
				PurchaseOnline();
			}
			GUILayout.Space(15f);
			GUI.enabled = true;
			GUI.backgroundColor = Color.white;
			if (GUILayout.Button("CANCEL", val3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(40f) }))
			{
				CloseUI();
			}
			GUILayout.EndVertical();
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 30f));
		}

		private void PurchaseWithCash()
		{
			if (NetworkSingleton<MoneyManager>.InstanceExists && !((Object)(object)_nearbyDealership == (Object)null))
			{
				MoneyManager instance = NetworkSingleton<MoneyManager>.Instance;
				if (instance.cashBalance >= 100000f)
				{
					instance.ChangeCashBalance(-100000f, true, false);
					instance.PlayCashSound();
					SpawnSupercar();
					CloseUI();
					MelonLogger.Msg("[TunedSupercar] Purchased Supercar with cash!");
				}
			}
		}

		private void PurchaseOnline()
		{
			if (NetworkSingleton<MoneyManager>.InstanceExists && !((Object)(object)_nearbyDealership == (Object)null))
			{
				MoneyManager instance = NetworkSingleton<MoneyManager>.Instance;
				if (instance.onlineBalance >= 100000f)
				{
					instance.CreateOnlineTransaction("Supercar purchase", -100000f, 1f, string.Empty);
					instance.PlayCashSound();
					SpawnSupercar();
					CloseUI();
					MelonLogger.Msg("[TunedSupercar] Purchased Supercar online!");
				}
			}
		}

		private void SpawnSupercar()
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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)
			if (!((Object)(object)_nearbyDealership == (Object)null) && NetworkSingleton<VehicleManager>.InstanceExists)
			{
				if (_nearbyDealership.SpawnPoints != null && _nearbyDealership.SpawnPoints.Length != 0)
				{
					Transform val = _nearbyDealership.SpawnPoints[Random.Range(0, _nearbyDealership.SpawnPoints.Length)];
					NetworkSingleton<VehicleManager>.Instance.SpawnVehicle("supercar", val.position, val.rotation, true);
					MelonLogger.Msg("[TunedSupercar] Spawned at designated spawn point");
				}
				else
				{
					MelonLogger.Warning("[TunedSupercar] No spawn points found, using dealership position");
					NetworkSingleton<VehicleManager>.Instance.SpawnVehicle("supercar", ((Component)_nearbyDealership).transform.position, ((Component)_nearbyDealership).transform.rotation, true);
				}
			}
		}

		private void TryAddSupercar()
		{
			try
			{
				VehicleManager instance = NetworkSingleton<VehicleManager>.Instance;
				if ((Object)(object)instance == (Object)null || instance.VehiclePrefabs == null || instance.VehiclePrefabs.Count == 0)
				{
					return;
				}
				if (instance.VehiclePrefabs.Any((LandVehicle v) => (Object)(object)v != (Object)null && v.VehicleCode.ToLower() == "supercar"))
				{
					_vehicleAdded = true;
					MelonLogger.Msg("[TunedSupercar] Supercar already registered.");
					return;
				}
				LandVehicle val = null;
				val = ((IEnumerable<LandVehicle>)instance.VehiclePrefabs).FirstOrDefault((Func<LandVehicle, bool>)((LandVehicle v) => (Object)(object)v != (Object)null && v.VehicleCode.ToLower().Contains("cheetah")));
				if ((Object)(object)val == (Object)null)
				{
					float num = 0f;
					foreach (LandVehicle vehiclePrefab in instance.VehiclePrefabs)
					{
						if ((Object)(object)vehiclePrefab != (Object)null && vehiclePrefab.TopSpeed > num)
						{
							num = vehiclePrefab.TopSpeed;
							val = vehiclePrefab;
						}
					}
				}
				if ((Object)(object)val == (Object)null)
				{
					MelonLogger.Warning("[TunedSupercar] Could not find a base vehicle!");
					return;
				}
				MelonLogger.Msg($"[TunedSupercar] Using '{val.VehicleName}' as base (TopSpeed: {val.TopSpeed}, Code: {val.VehicleCode})");
				GameObject val2 = Object.Instantiate<GameObject>(((Component)val).gameObject);
				((Object)val2).name = "Supercar_Prefab";
				val2.SetActive(false);
				Object.DontDestroyOnLoad((Object)(object)val2);
				LandVehicle component = val2.GetComponent<LandVehicle>();
				if ((Object)(object)component == (Object)null)
				{
					MelonLogger.Error("[TunedSupercar] Failed to get LandVehicle component!");
					Object.Destroy((Object)(object)val2);
					return;
				}
				ModifyVehicleProperties(component, val);
				instance.VehiclePrefabs.Add(component);
				_vehicleAdded = true;
				MelonLogger.Msg($"[TunedSupercar] Supercar registered! TopSpeed: {component.TopSpeed}, Price: ${100000f}");
				MelonLogger.Msg("[TunedSupercar] Press F8 near the dealership to purchase!");
			}
			catch (Exception ex)
			{
				MelonLogger.Error("[TunedSupercar] Error adding supercar: " + ex.Message + "\n" + ex.StackTrace);
			}
		}

		private void ModifyVehicleProperties(LandVehicle supercar, LandVehicle baseVehicle)
		{
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//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)
			Type typeFromHandle = typeof(LandVehicle);
			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			FieldInfo field = typeFromHandle.GetField("vehicleName", bindingAttr);
			if (field != null)
			{
				field.SetValue(supercar, "Supercar");
			}
			FieldInfo field2 = typeFromHandle.GetField("vehicleCode", bindingAttr);
			if (field2 != null)
			{
				field2.SetValue(supercar, "supercar");
			}
			FieldInfo field3 = typeFromHandle.GetField("vehiclePrice", bindingAttr);
			if (field3 != null)
			{
				field3.SetValue(supercar, 100000f);
			}
			supercar.TopSpeed = baseVehicle.TopSpeed * 1.4f;
			FieldInfo field4 = typeFromHandle.GetField("motorTorque", bindingAttr);
			if (field4 != null)
			{
				AnimationCurve val = (AnimationCurve)field4.GetValue(baseVehicle);
				if (val != null)
				{
					AnimationCurve val2 = new AnimationCurve();
					Keyframe[] keys = val.keys;
					for (int i = 0; i < keys.Length; i++)
					{
						Keyframe val3 = keys[i];
						val2.AddKey(((Keyframe)(ref val3)).time * 1.4f, ((Keyframe)(ref val3)).value * 1.4f);
					}
					field4.SetValue(supercar, val2);
				}
			}
			FieldInfo field5 = typeFromHandle.GetField("diffGearing", bindingAttr);
			if (field5 != null)
			{
				float num = (float)field5.GetValue(baseVehicle);
				field5.SetValue(supercar, num * 1.2f);
			}
			FieldInfo field6 = typeFromHandle.GetField("maxSteeringAngle", bindingAttr);
			if (field6 != null)
			{
				float num2 = (float)field6.GetValue(baseVehicle);
				field6.SetValue(supercar, num2 * 1.3f);
			}
			FieldInfo field7 = typeFromHandle.GetField("steerRate", bindingAttr);
			if (field7 != null)
			{
				float num3 = (float)field7.GetValue(baseVehicle);
				field7.SetValue(supercar, num3 * 1.5f);
			}
			FieldInfo field8 = typeFromHandle.GetField("downforce", bindingAttr);
			if (field8 != null)
			{
				float num4 = (float)field8.GetValue(baseVehicle);
				field8.SetValue(supercar, Mathf.Min(num4 * 2f, 10f));
			}
			SetVehicleColor(supercar);
		}

		private void SetVehicleColor(LandVehicle supercar)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			VehicleColor val = ((Component)supercar).GetComponent<VehicleColor>();
			if ((Object)(object)val == (Object)null)
			{
				val = ((Component)supercar).GetComponentInChildren<VehicleColor>();
			}
			if ((Object)(object)val != (Object)null)
			{
				try
				{
					val.DefaultColor = (EVehicleColor)9;
					val.ApplyColor((EVehicleColor)9);
					MelonLogger.Msg("[TunedSupercar] Applied purple color via VehicleColor component");
					return;
				}
				catch (Exception ex)
				{
					MelonLogger.Warning("[TunedSupercar] Could not apply color via component: " + ex.Message);
					SetPurpleColorDirect(((Component)supercar).gameObject);
					return;
				}
			}
			SetPurpleColorDirect(((Component)supercar).gameObject);
		}

		private void SetPurpleColorDirect(GameObject vehicle)
		{
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			((Color)(ref val))..ctor(0.6f, 0.1f, 0.9f, 1f);
			MeshRenderer[] componentsInChildren = vehicle.GetComponentsInChildren<MeshRenderer>(true);
			MeshRenderer[] array = componentsInChildren;
			foreach (MeshRenderer val2 in array)
			{
				if (((Renderer)val2).materials == null)
				{
					continue;
				}
				Material[] materials = ((Renderer)val2).materials;
				foreach (Material val3 in materials)
				{
					if (!((Object)(object)val3 != (Object)null))
					{
						continue;
					}
					string text = ((Object)val3).name.ToLower();
					if (text.Contains("body") || text.Contains("paint") || text.Contains("car") || text.Contains("exterior"))
					{
						if (val3.HasProperty("_Color"))
						{
							val3.SetColor("_Color", val);
						}
						if (val3.HasProperty("_BaseColor"))
						{
							val3.SetColor("_BaseColor", val);
						}
					}
				}
			}
		}
	}
}