Decompiled source of SillyValuablesFix v1.2.2

SillyValuablesFix.dll

Decompiled 2 weeks 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 BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SillyValuablesFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SillyValuablesFix")]
[assembly: AssemblyTitle("SillyValuablesFix")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially or fully created with the assistance of Generative AI (e.g., Code Suggestions, Refactoring, Documentation Generation).")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Google/Gemini")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 SillyValuablesFix
{
	[BepInPlugin("com.neko3004.sillyvaluablesfix", "SillyValuables Fix", "1.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.neko3004.sillyvaluablesfix";

		public const string PluginName = "SillyValuables Fix";

		public const string PluginVersion = "1.2.2";

		internal static ManualLogSource Log;

		private Harmony? harmony;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				harmony = new Harmony("com.neko3004.sillyvaluablesfix");
				UnpatchBrokenSillyValuablesPatches();
				SafePatch(typeof(Patch_PhotonView_Awake));
				SafePatch(typeof(Patch_PhotonView_SerializeComponent));
				SafePatch(typeof(Patch_PhotonView_DeserializeComponent));
				SafePatch(typeof(Patch_ItemMelee_Start));
				SafePatch(typeof(Patch_ItemGun_Start));
				SafePatch(typeof(Patch_GranadaJogavel_Start));
				SafePatch(typeof(Patch_GranadaJogavelSemExplosao_Start));
				Log.LogInfo((object)"SillyValuables Fix 1.2.2 loaded and patches applied successfully.");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"General error in Awake: {arg}");
			}
		}

		private void SafePatch(Type patchType)
		{
			try
			{
				Harmony? obj = harmony;
				if (obj != null)
				{
					obj.CreateClassProcessor(patchType).Patch();
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Failed to register patch '" + patchType.Name + "': " + ex.Message));
			}
		}

		private void UnpatchBrokenSillyValuablesPatches()
		{
			try
			{
				int num = 0;
				foreach (MethodBase item in Harmony.GetAllPatchedMethods().ToList())
				{
					Patches patchInfo = Harmony.GetPatchInfo(item);
					if (patchInfo == null)
					{
						continue;
					}
					foreach (Patch item2 in patchInfo.Prefixes.Concat(patchInfo.Postfixes).Concat(patchInfo.Transpilers).Concat(patchInfo.Finalizers))
					{
						if (item2.owner == null)
						{
							continue;
						}
						if (item2.owner.IndexOf("SillyValuables", StringComparison.OrdinalIgnoreCase) < 0)
						{
							Type? declaringType = item2.PatchMethod.DeclaringType;
							if ((object)declaringType == null || !(declaringType.Assembly.GetName().Name?.IndexOf("SillyValuables", StringComparison.OrdinalIgnoreCase) >= 0))
							{
								continue;
							}
						}
						if (!item2.owner.Equals("com.neko3004.sillyvaluablesfix", StringComparison.OrdinalIgnoreCase))
						{
							Harmony? obj = harmony;
							if (obj != null)
							{
								obj.Unpatch(item, item2.PatchMethod);
							}
							num++;
						}
					}
				}
				if (num > 0)
				{
					Log.LogInfo((object)$"Disabled {num} old/broken patch(es) from the original SillyValuables.");
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Could not disable old patches: " + ex.Message));
			}
		}

		private void OnDestroy()
		{
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}

		public static bool TryGetMember<T>(object? instance, string memberName, out T value)
		{
			value = default(T);
			if (instance == null)
			{
				return false;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				FieldInfo field = type.GetField(memberName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					try
					{
						if (field.GetValue(instance) is T val)
						{
							value = val;
							return true;
						}
					}
					catch (Exception ex)
					{
						Log.LogDebug((object)("Failed to read field '" + memberName + "': " + ex.Message));
					}
					return false;
				}
				PropertyInfo property = type.GetProperty(memberName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.GetMethod != null)
				{
					try
					{
						if (property.GetValue(instance) is T val2)
						{
							value = val2;
							return true;
						}
					}
					catch (Exception ex2)
					{
						Log.LogDebug((object)("Failed to read property '" + memberName + "': " + ex2.Message));
					}
					return false;
				}
				type = type.BaseType;
			}
			return false;
		}

		public static bool TrySetMember(object? instance, string memberName, object? value)
		{
			if (instance == null)
			{
				return false;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				FieldInfo field = type.GetField(memberName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					try
					{
						field.SetValue(instance, value);
						return true;
					}
					catch (Exception ex)
					{
						Log.LogDebug((object)("Failed to write field '" + memberName + "': " + ex.Message));
						return false;
					}
				}
				PropertyInfo property = type.GetProperty(memberName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.SetMethod != null)
				{
					try
					{
						property.SetValue(instance, value);
						return true;
					}
					catch (Exception ex2)
					{
						Log.LogDebug((object)("Failed to write property '" + memberName + "': " + ex2.Message));
						return false;
					}
				}
				type = type.BaseType;
			}
			return false;
		}

		public static bool CheckIsEquipped(Component? item)
		{
			bool value;
			return TryGetMember<bool>(item, "isEquipped", out value) && value;
		}
	}
	[HarmonyPatch(typeof(PhotonView), "Awake")]
	internal static class Patch_PhotonView_Awake
	{
		private static readonly HashSet<string> loggedCleanups = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static void Prefix(PhotonView __instance)
		{
			CleanObserved(__instance);
		}

		private static void Postfix(PhotonView __instance)
		{
			CleanObserved(__instance);
		}

		public static void CleanObserved(PhotonView view)
		{
			if ((Object)(object)view == (Object)null || view.ObservedComponents == null || view.ObservedComponents.Count == 0)
			{
				return;
			}
			List<Component> list = view.ObservedComponents.Where((Component comp) => (Object)(object)comp == (Object)null || !(comp is IPunObservable)).ToList();
			if (list.Count <= 0)
			{
				return;
			}
			string text = (((Object)(object)((Component)view).gameObject != (Object)null) ? ((Object)((Component)view).gameObject).name : "Unknown Object").Replace("(Clone)", "").Trim();
			if (loggedCleanups.Add(text))
			{
				string text2 = string.Join(", ", list.Select((Component c) => (!((Object)(object)c == (Object)null)) ? ((object)c).GetType().Name : "null"));
				Plugin.Log.LogInfo((object)("[PhotonView Fix] Incompatible components removed from '" + text + "': [" + text2 + "]"));
			}
			view.ObservedComponents.RemoveAll((Component comp) => (Object)(object)comp == (Object)null || !(comp is IPunObservable));
		}
	}
	[HarmonyPatch(typeof(PhotonView), "SerializeComponent")]
	internal static class Patch_PhotonView_SerializeComponent
	{
		private static bool Prefix(Component component)
		{
			if ((Object)(object)component == (Object)null || !(component is IPunObservable))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(PhotonView), "DeserializeComponent")]
	internal static class Patch_PhotonView_DeserializeComponent
	{
		private static bool Prefix(Component component)
		{
			if ((Object)(object)component == (Object)null || !(component is IPunObservable))
			{
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ItemMelee), "Start")]
	internal static class Patch_ItemMelee_Start
	{
		private static void Postfix(ItemMelee __instance)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				PhotonView component = ((Component)__instance).GetComponent<PhotonView>();
				if ((Object)(object)component != (Object)null)
				{
					Patch_PhotonView_Awake.CleanObserved(component);
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemGun), "Start")]
	internal static class Patch_ItemGun_Start
	{
		private const float DefaultDistanceKeep = 0.8f;

		private static void Postfix(ItemGun __instance)
		{
			if ((Object)(object)__instance != (Object)null && __instance.distanceKeep <= 0f)
			{
				__instance.distanceKeep = 0.8f;
			}
		}
	}
	[HarmonyPatch(typeof(GranadaJogavel), "Start")]
	internal static class Patch_GranadaJogavel_Start
	{
		private static void Postfix(GranadaJogavel __instance)
		{
			AttachFixer((MonoBehaviour)(object)__instance);
		}

		private static void AttachFixer(MonoBehaviour instance)
		{
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)((Component)instance).GetComponent<GranadaFixer>() != (Object)null))
			{
				((Component)instance).gameObject.AddComponent<GranadaFixer>().Setup(instance);
			}
		}
	}
	[HarmonyPatch(typeof(GranadaJogavelSemExplosao), "Start")]
	internal static class Patch_GranadaJogavelSemExplosao_Start
	{
		private static void Postfix(GranadaJogavelSemExplosao __instance)
		{
			if (!((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<GranadaFixer>() != (Object)null))
			{
				((Component)__instance).gameObject.AddComponent<GranadaFixer>().Setup((MonoBehaviour)(object)__instance);
			}
		}
	}
	internal sealed class GranadaFixer : MonoBehaviour
	{
		private MonoBehaviour? grenade;

		private AudioSource? replacementAudioSource;

		private GameObject? replacementAudioObject;

		private static AudioClip? cachedMineClip;

		private static bool searchedForClip;

		private float tickAudioTimer;

		private bool lastActive;

		private bool initialized;

		private bool shuttingDown;

		private const float MinePitch = 1.2f;

		private const float TickInterval = 0.35f;

		private const float AudioVolume = 0.95f;

		private const float AudioMinDistance = 4f;

		private const float AudioMaxDistance = 45f;

		public void Setup(MonoBehaviour original)
		{
			if (!initialized && !((Object)(object)original == (Object)null))
			{
				grenade = original;
				initialized = true;
				((Behaviour)grenade).enabled = false;
				Plugin.TrySetMember(grenade, "soundSplinter", null);
				FindGameMineSound();
				DisableOriginalAudioSources();
				CreateReplacementAudioSource();
				Plugin.Log.LogInfo((object)("Original function broken, applying fix to: " + ((Object)((Component)this).gameObject).name));
			}
		}

		private static void FindGameMineSound()
		{
			if (!searchedForClip)
			{
				searchedForClip = true;
				AudioClip[] source = Resources.FindObjectsOfTypeAll<AudioClip>();
				cachedMineClip = ((IEnumerable<AudioClip>)source).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => NameEquals(c, "item explosive mine warning beeps"))) ?? ((IEnumerable<AudioClip>)source).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => NameEquals(c, "grenade countdown"))) ?? ((IEnumerable<AudioClip>)source).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => NameEquals(c, "item explosive mine arm beep"))) ?? ((IEnumerable<AudioClip>)source).FirstOrDefault((Func<AudioClip, bool>)((AudioClip c) => NameEquals(c, "snd_dirt_tracker_beep")));
				if ((Object)(object)cachedMineClip == (Object)null)
				{
					Plugin.Log.LogWarning((object)"Could not find the grenade/mine warning beep AudioClip.");
				}
				else
				{
					Plugin.Log.LogInfo((object)("Using warning beep AudioClip: " + ((Object)cachedMineClip).name));
				}
			}
		}

		private static bool NameEquals(AudioClip clip, string name)
		{
			if ((Object)(object)clip != (Object)null)
			{
				return ((Object)clip).name.Equals(name, StringComparison.OrdinalIgnoreCase);
			}
			return false;
		}

		private void DisableOriginalAudioSources()
		{
			AudioSource[] componentsInChildren = ((Component)this).GetComponentsInChildren<AudioSource>(true);
			foreach (AudioSource obj in componentsInChildren)
			{
				obj.Stop();
				obj.playOnAwake = false;
				((Behaviour)obj).enabled = false;
			}
		}

		private void CreateReplacementAudioSource()
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)replacementAudioSource != (Object)null) && !((Object)(object)cachedMineClip == (Object)null))
			{
				replacementAudioObject = new GameObject("SillyValuablesFix_Audio");
				replacementAudioObject.transform.SetParent(((Component)this).transform, false);
				replacementAudioObject.transform.localPosition = Vector3.zero;
				replacementAudioSource = replacementAudioObject.AddComponent<AudioSource>();
				((Behaviour)replacementAudioSource).enabled = true;
				replacementAudioSource.playOnAwake = false;
				replacementAudioSource.loop = false;
				replacementAudioSource.clip = cachedMineClip;
				replacementAudioSource.volume = 0.95f;
				replacementAudioSource.pitch = 1.2f;
				replacementAudioSource.spatialBlend = 1f;
				replacementAudioSource.rolloffMode = (AudioRolloffMode)1;
				replacementAudioSource.minDistance = 4f;
				replacementAudioSource.maxDistance = 45f;
				replacementAudioSource.dopplerLevel = 0f;
				replacementAudioSource.ignoreListenerPause = false;
			}
		}

		private void PlayCustomMineTick()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			if (!shuttingDown && !((Object)(object)replacementAudioSource == (Object)null) && !((Object)(object)replacementAudioObject == (Object)null) && !((Object)(object)cachedMineClip == (Object)null) && replacementAudioObject.activeInHierarchy)
			{
				if (!((Behaviour)replacementAudioSource).enabled)
				{
					((Behaviour)replacementAudioSource).enabled = true;
				}
				((Component)replacementAudioSource).transform.position = ((Component)this).transform.position;
				replacementAudioSource.pitch = 1.2f;
				replacementAudioSource.PlayOneShot(cachedMineClip, 1f);
			}
		}

		private bool TryInvoke(string methodName)
		{
			MonoBehaviour val = grenade;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			try
			{
				MethodInfo methodInfo = FindMethod(((object)val).GetType(), methodName);
				if (methodInfo == null)
				{
					Plugin.Log.LogWarning((object)("Method '" + methodName + "' was not found on " + ((object)val).GetType().Name + "."));
					return false;
				}
				methodInfo.Invoke(val, null);
				return true;
			}
			catch (TargetInvocationException ex)
			{
				Plugin.Log.LogError((object)$"Exception inside '{methodName}': {ex.InnerException ?? ex}");
				return false;
			}
			catch (Exception arg)
			{
				Plugin.Log.LogError((object)$"Failed to invoke '{methodName}': {arg}");
				return false;
			}
		}

		private static MethodInfo? FindMethod(Type? type, string methodName)
		{
			while (type != null)
			{
				MethodInfo method = type.GetMethod(methodName, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method != null)
				{
					return method;
				}
				type = type.BaseType;
			}
			return null;
		}

		private bool TryGetState(out bool active, out bool thrownRocket, out bool equipped, out Component? physGrab)
		{
			active = false;
			thrownRocket = false;
			equipped = false;
			physGrab = null;
			MonoBehaviour val = grenade;
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (!Plugin.TryGetMember<bool>(val, "isActive", out active))
			{
				return false;
			}
			Plugin.TryGetMember<bool>(val, "isThrownRocket", out thrownRocket);
			Plugin.TryGetMember<Component>(val, "itemEquippable", out var value);
			Plugin.TryGetMember<Component>(val, "physGrabObject", out physGrab);
			equipped = Plugin.CheckIsEquipped(value);
			return true;
		}

		private static bool IsGrabbed(Component? physGrabObject)
		{
			bool value;
			return Plugin.TryGetMember<bool>(physGrabObject, "grabbed", out value) && value;
		}

		private void ResetArmedState()
		{
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			MonoBehaviour val = grenade;
			if (!((Object)(object)val == (Object)null))
			{
				Plugin.TrySetMember(val, "isActive", false);
				Plugin.TrySetMember(val, "grenadeTimer", 0f);
				Plugin.TrySetMember(val, "splinterAnimationProgress", 0f);
				Plugin.TrySetMember(val, "isThrownRocket", false);
				if (Plugin.TryGetMember<Component>(val, "itemToggle", out var value) && (Object)(object)value != (Object)null)
				{
					TryInvokeOnComponent(value, "ToggleItem", false, -1);
				}
				if (Plugin.TryGetMember<Transform>(val, "splinterTransform", out var value2) && (Object)(object)value2 != (Object)null)
				{
					value2.localEulerAngles = Vector3.zero;
				}
				if (Plugin.TryGetMember<Material>(val, "grenadeEmissionMaterial", out var value3) && (Object)(object)value3 != (Object)null)
				{
					value3.SetColor("_EmissionColor", Color.black);
				}
				if (Plugin.TryGetMember<GameObject>(val, "throwLine", out var value4) && (Object)(object)value4 != (Object)null)
				{
					value4.SetActive(false);
				}
			}
		}

		private static bool TryInvokeOnComponent(Component component, string methodName, params object[] args)
		{
			try
			{
				MethodInfo method = ((object)component).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (method == null)
				{
					return false;
				}
				method.Invoke(component, args);
				return true;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Failed to invoke component method '" + methodName + "': " + ex.Message));
				return false;
			}
		}

		private void Update()
		{
			if (shuttingDown || !initialized || (Object)(object)grenade == (Object)null || !TryGetState(out bool active, out bool thrownRocket, out bool equipped, out Component physGrab))
			{
				return;
			}
			bool flag = IsGrabbed(physGrab);
			if (equipped)
			{
				if (active)
				{
					ResetArmedState();
				}
				lastActive = false;
				tickAudioTimer = 0f;
				return;
			}
			if (!active && lastActive)
			{
				tickAudioTimer = 0f;
			}
			if (active)
			{
				tickAudioTimer += Time.deltaTime;
				while (tickAudioTimer >= 0.35f)
				{
					tickAudioTimer -= 0.35f;
					PlayCustomMineTick();
				}
				UpdatePinAnimation();
				UpdateEmission();
			}
			if ((Object)(object)physGrab != (Object)null && !equipped && active && !thrownRocket && !flag)
			{
				Plugin.TrySetMember(grenade, "isThrownRocket", true);
				TryInvoke("LaunchAsRocket");
			}
			TryStartActivation();
			lastActive = active;
		}

		private void TryStartActivation()
		{
			MonoBehaviour val = grenade;
			if (!((Object)(object)val == (Object)null) && SemiFunc.IsMasterClientOrSingleplayer() && Plugin.TryGetMember<Component>(val, "itemToggle", out var value) && !((Object)(object)value == (Object)null) && Plugin.TryGetMember<bool>(value, "toggleState", out var value2) && value2 && !(Plugin.TryGetMember<bool>(val, "isActive", out var value3) && value3))
			{
				Plugin.TrySetMember(val, "isActive", true);
				tickAudioTimer = 0f;
				PlayCustomMineTick();
				TryInvoke("TickStart");
			}
		}

		private void UpdatePinAnimation()
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			MonoBehaviour val = grenade;
			if (!((Object)(object)val == (Object)null) && Plugin.TryGetMember<float>(val, "splinterAnimationProgress", out var value) && Plugin.TryGetMember<AnimationCurve>(val, "splinterAnimationCurve", out var value2) && Plugin.TryGetMember<Transform>(val, "splinterTransform", out var value3))
			{
				if (value < 1f)
				{
					value = Mathf.Min(1f, value + 5f * Time.deltaTime);
					Plugin.TrySetMember(val, "splinterAnimationProgress", value);
				}
				if ((Object)(object)value3 != (Object)null)
				{
					float num = ((value2 != null) ? value2.Evaluate(value) : 0f);
					value3.localEulerAngles = new Vector3(num * 90f, 0f, 0f);
				}
			}
		}

		private void UpdateEmission()
		{
			//IL_0056: 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)
			MonoBehaviour val = grenade;
			if (!((Object)(object)val == (Object)null) && Plugin.TryGetMember<Color>(val, "blinkColor", out var value) && Plugin.TryGetMember<Material>(val, "grenadeEmissionMaterial", out var value2) && !((Object)(object)value2 == (Object)null))
			{
				float num = Mathf.PingPong(Time.time * 8f, 1f);
				value2.SetColor("_EmissionColor", value * Mathf.LinearToGammaSpace(num));
			}
		}

		private void FixedUpdate()
		{
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if (shuttingDown || !initialized || (Object)(object)grenade == (Object)null)
			{
				return;
			}
			MonoBehaviour instance = grenade;
			if (!Plugin.TryGetMember<Component>(instance, "itemEquippable", out var value) || !Plugin.TryGetMember<Rigidbody>(instance, "rb", out var value2) || !Plugin.TryGetMember<Vector3>(instance, "prevPosition", out var value3))
			{
				return;
			}
			Plugin.TryGetMember<Component>(instance, "physGrabObject", out var value4);
			bool flag = Plugin.CheckIsEquipped(value);
			bool flag2 = IsGrabbed(value4);
			Plugin.TryGetMember<float>(value, "wasEquippedTimer", out var value5);
			if ((Object)(object)value2 == (Object)null)
			{
				return;
			}
			if (flag || value5 > 0f)
			{
				Plugin.TrySetMember(instance, "prevPosition", value2.position);
				return;
			}
			Vector3 val = (value2.position - value3) / Mathf.Max(Time.fixedDeltaTime, 0.0001f);
			Plugin.TrySetMember(instance, "prevPosition", value2.position);
			if (!flag2 && ((Vector3)(ref val)).magnitude > 2f)
			{
				Plugin.TrySetMember(instance, "throwLineTimer", 0.2f);
			}
			Plugin.TryGetMember<float>(instance, "throwLineTimer", out var value6);
			if (Plugin.TryGetMember<TrailRenderer>(instance, "throwLineTrail", out var value7) && (Object)(object)value7 != (Object)null)
			{
				value7.emitting = value6 > 0f;
			}
			if (value6 > 0f)
			{
				Plugin.TrySetMember(instance, "throwLineTimer", value6 - Time.fixedDeltaTime);
			}
		}

		private void OnCollisionEnter(Collision collision)
		{
			if (!shuttingDown && !((Object)(object)grenade == (Object)null) && Plugin.TryGetMember<bool>(grenade, "isThrownRocket", out var value) && value && SemiFunc.IsMasterClientOrSingleplayer())
			{
				TryInvoke("TickEnd");
			}
		}

		private void OnDestroy()
		{
			shuttingDown = true;
			if ((Object)(object)replacementAudioSource != (Object)null)
			{
				replacementAudioSource.Stop();
				((Behaviour)replacementAudioSource).enabled = false;
				replacementAudioSource = null;
			}
			if ((Object)(object)replacementAudioObject != (Object)null)
			{
				Object.Destroy((Object)(object)replacementAudioObject);
				replacementAudioObject = null;
			}
		}
	}
}