Decompiled source of WobblyLifeTrafficPlus v1.0.6

plugins/WobblyLifeTrafficPlus.dll

Decompiled 5 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HawkNetworking;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Wobbly Life Traffic Plus")]
[assembly: AssemblyDescription("Ground-compatible varied traffic and Doomsday events for Wobbly Life.")]
[assembly: AssemblyCompany("Zappyix")]
[assembly: AssemblyProduct("Wobbly Life Traffic Plus")]
[assembly: AssemblyFileVersion("1.0.6.0")]
[assembly: AssemblyVersion("1.0.6.0")]
namespace Zappyix.WobblyLife.TrafficPlus;

[BepInPlugin("zappyix.wobblylife.trafficplus", "Wobbly Life Traffic Plus", "1.0.6")]
public sealed class WobblyLifeTrafficPlusPlugin : BaseUnityPlugin
{
	public const string PluginGuid = "zappyix.wobblylife.trafficplus";

	public const string PluginName = "Wobbly Life Traffic Plus";

	public const string PluginVersion = "1.0.6";

	private const BindingFlags InstanceFields = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

	private static readonly Type TrafficManagerType = typeof(PlayerNPCNavigation).Assembly.GetType("TrafficManager");

	private static readonly FieldInfo TrafficLastUpdate = ((TrafficManagerType == null) ? null : TrafficManagerType.GetField("trafficUpdateTime", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly FieldInfo TrafficMaxVehicles = ((TrafficManagerType == null) ? null : TrafficManagerType.GetField("maxVehicles", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly FieldInfo VehicleDefaultTopSpeed = typeof(PlayerVehicleRoadMovement).GetField("defaultTopSpeedMph", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo VehicleTopSpeed = typeof(PlayerVehicleRoadMovement).GetField("topSpeedMph", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo VehiclePreSimulate = typeof(PlayerVehicleRoadMovement).GetField("onPreSimulate", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly FieldInfo VehicleRoadRage = typeof(PlayerVehicleRoadAI).GetField("bRoadRage", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly MethodInfo SpawnAi = ((TrafficManagerType == null) ? null : TrafficManagerType.GetMethod("SpawnAI", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly MethodInfo GetVehicleSpawn = ((TrafficManagerType == null) ? null : TrafficManagerType.GetMethod("GetVehicleSpawn", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly MethodInfo SpawnAiVehicle = ((TrafficManagerType == null) ? null : TrafficManagerType.GetMethod("SpawnAIVehicle", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly MethodInfo GetAvailableVehicleAi = ((TrafficManagerType == null) ? null : TrafficManagerType.GetMethod("GetAvaliableVehicleAI", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly MethodInfo MakeUnavailable = ((TrafficManagerType == null) ? null : TrafficManagerType.GetMethod("MakeUnavaliable", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly MethodInfo SetupAiVehicle = ((TrafficManagerType == null) ? null : TrafficManagerType.GetMethod("SetupAIVehicle", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));

	private static readonly FieldInfo AllVehicleDatabases = typeof(VehicleManager).GetField("allVehiclesAssetReferences", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private static readonly MethodInfo ForceInputMethod = typeof(WobblyLifeTrafficPlusPlugin).GetMethod("ForceDoomsdayInput", BindingFlags.Static | BindingFlags.NonPublic);

	private readonly Dictionary<int, uint> originalTrafficCaps = new Dictionary<int, uint>();

	private readonly Dictionary<int, float> originalVehicleSpeeds = new Dictionary<int, float>();

	private readonly Dictionary<int, float> originalVehicleDefaultSpeeds = new Dictionary<int, float>();

	private readonly Dictionary<int, bool> originalRoadRage = new Dictionary<int, bool>();

	private readonly Dictionary<int, PlayerVehicleRoadMovement> forcedMovements = new Dictionary<int, PlayerVehicleRoadMovement>();

	private readonly List<object> groundVehiclePrefabs = new List<object>();

	private readonly Queue<object> uncheckedVehiclePrefabs = new Queue<object>();

	private readonly HashSet<string> discoveredVehiclePrefabGuids = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private readonly HashSet<string> acceptedGroundVehicleGuids = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

	private Delegate forceInputDelegate;

	private ConfigEntry<float> normalSpawnMultiplier;

	private ConfigEntry<float> doomsdayVehicleSpeedMultiplier;

	private ConfigEntry<float> doomsdaySpawnMultiplier;

	private ConfigEntry<float> doomsdayDurationSeconds;

	private ConfigEntry<bool> showDoomsdayBanner;

	private ConfigEntry<float> doomsdayDelaySeconds;

	private float nextScanTime;

	private float nextTrafficSpawnTime;

	private float nextDoomsdayTime;

	private float doomsdayEndTime;

	private float bannerEndTime;

	private float nextVehicleCatalogRefreshTime;

	private bool doomsdayActive;

	private bool warnedNotHost;

	private GUIStyle bannerStyle;

	private void Awake()
	{
		normalSpawnMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Traffic", "SpawnMultiplier", 3f, "Traffic spawn frequency and capacity multiplier outside Doomsday.");
		doomsdayVehicleSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Doomsday", "VehicleSpeedMultiplier", 50f, "AI vehicle top-speed multiplier during Doomsday.");
		doomsdaySpawnMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Doomsday", "SpawnMultiplier", 100f, "Traffic spawn frequency and capacity multiplier during Doomsday.");
		doomsdayDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Doomsday", "DelaySeconds", 60f, "Fixed normal-mode delay before the next Doomsday.");
		doomsdayDurationSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Doomsday", "DurationSeconds", 60f, "How long one Doomsday lasts.");
		showDoomsdayBanner = ((BaseUnityPlugin)this).Config.Bind<bool>("Doomsday", "ShowBanner", true, "Show the red Doomsday countdown at the top of the screen.");
		if (Mathf.Approximately(doomsdayVehicleSpeedMultiplier.Value, 20f))
		{
			doomsdayVehicleSpeedMultiplier.Value = 50f;
		}
		if (Mathf.Approximately(doomsdaySpawnMultiplier.Value, 18f))
		{
			doomsdaySpawnMultiplier.Value = 100f;
		}
		ScheduleNextDoomsday();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Wobbly Life Traffic Plus 1.0.6 loaded.");
	}

	private void Update()
	{
		bool flag = IsHost();
		if (Time.unscaledTime >= nextScanTime)
		{
			nextScanTime = Time.unscaledTime + 0.5f;
			ApplyTraffic(flag);
			ApplyVehicleSpeed(flag);
		}
		if (!flag)
		{
			if (!warnedNotHost)
			{
				warnedNotHost = true;
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Traffic and Doomsday are host-controlled.");
			}
			return;
		}
		warnedNotHost = false;
		if (!doomsdayActive && Time.unscaledTime >= nextDoomsdayTime)
		{
			BeginDoomsday();
		}
		else if (doomsdayActive && Time.unscaledTime >= doomsdayEndTime)
		{
			EndDoomsday();
		}
		RunTrafficSpawner();
	}

	private static bool IsHost()
	{
		try
		{
			HawkNetworkManager defaultInstance = HawkNetworkManager.DefaultInstance;
			return (Object)(object)defaultInstance != (Object)null && defaultInstance.IsServer();
		}
		catch
		{
			return false;
		}
	}

	private void ApplyTraffic(bool isHost)
	{
		if (!isHost || TrafficMaxVehicles == null)
		{
			return;
		}
		Object[] array = FindTrafficManagers();
		float num = CurrentSpawnMultiplier();
		foreach (Object val in array)
		{
			if (!Object.op_Implicit(val))
			{
				continue;
			}
			int instanceID = val.GetInstanceID();
			if (!originalTrafficCaps.TryGetValue(instanceID, out var value))
			{
				value = (uint)TrafficMaxVehicles.GetValue(val);
				if (value == 0)
				{
					value = 5u;
				}
				originalTrafficCaps[instanceID] = value;
			}
			uint num2 = (uint)Mathf.Clamp(Mathf.RoundToInt((float)value * num), 1, 120);
			TrafficMaxVehicles.SetValue(val, num2);
		}
	}

	private void ApplyVehicleSpeed(bool isHost)
	{
		if (!isHost || VehicleTopSpeed == null || VehicleDefaultTopSpeed == null)
		{
			return;
		}
		PlayerVehicleRoadAI[] array = Object.FindObjectsOfType<PlayerVehicleRoadAI>();
		foreach (PlayerVehicleRoadAI val in array)
		{
			if (!Object.op_Implicit((Object)(object)val))
			{
				continue;
			}
			PlayerVehicleRoadMovement val2 = ((Component)val).GetComponent<PlayerVehicleRoadMovement>();
			if (!Object.op_Implicit((Object)(object)val2))
			{
				val2 = ((Component)val).GetComponentInChildren<PlayerVehicleRoadMovement>();
			}
			if (!Object.op_Implicit((Object)(object)val2))
			{
				continue;
			}
			int instanceID = ((Object)val2).GetInstanceID();
			if (!originalVehicleSpeeds.TryGetValue(instanceID, out var value))
			{
				value = (float)VehicleDefaultTopSpeed.GetValue(val2);
				if (value <= 0f)
				{
					value = (float)VehicleTopSpeed.GetValue(val2);
				}
				if (value <= 0f)
				{
					value = 100f;
				}
				originalVehicleSpeeds[instanceID] = value;
				originalVehicleDefaultSpeeds[instanceID] = (float)VehicleDefaultTopSpeed.GetValue(val2);
			}
			float num = (doomsdayActive ? Mathf.Max(1f, doomsdayVehicleSpeedMultiplier.Value) : 1f);
			VehicleDefaultTopSpeed.SetValue(val2, originalVehicleDefaultSpeeds[instanceID] * num);
			VehicleTopSpeed.SetValue(val2, value * num);
			int instanceID2 = ((Object)val).GetInstanceID();
			if (VehicleRoadRage != null && !originalRoadRage.ContainsKey(instanceID2))
			{
				originalRoadRage[instanceID2] = (bool)VehicleRoadRage.GetValue(val);
			}
			if (doomsdayActive && ((Behaviour)val).enabled)
			{
				if (VehicleRoadRage != null)
				{
					VehicleRoadRage.SetValue(val, true);
				}
				AttachForcedInput(val2);
			}
			else
			{
				if (VehicleRoadRage != null && originalRoadRage.TryGetValue(instanceID2, out var value2))
				{
					VehicleRoadRage.SetValue(val, value2);
				}
				DetachForcedInput(val2);
			}
		}
	}

	private void AttachForcedInput(PlayerVehicleRoadMovement movement)
	{
		if (!Object.op_Implicit((Object)(object)movement) || VehiclePreSimulate == null || ForceInputMethod == null)
		{
			return;
		}
		int instanceID = ((Object)movement).GetInstanceID();
		if (!forcedMovements.ContainsKey(instanceID))
		{
			if ((object)forceInputDelegate == null)
			{
				forceInputDelegate = Delegate.CreateDelegate(VehiclePreSimulate.FieldType, ForceInputMethod);
			}
			Delegate a = (Delegate)VehiclePreSimulate.GetValue(movement);
			VehiclePreSimulate.SetValue(movement, Delegate.Combine(a, forceInputDelegate));
			forcedMovements[instanceID] = movement;
		}
	}

	private void DetachForcedInput(PlayerVehicleRoadMovement movement)
	{
		if (Object.op_Implicit((Object)(object)movement) && !(VehiclePreSimulate == null) && (object)forceInputDelegate != null)
		{
			int instanceID = ((Object)movement).GetInstanceID();
			if (forcedMovements.ContainsKey(instanceID))
			{
				Delegate source = (Delegate)VehiclePreSimulate.GetValue(movement);
				VehiclePreSimulate.SetValue(movement, Delegate.Remove(source, forceInputDelegate));
				forcedMovements.Remove(instanceID);
			}
		}
	}

	private static void ForceDoomsdayInput(ref VehicleRoadInput input)
	{
		input.acceleration = ((input.acceleration < -0.05f) ? (-1f) : 1f);
		input.bHandbrake = false;
		input.bHorn = Time.unscaledTime % 4f < 3f;
	}

	private void RunTrafficSpawner()
	{
		if (TrafficLastUpdate == null || SpawnAi == null)
		{
			return;
		}
		float num = CurrentSpawnMultiplier();
		float num2 = 1f / Mathf.Max(1f, num);
		if (Time.unscaledTime < nextTrafficSpawnTime)
		{
			return;
		}
		nextTrafficSpawnTime = Time.unscaledTime + num2;
		Object[] array = FindTrafficManagers();
		foreach (Object val in array)
		{
			if (!Object.op_Implicit(val))
			{
				continue;
			}
			TrafficLastUpdate.SetValue(val, Time.time);
			try
			{
				if (!TrySpawnRandomVehicle(val))
				{
					SpawnAi.Invoke(val, null);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Traffic spawn failed: " + ex.GetBaseException().Message));
			}
		}
	}

	private bool TrySpawnRandomVehicle(Object trafficManager)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		if (GetVehicleSpawn == null || SpawnAiVehicle == null)
		{
			return false;
		}
		RefreshVehicleCatalog();
		if (groundVehiclePrefabs.Count == 0)
		{
			return false;
		}
		object obj = GetVehicleSpawn.Invoke(trafficManager, null);
		if (!(obj is Object) || !Object.op_Implicit((Object)obj))
		{
			return true;
		}
		object obj2 = groundVehiclePrefabs[Random.Range(0, groundVehiclePrefabs.Count)];
		if (Guid.TryParse(GetAssetGuid(obj2), out var result) && GetAvailableVehicleAi != null && MakeUnavailable != null && SetupAiVehicle != null)
		{
			object obj3 = GetAvailableVehicleAi.Invoke(trafficManager, new object[1] { result });
			if (Object.op_Implicit((Object)((obj3 is Object) ? obj3 : null)))
			{
				MakeUnavailable.Invoke(trafficManager, new object[1] { obj3 });
				SetupAiVehicle.Invoke(trafficManager, new object[2] { obj3, obj });
				return true;
			}
		}
		SpawnAiVehicle.Invoke(trafficManager, new object[2] { obj2, obj });
		return true;
	}

	private void RefreshVehicleCatalog()
	{
		if (Time.unscaledTime < nextVehicleCatalogRefreshTime)
		{
			return;
		}
		nextVehicleCatalogRefreshTime = Time.unscaledTime + 0.5f;
		Object[] array = Object.FindObjectsOfType(typeof(VehicleManager));
		if (array.Length == 0 || AllVehicleDatabases == null || !(AllVehicleDatabases.GetValue(array[0]) is IEnumerable enumerable))
		{
			return;
		}
		foreach (object item in enumerable)
		{
			if (item == null)
			{
				continue;
			}
			MethodInfo method = item.GetType().GetMethod("GetAllVehicleReferences", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			IEnumerable enumerable2 = ((method == null) ? null : (method.Invoke(item, null) as IEnumerable));
			if (enumerable2 == null)
			{
				continue;
			}
			foreach (object item2 in enumerable2)
			{
				if (item2 != null)
				{
					FieldInfo field = item2.GetType().GetField("prefab", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					object obj = ((field == null) ? null : field.GetValue(item2));
					string assetGuid = GetAssetGuid(obj);
					if (obj != null && !string.IsNullOrEmpty(assetGuid) && discoveredVehiclePrefabGuids.Add(assetGuid))
					{
						uncheckedVehiclePrefabs.Enqueue(obj);
					}
				}
			}
		}
		int num = 4;
		while (num-- > 0 && uncheckedVehiclePrefabs.Count > 0)
		{
			object obj2 = uncheckedVehiclePrefabs.Dequeue();
			GameObject val = LoadVehiclePrefab(obj2);
			if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.GetComponentInChildren<PlayerVehicleRoadMovement>(true)))
			{
				string assetGuid2 = GetAssetGuid(obj2);
				if (!string.IsNullOrEmpty(assetGuid2) && acceptedGroundVehicleGuids.Add(assetGuid2))
				{
					groundVehiclePrefabs.Add(obj2);
				}
			}
		}
		if (groundVehiclePrefabs.Count > 0)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Ground-compatible traffic catalogue: " + groundVehiclePrefabs.Count + " vehicles."));
		}
	}

	private GameObject LoadVehiclePrefab(object assetReference)
	{
		if (assetReference == null)
		{
			return null;
		}
		try
		{
			PropertyInfo property = assetReference.GetType().GetProperty("Asset", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			GameObject val = (GameObject)((property == null) ? null : /*isinst with value type is only supported in some contexts*/);
			if (Object.op_Implicit((Object)(object)val))
			{
				return val;
			}
			MethodInfo methodInfo = null;
			MethodInfo[] methods = assetReference.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			for (int i = 0; i < methods.Length; i++)
			{
				if (methods[i].Name == "LoadAssetAsync" && methods[i].IsGenericMethodDefinition && methods[i].GetParameters().Length == 0)
				{
					methodInfo = methods[i];
					break;
				}
			}
			if (methodInfo == null)
			{
				return null;
			}
			object obj = methodInfo.MakeGenericMethod(typeof(GameObject)).Invoke(assetReference, null);
			if (obj == null)
			{
				return null;
			}
			MethodInfo method = obj.GetType().GetMethod("WaitForCompletion", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			return (GameObject)((method == null) ? null : /*isinst with value type is only supported in some contexts*/);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Skipped unreadable vehicle prefab: " + ex.GetBaseException().Message));
			return null;
		}
	}

	private static string GetAssetGuid(object prefab)
	{
		if (prefab == null)
		{
			return null;
		}
		PropertyInfo property = prefab.GetType().GetProperty("AssetGUID", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		if (!(property == null))
		{
			return property.GetValue(prefab, null) as string;
		}
		return null;
	}

	private float CurrentSpawnMultiplier()
	{
		if (!doomsdayActive)
		{
			return Mathf.Max(1f, normalSpawnMultiplier.Value);
		}
		return Mathf.Max(1f, doomsdaySpawnMultiplier.Value);
	}

	private void BeginDoomsday()
	{
		doomsdayActive = true;
		doomsdayEndTime = Time.unscaledTime + Mathf.Max(5f, doomsdayDurationSeconds.Value);
		bannerEndTime = Time.unscaledTime + 5f;
		nextTrafficSpawnTime = 0f;
		((BaseUnityPlugin)this).Logger.LogWarning((object)("DOOMSDAY STARTED: traffic x" + CurrentSpawnMultiplier().ToString("0.#") + ", vehicle speed x" + doomsdayVehicleSpeedMultiplier.Value.ToString("0.#")));
	}

	private void EndDoomsday()
	{
		doomsdayActive = false;
		nextTrafficSpawnTime = 0f;
		ScheduleNextDoomsday();
		ApplyTraffic(isHost: true);
		ApplyVehicleSpeed(isHost: true);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Doomsday ended. Normal traffic restored.");
	}

	private void ScheduleNextDoomsday()
	{
		nextDoomsdayTime = Time.unscaledTime + Mathf.Max(1f, (doomsdayDelaySeconds == null) ? 60f : doomsdayDelaySeconds.Value);
	}

	private void OnGUI()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_0033: Expected O, but got Unknown
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		if (showDoomsdayBanner.Value && doomsdayActive)
		{
			if (bannerStyle == null)
			{
				bannerStyle = new GUIStyle(GUI.skin.label);
				bannerStyle.alignment = (TextAnchor)4;
				bannerStyle.fontSize = 28;
				bannerStyle.fontStyle = (FontStyle)1;
				bannerStyle.normal.textColor = Color.red;
			}
			float num = Mathf.Max(0f, doomsdayEndTime - Time.unscaledTime);
			string text = ((Time.unscaledTime < bannerEndTime) ? "DOOMSDAY!  " : "");
			GUI.Label(new Rect(0f, 18f, (float)Screen.width, 42f), text + Mathf.CeilToInt(num) + "s", bannerStyle);
		}
	}

	private void OnDestroy()
	{
		RestoreAllValues();
	}

	private void RestoreAllValues()
	{
		Object[] array = FindTrafficManagers();
		for (int i = 0; i < array.Length; i++)
		{
			if (Object.op_Implicit(array[i]) && originalTrafficCaps.TryGetValue(array[i].GetInstanceID(), out var value) && TrafficMaxVehicles != null)
			{
				TrafficMaxVehicles.SetValue(array[i], value);
			}
		}
		PlayerVehicleRoadMovement[] array2 = Object.FindObjectsOfType<PlayerVehicleRoadMovement>();
		for (int j = 0; j < array2.Length; j++)
		{
			if (Object.op_Implicit((Object)(object)array2[j]) && originalVehicleSpeeds.TryGetValue(((Object)array2[j]).GetInstanceID(), out var value2) && VehicleTopSpeed != null)
			{
				VehicleTopSpeed.SetValue(array2[j], value2);
			}
			if (Object.op_Implicit((Object)(object)array2[j]) && originalVehicleDefaultSpeeds.TryGetValue(((Object)array2[j]).GetInstanceID(), out var value3) && VehicleDefaultTopSpeed != null)
			{
				VehicleDefaultTopSpeed.SetValue(array2[j], value3);
			}
			DetachForcedInput(array2[j]);
		}
		PlayerVehicleRoadAI[] array3 = Object.FindObjectsOfType<PlayerVehicleRoadAI>();
		for (int k = 0; k < array3.Length; k++)
		{
			if (Object.op_Implicit((Object)(object)array3[k]) && VehicleRoadRage != null && originalRoadRage.TryGetValue(((Object)array3[k]).GetInstanceID(), out var value4))
			{
				VehicleRoadRage.SetValue(array3[k], value4);
			}
		}
	}

	private static Object[] FindTrafficManagers()
	{
		if (!(TrafficManagerType == null))
		{
			return Object.FindObjectsOfType(TrafficManagerType);
		}
		return (Object[])(object)new Object[0];
	}
}