Decompiled source of Repo Optimization v1.0.1

RepoOptimization.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace RepoOptimization;

[BepInPlugin("RepoOptimization", "Repo Optimization", "1.0.1")]
public class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "RepoOptimization";

	public const string PluginName = "Repo Optimization";

	public const string PluginVersion = "1.0.1";

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> ModEnabled;

	internal static ConfigEntry<string> TargetNames;

	internal static ConfigEntry<int> LowestLevel;

	private static string[] _targets = new string[0];

	[ThreadStatic]
	private static bool _busy;

	private Harmony _harmony;

	private void Awake()
	{
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn the reversed upgrades on or off.");
		TargetNames = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TargetPlayerNames", "SofieLoafy", "Comma-separated player names whose upgrades are reversed (not case-sensitive).");
		LowestLevel = ((BaseUnityPlugin)this).Config.Bind<int>("General", "LowestUpgradeLevel", -3, "How far below zero an upgrade level can go. Lower = harsher. Very low values (e.g. -5 health or stamina) can leave a stat at zero.");
		RefreshTargets();
		TargetNames.SettingChanged += delegate
		{
			RefreshTargets();
		};
		_harmony = new Harmony("RepoOptimization");
		PatchUpgradeMethods();
		Pranks.Init(((BaseUnityPlugin)this).Config, _harmony);
	}

	private static void RefreshTargets()
	{
		_targets = (from n in (TargetNames.Value ?? string.Empty).Split(',')
			select n.Trim() into n
			where n.Length > 0
			select n).ToArray();
	}

	private void PatchUpgradeMethods()
	{
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("PunManager");
		if (type == null)
		{
			Log.LogError((object)"Couldn't find PunManager. The game may have updated; nothing was patched.");
			return;
		}
		HarmonyMethod val = new HarmonyMethod(typeof(Plugin).GetMethod("UpgradePrefix", BindingFlags.Static | BindingFlags.NonPublic));
		int num = 0;
		foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(type))
		{
			if (!declaredMethod.Name.StartsWith("Upgrade") || declaredMethod.Name.EndsWith("RPC"))
			{
				continue;
			}
			ParameterInfo[] parameters = declaredMethod.GetParameters();
			if (parameters.Length == 2 && !(parameters[0].ParameterType != typeof(string)) && !(parameters[1].ParameterType != typeof(int)) && !(declaredMethod.ReturnType != typeof(int)))
			{
				try
				{
					_harmony.Patch((MethodBase)declaredMethod, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Reversing: PunManager." + declaredMethod.Name));
					num++;
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Couldn't patch " + declaredMethod.Name + ": " + ex.Message));
				}
			}
		}
		if (num == 0)
		{
			Log.LogWarning((object)"No upgrade methods matched. The game may have changed how upgrades work.");
		}
		else
		{
			Log.LogInfo((object)("Repo Optimization loaded. Patched " + num + " upgrade types."));
		}
	}

	private static bool UpgradePrefix(object __instance, MethodBase __originalMethod, object[] __args, ref int __result)
	{
		if (_busy || !ModEnabled.Value || __args == null || __args.Length < 2)
		{
			return true;
		}
		string text = __args[0] as string;
		if (!(__args[1] is int))
		{
			return true;
		}
		int num = (int)__args[1];
		if (num <= 0 || !IsTargetPlayer(text))
		{
			return true;
		}
		_busy = true;
		try
		{
			int num2 = (int)__originalMethod.Invoke(__instance, new object[2]
			{
				text,
				-num
			});
			int value = LowestLevel.Value;
			if (num2 < value)
			{
				num2 = (int)__originalMethod.Invoke(__instance, new object[2]
				{
					text,
					value - num2
				});
			}
			__result = num2;
			Log.LogInfo((object)(__originalMethod.Name + " reversed for " + text + " -> level " + num2));
			return false;
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Reverse failed, letting the normal upgrade through: " + ex));
			return true;
		}
		finally
		{
			_busy = false;
		}
	}

	private static bool IsTargetPlayer(string steamId)
	{
		if (string.IsNullOrEmpty(steamId) || _targets.Length == 0)
		{
			return false;
		}
		return NameIsTarget(GetPlayerName(steamId));
	}

	internal static bool NameIsTarget(string name)
	{
		if (string.IsNullOrEmpty(name) || _targets.Length == 0)
		{
			return false;
		}
		name = name.Trim();
		return _targets.Any((string t) => string.Equals(t, name, StringComparison.OrdinalIgnoreCase));
	}

	private static string GetPlayerName(string steamId)
	{
		Type type = AccessTools.TypeByName("SemiFunc");
		if (type == null)
		{
			return null;
		}
		object obj = null;
		MethodInfo methodInfo = AccessTools.Method(type, "PlayerAvatarGetFromSteamID", new Type[1] { typeof(string) }, (Type[])null);
		if (methodInfo != null)
		{
			obj = methodInfo.Invoke(null, new object[1] { steamId });
		}
		if (IsMissing(obj))
		{
			obj = null;
			if (AccessTools.Method(type, "PlayerGetAll", (Type[])null, (Type[])null)?.Invoke(null, null) is IEnumerable enumerable)
			{
				foreach (object item in enumerable)
				{
					if (!IsMissing(item) && GetSteamId(type, item) == steamId)
					{
						obj = item;
						break;
					}
				}
			}
		}
		return AvatarName(obj);
	}

	internal static string AvatarName(object avatar)
	{
		if (IsMissing(avatar))
		{
			return null;
		}
		Type type = AccessTools.TypeByName("SemiFunc");
		string text = Traverse.Create(avatar).Field("playerName").GetValue() as string;
		if (string.IsNullOrEmpty(text) && type != null)
		{
			MethodInfo methodInfo = AccessTools.Method(type, "PlayerGetName", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				text = methodInfo.Invoke(null, new object[1] { avatar }) as string;
			}
		}
		return text;
	}

	private static string GetSteamId(Type semiFunc, object avatar)
	{
		MethodInfo methodInfo = AccessTools.Method(semiFunc, "PlayerGetSteamID", (Type[])null, (Type[])null);
		if (methodInfo != null)
		{
			return methodInfo.Invoke(null, new object[1] { avatar }) as string;
		}
		return Traverse.Create(avatar).Field("steamID").GetValue() as string;
	}

	internal static bool IsMissing(object obj)
	{
		if (obj == null)
		{
			return true;
		}
		Object val = (Object)((obj is Object) ? obj : null);
		return val != (Object)null && val == (Object)null;
	}
}
internal class Pranks : MonoBehaviour
{
	private static ConfigEntry<bool> _butterOn;

	private static ConfigEntry<bool> _drunkOn;

	private static ConfigEntry<bool> _tumbleOn;

	private static ConfigEntry<bool> _staminaOn;

	private static ConfigEntry<bool> _ghostOn;

	private static ConfigEntry<bool> _mapOn;

	private static ConfigEntry<bool> _mapDecoys;

	private static ConfigEntry<float> _butterAvg;

	private static ConfigEntry<float> _drunkAvg;

	private static ConfigEntry<float> _drunkLength;

	private static ConfigEntry<float> _driftStrength;

	private static ConfigEntry<float> _tumbleAvg;

	private static ConfigEntry<float> _drainMult;

	private static ConfigEntry<float> _regenMult;

	private static ConfigEntry<float> _ghostAvg;

	private static ConfigEntry<float> _ghostVolume;

	private static ConfigEntry<float> _mapHideChance;

	internal static bool ControlsSwapped;

	private static Type _semiFunc;

	private static Type _playerAvatar;

	private static Type _playerController;

	private static Type _physGrabber;

	private static Type _mapValuable;

	private object _avatar;

	private bool _isTarget;

	private bool _inLevel;

	private float _checkTimer;

	private float _drunkTimer;

	private float _tumbleEndTimer;

	private float _mapTimer;

	private float _ghostScanTimer;

	private float _lastEnergy = -1f;

	private object _tumblingObject;

	private List<AudioClip> _ghostClips = new List<AudioClip>();

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

	private readonly List<GameObject> _decoys = new List<GameObject>();

	private static readonly string[] GhostWords = new string[13]
	{
		"footstep", "step", "growl", "scream", "breath", "whisper", "monster", "enemy", "creak", "knock",
		"door", "groan", "laugh"
	};

	private readonly HashSet<string> _broken = new HashSet<string>();

	public static void Init(ConfigFile cfg, Harmony harmony)
	{
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024f: Expected O, but got Unknown
		_butterOn = cfg.Bind<bool>("1. Butterfingers", "Enabled", true, "Randomly drop whatever is being held.");
		_butterAvg = cfg.Bind<float>("1. Butterfingers", "AverageSecondsBetweenDrops", 45f, "Average seconds of holding something before it slips.");
		_drunkOn = cfg.Bind<bool>("4. Drunk Walk", "Enabled", true, "Left/right controls swap now and then, with a sideways drift.");
		_drunkAvg = cfg.Bind<float>("4. Drunk Walk", "AverageSecondsBetweenSpells", 120f, "Average seconds between drunk spells.");
		_drunkLength = cfg.Bind<float>("4. Drunk Walk", "SpellLengthSeconds", 8f, "How long each drunk spell lasts.");
		_driftStrength = cfg.Bind<float>("4. Drunk Walk", "DriftStrength", 4f, "How hard the sideways drift pushes. 0 = no drift.");
		_tumbleOn = cfg.Bind<bool>("5. Random Tumbles", "Enabled", true, "Trip into a tumble for no reason.");
		_tumbleAvg = cfg.Bind<float>("5. Random Tumbles", "AverageSecondsBetweenTrips", 180f, "Average seconds between trips.");
		_staminaOn = cfg.Bind<bool>("6. Shrinking Stamina", "Enabled", true, "Stamina drains faster and refills slower.");
		_drainMult = cfg.Bind<float>("6. Shrinking Stamina", "DrainMultiplier", 1.4f, "1.4 = stamina drains 40% faster.");
		_regenMult = cfg.Bind<float>("6. Shrinking Stamina", "RegenMultiplier", 0.6f, "0.6 = stamina refills at 60% speed.");
		_ghostOn = cfg.Bind<bool>("11. Ghost Sounds", "Enabled", true, "Play creepy game sounds behind the player. Only they hear them.");
		_ghostAvg = cfg.Bind<float>("11. Ghost Sounds", "AverageSecondsBetweenSounds", 75f, "Average seconds between ghost sounds.");
		_ghostVolume = cfg.Bind<float>("11. Ghost Sounds", "Volume", 0.8f, "0 to 1.");
		_mapOn = cfg.Bind<bool>("13. Map Lies", "Enabled", true, "Hide some valuables from the map.");
		_mapHideChance = cfg.Bind<float>("13. Map Lies", "HideChance", 0.4f, "Chance (0 to 1) that each valuable is hidden from the map.");
		_mapDecoys = cfg.Bind<bool>("13. Map Lies", "FakeMarkers", true, "Put a fake marker in the wrong spot for each hidden one.");
		_semiFunc = AccessTools.TypeByName("SemiFunc");
		_playerAvatar = AccessTools.TypeByName("PlayerAvatar");
		_playerController = AccessTools.TypeByName("PlayerController");
		_physGrabber = AccessTools.TypeByName("PhysGrabber");
		_mapValuable = AccessTools.TypeByName("MapValuable");
		PatchMovementInput(harmony);
		GameObject val = new GameObject("RepoOptimization.Pranks");
		((Object)val).hideFlags = (HideFlags)61;
		Object.DontDestroyOnLoad((Object)(object)val);
		val.AddComponent<Pranks>();
	}

	private void Update()
	{
		float dt = Time.deltaTime;
		_checkTimer -= dt;
		if (_checkTimer <= 0f)
		{
			_checkTimer = 1f;
			_avatar = GetLocalAvatar();
			_isTarget = Plugin.ModEnabled.Value && Plugin.NameIsTarget(Plugin.AvatarName(_avatar));
			_inLevel = IsInLevel();
		}
		if (!_isTarget || !_inLevel)
		{
			ControlsSwapped = false;
			_lastEnergy = -1f;
			return;
		}
		Safe("Butterfingers", delegate
		{
			if (_butterOn.Value)
			{
				Butterfingers();
			}
		});
		Safe("Drunk walk", delegate
		{
			DrunkWalk(dt);
		});
		Safe("Random tumbles", delegate
		{
			RandomTumbles(dt);
		});
		Safe("Ghost sounds", delegate
		{
			if (_ghostOn.Value)
			{
				GhostSounds(dt);
			}
		});
		Safe("Map lies", delegate
		{
			if (_mapOn.Value)
			{
				MapLies(dt);
			}
		});
	}

	private void LateUpdate()
	{
		if (!_isTarget || !_inLevel)
		{
			return;
		}
		Safe("Shrinking stamina", delegate
		{
			if (_staminaOn.Value)
			{
				ShrinkingStamina();
			}
			else
			{
				_lastEnergy = -1f;
			}
		});
	}

	private void FixedUpdate()
	{
		if (!_isTarget || !_inLevel || !ControlsSwapped || _driftStrength.Value <= 0f)
		{
			return;
		}
		Safe("Drunk drift", delegate
		{
			//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_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_007a: Unknown result type (might be due to invalid IL or missing references)
			object field = GetField(StaticInstance(_playerController), "rb");
			Rigidbody val = (Rigidbody)((field is Rigidbody) ? field : null);
			Camera main = Camera.main;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)main == (Object)null))
			{
				Vector3 right = ((Component)main).transform.right;
				right.y = 0f;
				float num = Mathf.Sin(Time.time * 1.3f);
				val.AddForce(((Vector3)(ref right)).normalized * num * _driftStrength.Value, (ForceMode)5);
			}
		});
	}

	private void Butterfingers()
	{
		object obj = StaticInstance(_physGrabber);
		if (Plugin.IsMissing(obj))
		{
			return;
		}
		object field = GetField(obj, "grabbed");
		if (field is bool && (bool)field && Roll(_butterAvg.Value))
		{
			MethodInfo methodInfo = AccessTools.GetDeclaredMethods(_physGrabber).FirstOrDefault((MethodInfo m) => m.Name == "ReleaseObject");
			if (methodInfo != null)
			{
				methodInfo.Invoke(obj, DefaultArgs(methodInfo));
			}
		}
	}

	private void DrunkWalk(float dt)
	{
		if (!_drunkOn.Value)
		{
			ControlsSwapped = false;
		}
		else if (ControlsSwapped)
		{
			_drunkTimer -= dt;
			if (_drunkTimer <= 0f)
			{
				ControlsSwapped = false;
			}
		}
		else if (Roll(_drunkAvg.Value))
		{
			ControlsSwapped = true;
			_drunkTimer = _drunkLength.Value;
		}
	}

	private static void PatchMovementInput(Harmony harmony)
	{
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Expected O, but got Unknown
		Type type = AccessTools.TypeByName("InputManager");
		List<MethodInfo> list = new List<MethodInfo>();
		if (type != null)
		{
			list.Add(AccessTools.Method(type, "GetMovementX", (Type[])null, (Type[])null));
			list.Add(AccessTools.Method(type, "GetMovement", (Type[])null, (Type[])null));
		}
		if (_semiFunc != null)
		{
			list.Add(AccessTools.Method(_semiFunc, "InputMovementX", (Type[])null, (Type[])null));
		}
		foreach (MethodInfo item in list)
		{
			if (item == null)
			{
				continue;
			}
			string text = ((item.ReturnType == typeof(float)) ? "FlipFloat" : ((!(item.ReturnType == typeof(Vector2))) ? null : "FlipVector2"));
			if (text != null)
			{
				try
				{
					MethodInfo methodInfo = item;
					HarmonyMethod val = new HarmonyMethod(typeof(Pranks).GetMethod(text, BindingFlags.Static | BindingFlags.NonPublic));
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("Drunk walk hooked into " + item.DeclaringType.Name + "." + item.Name));
					return;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Couldn't hook " + item.Name + ": " + ex.Message));
				}
			}
		}
		Plugin.Log.LogWarning((object)"Drunk walk: no movement input found to swap, so only the drift will happen.");
	}

	private static void FlipFloat(ref float __result)
	{
		if (ControlsSwapped)
		{
			__result = 0f - __result;
		}
	}

	private static void FlipVector2(ref Vector2 __result)
	{
		if (ControlsSwapped)
		{
			__result.x = 0f - __result.x;
		}
	}

	private void RandomTumbles(float dt)
	{
		if (_tumblingObject != null)
		{
			_tumbleEndTimer -= dt;
			if (_tumbleEndTimer <= 0f)
			{
				InvokeTumble(_tumblingObject, start: false);
				_tumblingObject = null;
			}
		}
		else
		{
			if (!_tumbleOn.Value || !Roll(_tumbleAvg.Value))
			{
				return;
			}
			object field = GetField(_avatar, "tumble");
			if (!Plugin.IsMissing(field))
			{
				object field2 = GetField(field, "isTumbling");
				if ((!(field2 is bool) || !(bool)field2) && InvokeTumble(field, start: true))
				{
					_tumblingObject = field;
					_tumbleEndTimer = Random.Range(1.5f, 3f);
				}
			}
		}
	}

	private static bool InvokeTumble(object tumble, bool start)
	{
		MethodInfo methodInfo = AccessTools.GetDeclaredMethods(tumble.GetType()).FirstOrDefault((MethodInfo m) => m.Name == "TumbleRequest");
		if (methodInfo == null)
		{
			return false;
		}
		object[] array = DefaultArgs(methodInfo);
		if (array.Length > 0 && array[0] is bool)
		{
			array[0] = start;
		}
		if (array.Length > 1 && array[1] is bool)
		{
			array[1] = false;
		}
		methodInfo.Invoke(tumble, array);
		return true;
	}

	private void ShrinkingStamina()
	{
		object obj = StaticInstance(_playerController);
		FieldInfo fieldInfo = ((!(_playerController != null)) ? null : AccessTools.Field(_playerController, "EnergyCurrent"));
		if (Plugin.IsMissing(obj) || fieldInfo == null || fieldInfo.FieldType != typeof(float))
		{
			return;
		}
		float num = (float)fieldInfo.GetValue(obj);
		if (_lastEnergy >= 0f)
		{
			float num2 = num - _lastEnergy;
			if (num2 > 0f && num2 < 20f)
			{
				num = _lastEnergy + num2 * _regenMult.Value;
			}
			else if (num2 < 0f)
			{
				num = Mathf.Max(0f, _lastEnergy + num2 * _drainMult.Value);
			}
			fieldInfo.SetValue(obj, num);
		}
		_lastEnergy = num;
	}

	private void GhostSounds(float dt)
	{
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: 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_0153: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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)
		_ghostScanTimer -= dt;
		if (_ghostClips.Count == 0 && _ghostScanTimer <= 0f)
		{
			_ghostScanTimer = 30f;
			_ghostClips = (from c in Resources.FindObjectsOfTypeAll<AudioClip>()
				where (Object)(object)c != (Object)null && c.length > 0.2f && c.length < 8f && GhostWords.Any((string w) => ((Object)c).name.IndexOf(w, StringComparison.OrdinalIgnoreCase) >= 0)
				select c).ToList();
			if (_ghostClips.Count > 0)
			{
				Plugin.Log.LogInfo((object)("Ghost sounds: found " + _ghostClips.Count + " creepy clips."));
			}
		}
		if (_ghostClips.Count == 0 || !Roll(_ghostAvg.Value))
		{
			return;
		}
		Camera main = Camera.main;
		if (!((Object)(object)main == (Object)null))
		{
			AudioClip val = _ghostClips[Random.Range(0, _ghostClips.Count)];
			if ((Object)(object)val == (Object)null)
			{
				_ghostClips.Clear();
				return;
			}
			Transform transform = ((Component)main).transform;
			Vector3 val2 = transform.position - transform.forward * Random.Range(3f, 7f) + transform.right * Random.Range(-3f, 3f);
			AudioSource.PlayClipAtPoint(val, val2, Mathf.Clamp01(_ghostVolume.Value));
		}
	}

	private void MapLies(float dt)
	{
		_mapTimer -= dt;
		if (_mapTimer > 0f || _mapValuable == null)
		{
			return;
		}
		_mapTimer = 0.3f;
		Object[] array = Object.FindObjectsOfType(_mapValuable);
		if (array.Length == 0)
		{
			_mapDecided.Clear();
			_decoys.RemoveAll((GameObject d) => (Object)(object)d == (Object)null);
			return;
		}
		List<Component> list = (from c in array.OfType<Component>()
			where (Object)(object)c != (Object)null && (Object)(object)c.GetComponentInParent<Rigidbody>() == (Object)null
			select c).ToList();
		foreach (Component item in list)
		{
			int instanceID = ((Object)item).GetInstanceID();
			if (!_mapDecided.TryGetValue(instanceID, out var value))
			{
				value = Random.value < _mapHideChance.Value;
				_mapDecided[instanceID] = value;
				if (value && _mapDecoys.Value && list.Count >= 2)
				{
					MakeDecoy(item, list);
				}
			}
			if (value)
			{
				Renderer[] componentsInChildren = item.GetComponentsInChildren<Renderer>(true);
				foreach (Renderer val in componentsInChildren)
				{
					val.enabled = false;
				}
			}
		}
	}

	private void MakeDecoy(Component marker, List<Component> all)
	{
		//IL_0085: 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_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_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: 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)
		GameObject val = Object.Instantiate<GameObject>(marker.gameObject, marker.transform.parent);
		MonoBehaviour[] componentsInChildren = val.GetComponentsInChildren<MonoBehaviour>(true);
		foreach (MonoBehaviour val2 in componentsInChildren)
		{
			Object.Destroy((Object)(object)val2);
		}
		Renderer[] componentsInChildren2 = val.GetComponentsInChildren<Renderer>(true);
		foreach (Renderer val3 in componentsInChildren2)
		{
			val3.enabled = true;
		}
		Vector3 position = all[Random.Range(0, all.Count)].transform.position;
		Vector3 position2 = all[Random.Range(0, all.Count)].transform.position;
		val.transform.position = Vector3.Lerp(position, position2, Random.Range(0.3f, 0.7f));
		_decoys.Add(val);
	}

	private static bool Roll(float avgSeconds)
	{
		if (avgSeconds <= 0f)
		{
			return false;
		}
		return Random.value < Time.deltaTime / avgSeconds;
	}

	private static object GetLocalAvatar()
	{
		if (_semiFunc != null)
		{
			MethodInfo methodInfo = AccessTools.Method(_semiFunc, "PlayerAvatarLocal", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				object obj = methodInfo.Invoke(null, null);
				if (!Plugin.IsMissing(obj))
				{
					return obj;
				}
			}
		}
		object obj2 = StaticInstance(_playerAvatar);
		return (!Plugin.IsMissing(obj2)) ? obj2 : null;
	}

	private static bool IsInLevel()
	{
		if (_semiFunc == null)
		{
			return true;
		}
		MethodInfo methodInfo = AccessTools.Method(_semiFunc, "RunIsLevel", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			return true;
		}
		object obj = methodInfo.Invoke(null, null);
		return !(obj is bool) || (bool)obj;
	}

	private static object StaticInstance(Type t)
	{
		if (t == null)
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(t, "instance") ?? AccessTools.Field(t, "Instance");
		return (!(fieldInfo != null) || !fieldInfo.IsStatic) ? null : fieldInfo.GetValue(null);
	}

	private static object GetField(object obj, string name)
	{
		if (Plugin.IsMissing(obj))
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(obj.GetType(), name);
		return (!(fieldInfo != null)) ? null : fieldInfo.GetValue(obj);
	}

	private static object[] DefaultArgs(MethodInfo m)
	{
		return (from p in m.GetParameters()
			select p.HasDefaultValue ? p.DefaultValue : ((!p.ParameterType.IsValueType) ? null : Activator.CreateInstance(p.ParameterType))).ToArray();
	}

	private void Safe(string effect, Action action)
	{
		if (_broken.Contains(effect))
		{
			return;
		}
		try
		{
			action();
		}
		catch (Exception ex)
		{
			_broken.Add(effect);
			Plugin.Log.LogWarning((object)(effect + " stopped working and was turned off: " + ex.Message));
		}
	}
}