Decompiled source of The Slime Gun v0.2.15

BepInEx\plugins\SlimeGun\SlimeGun.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using SlimeGun.Combat;
using SlimeGun.Weapon;
using UnityEngine;
using UnityEngine.Rendering;

[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("SlimeGun")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Slime Gun weapon mod for R.E.P.O. - coats enemies in toxic goo and heals allies.")]
[assembly: AssemblyFileVersion("0.2.15.0")]
[assembly: AssemblyInformationalVersion("0.2.15")]
[assembly: AssemblyProduct("SlimeGun")]
[assembly: AssemblyTitle("SlimeGun")]
[assembly: AssemblyVersion("0.2.15.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.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]
	[Microsoft.CodeAnalysis.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]
	[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 SlimeGun
{
	[BepInPlugin("com.amgru.slimegun", "SlimeGun", "0.2.15")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "com.amgru.slimegun";

		public const string PluginName = "SlimeGun";

		public const string PluginVersion = "0.2.15";

		internal static ConfigEntry<bool> ModEnabled = null;

		internal static ConfigEntry<float> DamagePerTick = null;

		internal static ConfigEntry<float> HealPerTick = null;

		internal static ConfigEntry<float> SlowAmount = null;

		internal static ConfigEntry<float> SlimeDuration = null;

		internal static ConfigEntry<float> TickInterval = null;

		internal static ConfigEntry<float> TankCapacity = null;

		internal static ConfigEntry<float> TankDrainRate = null;

		internal static ConfigEntry<float> TankRechargeRate = null;

		internal static ConfigEntry<float> GlobSpeed = null;

		private Harmony? harmony;

		internal static string PluginDirectory { get; private set; } = string.Empty;


		private void Awake()
		{
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Expected O, but got Unknown
			PluginDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty;
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enables or disables the Slime Gun.");
			DamagePerTick = ((BaseUnityPlugin)this).Config.Bind<float>("Slime", "DamagePerTick", 8f, "Damage dealt to enemies per tick while slimed.");
			HealPerTick = ((BaseUnityPlugin)this).Config.Bind<float>("Slime", "HealPerTick", 10f, "Health restored to friendly players per tick while slimed.");
			SlowAmount = ((BaseUnityPlugin)this).Config.Bind<float>("Slime", "SlowAmount", 0.78f, "Fraction of movement speed removed while slimed. 0 = no slow, 1 = fully frozen.");
			SlimeDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Slime", "Duration", 6f, "Base seconds the slime effect lasts before the built-in 2.5x lasting coat multiplier. Re-coating refreshes the timer.");
			TickInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Slime", "TickInterval", 0.5f, "Seconds between each damage or heal tick.");
			TankCapacity = ((BaseUnityPlugin)this).Config.Bind<float>("Gun", "TankCapacity", 100f, "Maximum slime tank capacity.");
			TankDrainRate = ((BaseUnityPlugin)this).Config.Bind<float>("Gun", "DrainRate", 4f, "Slime units drained per second while firing.");
			TankRechargeRate = ((BaseUnityPlugin)this).Config.Bind<float>("Gun", "RechargeRate", 8f, "Slime units recharged per second when not firing.");
			GlobSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Gun", "GlobSpeed", 6f, "Initial speed of slime projectiles in m/s.");
			SlimeGunRuntime.Enabled = ModEnabled.Value;
			SlimeGunRuntime.PluginDirectory = PluginDirectory;
			harmony = new Harmony("com.amgru.slimegun");
			harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("{0} v{1} loaded. Enabled={2}", "SlimeGun", "0.2.15", ModEnabled.Value));
		}

		private void OnDestroy()
		{
			Harmony? obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
		}
	}
}
namespace SlimeGun.Patches
{
	[HarmonyPatch(typeof(ItemGun), "Shoot")]
	internal static class ItemGunShootPatch
	{
		private static bool Prefix(ItemGun __instance)
		{
			if ((((Component)__instance).GetComponent<ItemAttributes>() ?? ((Component)__instance).GetComponentInChildren<ItemAttributes>(true) ?? ((Component)__instance).GetComponentInParent<ItemAttributes>())?.item?.itemName != "Slime Gun")
			{
				return true;
			}
			SlimeGunController.OnItemGunShoot(__instance);
			return false;
		}
	}
	[HarmonyPatch(typeof(ItemGun), "Update")]
	internal static class ItemGunUpdatePatch
	{
		private static void Postfix(ItemGun __instance)
		{
			if ((((Component)__instance).GetComponent<ItemAttributes>() ?? ((Component)__instance).GetComponentInChildren<ItemAttributes>(true) ?? ((Component)__instance).GetComponentInParent<ItemAttributes>())?.item?.itemName != "Slime Gun")
			{
				return;
			}
			Renderer[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				string name = ((object)val).GetType().Name;
				if ((name == "LineRenderer" || name == "TrailRenderer") && val.enabled)
				{
					val.enabled = false;
				}
			}
			Component[] componentsInChildren2 = ((Component)__instance).GetComponentsInChildren<Component>(true);
			bool flag = default(bool);
			foreach (Component val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null) && !(((object)val2).GetType().Name != "ParticleSystem"))
				{
					object obj = ((object)val2).GetType().GetProperty("isPlaying")?.GetValue(val2);
					int num;
					if (obj is bool)
					{
						flag = (bool)obj;
						num = 1;
					}
					else
					{
						num = 0;
					}
					if (((uint)num & (flag ? 1u : 0u)) != 0)
					{
						((object)val2).GetType().GetMethod("Stop", Type.EmptyTypes)?.Invoke(val2, null);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(PhysGrabObject), "Update")]
	internal static class PhysGrabObjectUpdatePatch
	{
		private static void Postfix(PhysGrabObject __instance)
		{
			SlimeGunController.OnPhysGrabObjectUpdate(__instance);
		}
	}
	[HarmonyPatch(typeof(PlayerController), "Start")]
	internal static class PlayerControllerStartPatch
	{
		private static void Postfix(PlayerController __instance)
		{
		}
	}
}
namespace SlimeGun.Combat
{
	internal static class SlimeCombat
	{
		private static readonly FieldInfo EnemyHasHealthField = AccessTools.Field(typeof(Enemy), "HasHealth");

		private static readonly FieldInfo EnemyHealthField = AccessTools.Field(typeof(Enemy), "Health");

		private static readonly FieldInfo EnemyHasRigidbodyField = AccessTools.Field(typeof(Enemy), "HasRigidbody");

		private static readonly FieldInfo EnemyRigidbodyField = AccessTools.Field(typeof(Enemy), "Rigidbody");

		private static readonly FieldInfo EnemyRbField = AccessTools.Field(typeof(EnemyRigidbody), "rb");

		internal static Enemy? FindEnemy(Collider collider)
		{
			Enemy componentInParent = ((Component)collider).GetComponentInParent<Enemy>();
			if ((Object)(object)componentInParent != (Object)null && Object.op_Implicit((Object)(object)componentInParent))
			{
				return componentInParent;
			}
			EnemyRigidbody componentInParent2 = ((Component)collider).GetComponentInParent<EnemyRigidbody>();
			if ((Object)(object)componentInParent2 != (Object)null && (Object)(object)componentInParent2.enemy != (Object)null && Object.op_Implicit((Object)(object)componentInParent2.enemy))
			{
				return componentInParent2.enemy;
			}
			if (!((Object)(object)collider.attachedRigidbody != (Object)null))
			{
				return null;
			}
			return ((Component)collider.attachedRigidbody).GetComponent<EnemyRigidbody>()?.enemy;
		}

		internal static PlayerController? FindPlayer(Collider collider)
		{
			PlayerController componentInParent = ((Component)collider).GetComponentInParent<PlayerController>();
			if ((Object)(object)componentInParent != (Object)null && Object.op_Implicit((Object)(object)componentInParent))
			{
				return componentInParent;
			}
			PlayerAvatar componentInParent2 = ((Component)collider).GetComponentInParent<PlayerAvatar>();
			if ((Object)(object)componentInParent2 != (Object)null && Object.op_Implicit((Object)(object)componentInParent2))
			{
				PlayerController val = ((Component)componentInParent2).GetComponent<PlayerController>() ?? ((Component)componentInParent2).GetComponentInParent<PlayerController>();
				if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val))
				{
					return val;
				}
			}
			return null;
		}

		internal static void DamageEnemy(Enemy enemy, int damage, Vector3 hitPosition)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: 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_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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 (!SemiFunc.IsMasterClientOrSingleplayer())
			{
				return;
			}
			Vector3 val = ((Component)enemy).transform.position - hitPosition;
			Vector3 val2 = ((Vector3)(ref val)).normalized;
			if (((Vector3)(ref val2)).sqrMagnitude < 0.01f)
			{
				val2 = Vector3.forward;
			}
			object value = EnemyHasHealthField.GetValue(enemy);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0)
			{
				object? value2 = EnemyHealthField.GetValue(enemy);
				EnemyHealth val3 = (EnemyHealth)((value2 is EnemyHealth) ? value2 : null);
				if (val3 != null)
				{
					val3.Hurt(Mathf.Max(0, damage), val2);
					Debug.Log((object)$"[SlimeGun] Slime tick: {damage} damage to {((Object)enemy).name}.");
					return;
				}
			}
			Debug.Log((object)$"[SlimeGun] Would deal {damage} to {((Object)enemy).name} but no EnemyHealth hook available.");
		}

		internal static void HealPlayer(PlayerAvatar playerAvatar, int amount)
		{
			if (SemiFunc.IsMasterClientOrSingleplayer())
			{
				PlayerHealth playerHealth = playerAvatar.playerHealth;
				if ((Object)(object)playerHealth != (Object)null && Object.op_Implicit((Object)(object)playerHealth))
				{
					playerHealth.HealOther(Mathf.Max(0, amount), true);
					Debug.Log((object)$"[SlimeGun] Slime tick: healed {amount} HP on {((Object)playerAvatar).name}.");
				}
				else
				{
					Debug.Log((object)$"[SlimeGun] Would heal {amount} HP on {((Object)playerAvatar).name} but no PlayerHealth component was found.");
				}
			}
		}

		internal static Rigidbody? GetEnemyRigidbody(Enemy enemy)
		{
			object value = EnemyHasRigidbodyField.GetValue(enemy);
			bool flag = default(bool);
			int num;
			if (value is bool)
			{
				flag = (bool)value;
				num = 1;
			}
			else
			{
				num = 0;
			}
			if (((uint)num & (flag ? 1u : 0u)) != 0)
			{
				object? value2 = EnemyRigidbodyField.GetValue(enemy);
				EnemyRigidbody val = (EnemyRigidbody)((value2 is EnemyRigidbody) ? value2 : null);
				if (val != null)
				{
					object? value3 = EnemyRbField.GetValue(val);
					Rigidbody val2 = (Rigidbody)((value3 is Rigidbody) ? value3 : null);
					if (val2 != null)
					{
						return val2;
					}
				}
			}
			return null;
		}
	}
}
namespace SlimeGun.Weapon
{
	public sealed class SlimeEffect : MonoBehaviour
	{
		public enum TargetType
		{
			Enemy,
			Player
		}

		private struct MaterialTintState
		{
			public Material material;

			public Color originalColor;

			public Color originalEmission;

			public bool hadEmission;
		}

		private struct RendererTintState
		{
			public Renderer renderer;

			public MaterialPropertyBlock originalBlock;

			public MaterialPropertyBlock slimeBlock;
		}

		private struct FloatMemberState
		{
			public object target;

			public FieldInfo? field;

			public PropertyInfo? property;

			public float originalValue;
		}

		private TargetType targetType;

		private Enemy? enemy;

		private PlayerAvatar? playerAvatar;

		private EnemyRigidbody? enemyRigidbody;

		private Rigidbody? targetRigidbody;

		private float originalDrag;

		private GameObject? gooCoat;

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

		private Component? navAgentComponent;

		private PropertyInfo? navAgentSpeedProp;

		private float originalNavSpeed;

		private float slowAmount;

		private float startedAt;

		private float duration;

		private float expiresAt;

		private float nextTickAt;

		private float tickInterval;

		private int damageOrHealPerTick;

		private bool visualOnly;

		private const float DissolveStartFraction = 0.6f;

		private const float DurationMultiplier = 2.5f;

		private const float EnemyDamageMultiplier = 3f;

		private const int MaxGooPatchCount = 42;

		private readonly List<MaterialTintState> tintedStates = new List<MaterialTintState>();

		private readonly List<RendererTintState> rendererTintStates = new List<RendererTintState>();

		private readonly List<FloatMemberState> slowedFloatStates = new List<FloatMemberState>();

		private static readonly Color SlimeTint = new Color(0.12f, 0.95f, 0.16f, 1f);

		private static readonly Color SlimeEmission = new Color(0.08f, 2.8f, 0.12f);

		public static SlimeEffect ApplyToEnemy(Enemy enemy, float duration, float slow, int damage, float tickInterval)
		{
			SlimeEffect obj = ((Component)enemy).gameObject.GetComponent<SlimeEffect>() ?? ((Component)enemy).gameObject.AddComponent<SlimeEffect>();
			obj.InitForEnemy(enemy, duration, slow, damage, tickInterval, visualOnlyEffect: false);
			return obj;
		}

		public static SlimeEffect ApplyVisualToEnemy(Enemy enemy, float duration, float slow, int damage, float tickInterval)
		{
			SlimeEffect obj = ((Component)enemy).gameObject.GetComponent<SlimeEffect>() ?? ((Component)enemy).gameObject.AddComponent<SlimeEffect>();
			obj.InitForEnemy(enemy, duration, slow, damage, tickInterval, visualOnlyEffect: true);
			return obj;
		}

		public static SlimeEffect ApplyToPlayer(PlayerController player, float duration, float slow, int heal, float tickInterval)
		{
			SlimeEffect obj = ((Component)player).gameObject.GetComponent<SlimeEffect>() ?? ((Component)player).gameObject.AddComponent<SlimeEffect>();
			obj.InitForPlayer(player, duration, slow, heal, tickInterval, visualOnlyEffect: false);
			return obj;
		}

		public static SlimeEffect ApplyVisualToPlayer(PlayerController player, float duration, float slow, int heal, float tickInterval)
		{
			SlimeEffect obj = ((Component)player).gameObject.GetComponent<SlimeEffect>() ?? ((Component)player).gameObject.AddComponent<SlimeEffect>();
			obj.InitForPlayer(player, duration, slow, heal, tickInterval, visualOnlyEffect: true);
			return obj;
		}

		public static SlimeEffect ApplyVisualToPlayerAvatar(PlayerAvatar avatar, float duration, float slow, int heal, float tickInterval)
		{
			SlimeEffect obj = ((Component)avatar).gameObject.GetComponent<SlimeEffect>() ?? ((Component)avatar).gameObject.AddComponent<SlimeEffect>();
			obj.InitForPlayerAvatar(avatar, duration, slow, heal, tickInterval, visualOnlyEffect: true);
			return obj;
		}

		public static SlimeEffect ApplyToPlayerAvatar(PlayerAvatar avatar, float duration, float slow, int heal, float tickInterval)
		{
			SlimeEffect obj = ((Component)avatar).gameObject.GetComponent<SlimeEffect>() ?? ((Component)avatar).gameObject.AddComponent<SlimeEffect>();
			obj.InitForPlayerAvatar(avatar, duration, slow, heal, tickInterval, visualOnlyEffect: false);
			return obj;
		}

		private void InitForEnemy(Enemy e, float duration, float slow, int damage, float tick, bool visualOnlyEffect)
		{
			if (targetType == TargetType.Enemy && (Object)(object)enemy == (Object)(object)e && Time.time < expiresAt)
			{
				Refresh(duration * 2.5f, slow, Mathf.CeilToInt((float)damage * 3f), Mathf.Min(tick, 0.25f));
				if ((visualOnlyEffect && !visualOnly) || visualOnly == visualOnlyEffect)
				{
					return;
				}
			}
			RestoreSlow();
			ClearTint();
			targetType = TargetType.Enemy;
			enemy = e;
			enemyRigidbody = ((Component)e).GetComponentInChildren<EnemyRigidbody>();
			visualOnly = visualOnlyEffect;
			slowAmount = slow;
			damageOrHealPerTick = Mathf.CeilToInt((float)damage * 3f);
			tickInterval = Mathf.Min(tick, 0.25f);
			this.duration = duration * 2.5f;
			startedAt = Time.time;
			expiresAt = Time.time + this.duration;
			nextTickAt = Time.time + tickInterval;
			targetRigidbody = (visualOnly ? null : SlimeCombat.GetEnemyRigidbody(e));
			if (!visualOnly)
			{
				TrySlowNavAgent(((Component)e).gameObject);
				ApplyBroadEnemySlow(((Component)e).gameObject);
				ApplyRigidbodyDrag();
			}
			GameObject root = FindVisualRoot(((Component)e).gameObject);
			ApplyPatchyGooCoat(root);
			Debug.Log((object)$"[SlimeGun] SlimeEffect started on enemy {((Object)e).name}. slow={slow:0.00} dmg={damageOrHealPerTick} duration={this.duration:0.0}s");
		}

		private void InitForPlayer(PlayerController pc, float duration, float slow, int heal, float tick, bool visualOnlyEffect)
		{
			if (targetType == TargetType.Player && (Object)(object)playerAvatar == (Object)(object)pc.playerAvatarScript && Time.time < expiresAt)
			{
				Refresh(duration * 2.5f, slow, heal, tick);
				if ((visualOnlyEffect && !visualOnly) || visualOnly == visualOnlyEffect)
				{
					return;
				}
			}
			RestoreSlow();
			ClearTint();
			targetType = TargetType.Player;
			playerAvatar = pc.playerAvatarScript;
			enemyRigidbody = null;
			visualOnly = visualOnlyEffect;
			slowAmount = slow;
			damageOrHealPerTick = heal;
			tickInterval = tick;
			this.duration = duration * 2.5f;
			startedAt = Time.time;
			expiresAt = Time.time + this.duration;
			nextTickAt = Time.time + tick;
			targetRigidbody = (visualOnly ? null : pc.rb);
			if (!visualOnly)
			{
				ApplyRigidbodyDrag();
			}
			ApplyPatchyGooCoat(((Component)pc).gameObject);
			Debug.Log((object)$"[SlimeGun] SlimeEffect started on player {((Object)pc).name}. slow={slow:0.00} heal={heal} duration={this.duration:0.0}s");
		}

		private void InitForPlayerAvatar(PlayerAvatar avatar, float duration, float slow, int heal, float tick, bool visualOnlyEffect)
		{
			if (targetType == TargetType.Player && (Object)(object)playerAvatar == (Object)(object)avatar && Time.time < expiresAt)
			{
				Refresh(duration * 2.5f, slow, heal, tick);
				if ((visualOnlyEffect && !visualOnly) || visualOnly == visualOnlyEffect)
				{
					return;
				}
			}
			RestoreSlow();
			ClearTint();
			targetType = TargetType.Player;
			playerAvatar = avatar;
			enemyRigidbody = null;
			targetRigidbody = null;
			visualOnly = visualOnlyEffect;
			slowAmount = slow;
			damageOrHealPerTick = heal;
			tickInterval = tick;
			this.duration = duration * 2.5f;
			startedAt = Time.time;
			expiresAt = Time.time + this.duration;
			nextTickAt = Time.time + tick;
			ApplyPatchyGooCoat(FindVisualRoot(((Component)avatar).gameObject));
			Debug.Log((object)(visualOnly ? $"[SlimeGun] Visual slime coat started on player avatar {((Object)avatar).name}. duration={this.duration:0.0}s" : $"[SlimeGun] SlimeEffect started on player avatar {((Object)avatar).name}. heal={heal} duration={this.duration:0.0}s"));
		}

		private void Refresh(float refreshedDuration, float refreshedSlow, int refreshedTickAmount, float refreshedTickInterval)
		{
			slowAmount = Mathf.Max(slowAmount, refreshedSlow);
			damageOrHealPerTick = Mathf.Max(damageOrHealPerTick, refreshedTickAmount);
			tickInterval = Mathf.Min(tickInterval, refreshedTickInterval);
			duration = Mathf.Max(duration, refreshedDuration);
			expiresAt = Time.time + duration;
		}

		private void Update()
		{
			if (Time.time >= expiresAt)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			float num = Time.time - startedAt;
			float num2 = duration * 0.6f;
			if (num >= num2 && duration > 0f)
			{
				float num3 = (num - num2) / (duration * 0.39999998f);
				float alpha = Mathf.Clamp01(1f - num3);
				UpdateGooCoatAlpha(alpha);
			}
			if (!visualOnly && Time.time >= nextTickAt)
			{
				nextTickAt = Time.time + tickInterval;
				ApplyTick();
			}
		}

		private void UpdateGooCoatAlpha(float alpha)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			foreach (GameObject gooPatch in gooPatches)
			{
				if ((Object)(object)gooPatch == (Object)null || !Object.op_Implicit((Object)(object)gooPatch))
				{
					continue;
				}
				Renderer component = gooPatch.GetComponent<Renderer>();
				if ((Object)(object)component == (Object)null || !Object.op_Implicit((Object)(object)component))
				{
					continue;
				}
				Material[] materials = component.materials;
				foreach (Material val in materials)
				{
					if (!((Object)(object)val == (Object)null))
					{
						Color val2 = (Color)(val.HasProperty("_Color") ? val.GetColor("_Color") : new Color(0.08f, 1f, 0.14f, 0.62f));
						val2.a = Mathf.Min(val2.a, alpha * 0.62f);
						if (val.HasProperty("_Color"))
						{
							val.SetColor("_Color", val2);
						}
						if (val.HasProperty("_BaseColor"))
						{
							val.SetColor("_BaseColor", val2);
						}
					}
				}
			}
		}

		private void FixedUpdate()
		{
			//IL_0057: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (!visualOnly)
			{
				if (targetType == TargetType.Enemy)
				{
					ApplyEnemyMovementSuppression();
					ReapplyBroadEnemySlow();
				}
				if ((Object)(object)targetRigidbody != (Object)null && Object.op_Implicit((Object)(object)targetRigidbody))
				{
					float num = Mathf.Clamp01(1f - slowAmount * 0.65f);
					Rigidbody? obj = targetRigidbody;
					obj.velocity *= num;
					Rigidbody? obj2 = targetRigidbody;
					obj2.angularVelocity *= num;
				}
			}
		}

		private void OnDestroy()
		{
			if (!visualOnly)
			{
				RestoreSlow();
			}
			ClearTint();
		}

		private void ApplyTick()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (targetType == TargetType.Enemy && (Object)(object)enemy != (Object)null && Object.op_Implicit((Object)(object)enemy))
			{
				SlimeCombat.DamageEnemy(enemy, damageOrHealPerTick, ((Component)this).transform.position);
			}
			else if (targetType == TargetType.Player && (Object)(object)playerAvatar != (Object)null && Object.op_Implicit((Object)(object)playerAvatar))
			{
				SlimeCombat.HealPlayer(playerAvatar, damageOrHealPerTick);
			}
		}

		private void TrySlowNavAgent(GameObject root)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>();
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null || ((object)val).GetType().FullName != "UnityEngine.AI.NavMeshAgent")
				{
					continue;
				}
				PropertyInfo property = ((object)val).GetType().GetProperty("speed", BindingFlags.Instance | BindingFlags.Public);
				if (!(property == null))
				{
					object value = property.GetValue(val);
					if (value is float)
					{
						float num = (originalNavSpeed = (float)value);
						property.SetValue(val, num * (1f - slowAmount));
						navAgentComponent = val;
						navAgentSpeedProp = property;
						Debug.Log((object)$"[SlimeGun] NavMeshAgent speed slowed: {num:0.00} -> {num * (1f - slowAmount):0.00}");
					}
				}
				break;
			}
		}

		private void ApplyRigidbodyDrag()
		{
			if (!((Object)(object)targetRigidbody == (Object)null) && Object.op_Implicit((Object)(object)targetRigidbody))
			{
				originalDrag = targetRigidbody.drag;
				targetRigidbody.drag = originalDrag + slowAmount * 60f;
			}
		}

		private void ApplyEnemyMovementSuppression()
		{
			if (!((Object)(object)enemyRigidbody == (Object)null) && Object.op_Implicit((Object)(object)enemyRigidbody))
			{
				enemyRigidbody.DisableFollowPosition(0.25f, Mathf.Lerp(18f, 42f, slowAmount));
				enemyRigidbody.DisableFollowRotation(0.25f, Mathf.Lerp(16f, 38f, slowAmount));
			}
		}

		private void RestoreSlow()
		{
			if ((Object)(object)navAgentComponent != (Object)null && navAgentSpeedProp != null && Object.op_Implicit((Object)(object)navAgentComponent))
			{
				navAgentSpeedProp.SetValue(navAgentComponent, originalNavSpeed);
			}
			navAgentComponent = null;
			navAgentSpeedProp = null;
			RestoreBroadEnemySlow();
			if ((Object)(object)targetRigidbody != (Object)null && Object.op_Implicit((Object)(object)targetRigidbody))
			{
				targetRigidbody.drag = originalDrag;
			}
			targetRigidbody = null;
			enemyRigidbody = null;
		}

		private void ApplyBroadEnemySlow(GameObject root)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Type type = ((object)val).GetType();
				if (type.Namespace != null && type.Namespace.StartsWith("UnityEngine", StringComparison.Ordinal))
				{
					continue;
				}
				FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!(fieldInfo.FieldType != typeof(float)) && !fieldInfo.IsInitOnly && ShouldSlowMember(fieldInfo.Name))
					{
						float num = (float)fieldInfo.GetValue(val);
						float num2 = SlowValue(fieldInfo.Name, num);
						if (!Mathf.Approximately(num, num2))
						{
							slowedFloatStates.Add(new FloatMemberState
							{
								target = val,
								field = fieldInfo,
								originalValue = num
							});
							fieldInfo.SetValue(val, num2);
						}
					}
				}
				PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (propertyInfo.PropertyType != typeof(float) || !propertyInfo.CanRead || !propertyInfo.CanWrite || !ShouldSlowMember(propertyInfo.Name) || propertyInfo.GetIndexParameters().Length != 0)
					{
						continue;
					}
					float num3;
					try
					{
						num3 = (float)propertyInfo.GetValue(val, null);
					}
					catch
					{
						continue;
					}
					float num4 = SlowValue(propertyInfo.Name, num3);
					if (!Mathf.Approximately(num3, num4))
					{
						slowedFloatStates.Add(new FloatMemberState
						{
							target = val,
							property = propertyInfo,
							originalValue = num3
						});
						try
						{
							propertyInfo.SetValue(val, num4, null);
						}
						catch
						{
							slowedFloatStates.RemoveAt(slowedFloatStates.Count - 1);
						}
					}
				}
			}
		}

		private void ReapplyBroadEnemySlow()
		{
			foreach (FloatMemberState slowedFloatState in slowedFloatStates)
			{
				object target = slowedFloatState.target;
				Object val = (Object)((target is Object) ? target : null);
				if (val == null || !Object.op_Implicit(val))
				{
					continue;
				}
				float num = SlowValue(slowedFloatState.field?.Name ?? slowedFloatState.property?.Name ?? string.Empty, slowedFloatState.originalValue);
				slowedFloatState.field?.SetValue(slowedFloatState.target, num);
				if (slowedFloatState.property != null)
				{
					try
					{
						slowedFloatState.property.SetValue(slowedFloatState.target, num, null);
					}
					catch
					{
					}
				}
			}
		}

		private void RestoreBroadEnemySlow()
		{
			foreach (FloatMemberState slowedFloatState in slowedFloatStates)
			{
				object target = slowedFloatState.target;
				Object val = (Object)((target is Object) ? target : null);
				if (val == null || !Object.op_Implicit(val))
				{
					continue;
				}
				slowedFloatState.field?.SetValue(slowedFloatState.target, slowedFloatState.originalValue);
				if (slowedFloatState.property != null)
				{
					try
					{
						slowedFloatState.property.SetValue(slowedFloatState.target, slowedFloatState.originalValue, null);
					}
					catch
					{
					}
				}
			}
			slowedFloatStates.Clear();
		}

		private bool ShouldSlowMember(string name)
		{
			string text = name.ToLowerInvariant();
			if (text.Contains("attack") || text.Contains("cooldown") || text.Contains("delay") || text.Contains("interval"))
			{
				return true;
			}
			if (!text.Contains("speed") && !text.Contains("acceleration") && !text.Contains("chase") && !text.Contains("move") && !text.Contains("turn"))
			{
				return text.Contains("rotate");
			}
			return true;
		}

		private float SlowValue(string name, float original)
		{
			if (original <= 0f)
			{
				return original;
			}
			string text = name.ToLowerInvariant();
			if (text.Contains("cooldown") || text.Contains("delay") || text.Contains("interval"))
			{
				return original / Mathf.Max(0.08f, 1f - slowAmount);
			}
			return original * Mathf.Clamp(1f - slowAmount, 0.04f, 1f);
		}

		private void ApplyTint(GameObject root)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//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_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: 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)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			int num2 = 0;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>();
			foreach (Renderer val in componentsInChildren)
			{
				if (!ShouldUseRendererForTint(val))
				{
					continue;
				}
				num++;
				MaterialPropertyBlock val2 = new MaterialPropertyBlock();
				val.GetPropertyBlock(val2);
				MaterialPropertyBlock slimeBlock = new MaterialPropertyBlock();
				rendererTintStates.Add(new RendererTintState
				{
					renderer = val,
					originalBlock = val2,
					slimeBlock = slimeBlock
				});
				Material[] materials = val.materials;
				foreach (Material val3 in materials)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						num2++;
						Color materialColor = GetMaterialColor(val3, Color.white);
						Color originalEmission = (val3.HasProperty("_EmissionColor") ? val3.GetColor("_EmissionColor") : Color.black);
						tintedStates.Add(new MaterialTintState
						{
							material = val3,
							originalColor = materialColor,
							originalEmission = originalEmission,
							hadEmission = val3.IsKeywordEnabled("_EMISSION")
						});
						ApplySlimeToMaterial(val3, materialColor, originalEmission, 1f);
					}
				}
			}
			Debug.Log((object)$"[SlimeGun] Goo visual tint targets on {((Object)root).name}: renderers={num}, materials={num2}");
		}

		private void ReapplyTint(float alpha)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_0060: 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)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: 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)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			foreach (MaterialTintState tintedState in tintedStates)
			{
				if (!((Object)(object)tintedState.material == (Object)null))
				{
					ApplySlimeToMaterial(tintedState.material, tintedState.originalColor, tintedState.originalEmission, alpha);
				}
			}
			Color slimeTintedColor = GetSlimeTintedColor(Color.white, alpha);
			Color val = Color.Lerp(Color.black, SlimeEmission, alpha);
			foreach (RendererTintState rendererTintState in rendererTintStates)
			{
				if (!((Object)(object)rendererTintState.renderer == (Object)null) && Object.op_Implicit((Object)(object)rendererTintState.renderer))
				{
					rendererTintState.slimeBlock.SetColor("_Color", slimeTintedColor);
					rendererTintState.slimeBlock.SetColor("_BaseColor", slimeTintedColor);
					rendererTintState.slimeBlock.SetColor("_EmissionColor", val);
					rendererTintState.renderer.SetPropertyBlock(rendererTintState.slimeBlock);
				}
			}
		}

		private static Color GetSlimeTintedColor(Color original, float alpha)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: 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_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Color result = Color.Lerp(original, SlimeTint, 0.93f * alpha);
			result.a = original.a;
			return result;
		}

		private static void ApplySlimeToMaterial(Material mat, Color originalColor, Color originalEmission, float alpha)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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)
			Color slimeTintedColor = GetSlimeTintedColor(originalColor, alpha);
			if (mat.HasProperty("_Color"))
			{
				mat.SetColor("_Color", slimeTintedColor);
			}
			if (mat.HasProperty("_BaseColor"))
			{
				mat.SetColor("_BaseColor", slimeTintedColor);
			}
			mat.EnableKeyword("_EMISSION");
			Color val = Color.Lerp(originalEmission, SlimeEmission, alpha);
			if (mat.HasProperty("_EmissionColor"))
			{
				mat.SetColor("_EmissionColor", val);
			}
		}

		private static Color GetMaterialColor(Material mat, Color fallback)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (mat.HasProperty("_Color"))
			{
				return mat.GetColor("_Color");
			}
			if (mat.HasProperty("_BaseColor"))
			{
				return mat.GetColor("_BaseColor");
			}
			return fallback;
		}

		private void ApplyPatchyGooCoat(GameObject root)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_0056: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gooCoat != (Object)null)
			{
				Object.Destroy((Object)(object)gooCoat);
			}
			gooPatches.Clear();
			gooCoat = new GameObject("SlimeGun_GooCoat");
			gooCoat.transform.SetParent(root.transform, false);
			gooCoat.transform.localPosition = Vector3.zero;
			gooCoat.transform.localRotation = Quaternion.identity;
			gooCoat.transform.localScale = Vector3.one;
			Material goo = CreateGooMaterial();
			List<Renderer> targetRenderers = GetTargetRenderers(root);
			if (targetRenderers.Count == 0)
			{
				return;
			}
			int num = 42;
			foreach (Renderer item2 in targetRenderers)
			{
				if (!((Object)(object)item2 == (Object)null) && Object.op_Implicit((Object)(object)item2))
				{
					AddRendererMeshShell(gooCoat.transform, item2, goo);
					int patchCountForRenderer = GetPatchCountForRenderer(item2, num);
					for (int i = 0; i < patchCountForRenderer; i++)
					{
						GameObject item = AddAttachedGooPatch(item2, goo, i);
						gooPatches.Add(item);
					}
					num -= patchCountForRenderer;
					if (num <= 0)
					{
						break;
					}
				}
			}
		}

		private static int GetPatchCountForRenderer(Renderer renderer, int remainingBudget)
		{
			//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_0009: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = renderer.bounds;
			return Mathf.Clamp(Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)) * 5.5f), 4, 10), 0, remainingBudget);
		}

		private void AddRendererMeshShell(Transform parent, Renderer source, Material goo)
		{
			//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_0009: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = source.bounds;
			float num = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z));
			if (num <= 0.01f || num > 4.75f)
			{
				return;
			}
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((source is SkinnedMeshRenderer) ? source : null);
			if (val != null)
			{
				if (!((Object)(object)val.sharedMesh == (Object)null))
				{
					AddSkinnedShell(parent, val, goo, 1.055f);
					AddSkinnedShell(parent, val, goo, 1.095f);
				}
				return;
			}
			MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
			if (!((Object)(object)component == (Object)null) && !((Object)(object)component.sharedMesh == (Object)null))
			{
				AddStaticShell(parent, source, component.sharedMesh, goo, 1.055f);
				AddStaticShell(parent, source, component.sharedMesh, goo, 1.095f);
			}
		}

		private void AddSkinnedShell(Transform parent, SkinnedMeshRenderer source, Material goo, float scaleMultiplier)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = CreateShellObject(parent, ((Component)source).transform, scaleMultiplier);
			SkinnedMeshRenderer obj = val.AddComponent<SkinnedMeshRenderer>();
			obj.sharedMesh = source.sharedMesh;
			obj.bones = source.bones;
			obj.rootBone = source.rootBone;
			((Renderer)obj).localBounds = ((Renderer)source).localBounds;
			obj.updateWhenOffscreen = true;
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).materials = MakeMaterialArray(Mathf.Max(1, ((Renderer)source).sharedMaterials.Length), goo);
			gooPatches.Add(val);
		}

		private void AddStaticShell(Transform parent, Renderer source, Mesh mesh, Material goo, float scaleMultiplier)
		{
			GameObject val = CreateShellObject(parent, ((Component)source).transform, scaleMultiplier);
			val.AddComponent<MeshFilter>().sharedMesh = mesh;
			MeshRenderer obj = val.AddComponent<MeshRenderer>();
			((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
			((Renderer)obj).receiveShadows = false;
			((Renderer)obj).materials = MakeMaterialArray(Mathf.Max(1, source.sharedMaterials.Length), goo);
			gooPatches.Add(val);
		}

		private static GameObject CreateShellObject(Transform parent, Transform source, float scaleMultiplier)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: 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_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			GameObject val = new GameObject($"goo_mesh_shell_{((Object)source).name}_{scaleMultiplier:0.000}");
			val.transform.SetParent(parent, true);
			val.transform.SetPositionAndRotation(source.position, source.rotation);
			val.transform.localScale = source.lossyScale * scaleMultiplier;
			val.AddComponent<SlimeShellFollower>().Init(source, scaleMultiplier);
			return val;
		}

		private static Material[] MakeMaterialArray(int count, Material material)
		{
			Material[] array = (Material[])(object)new Material[count];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = material;
			}
			return array;
		}

		private static GameObject AddAttachedGooPatch(Renderer target, Material goo, int index)
		{
			//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_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_001b: 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_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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)
			//IL_00ab: 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)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: 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_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = target.bounds;
			Vector3 extents = ((Bounds)(ref bounds)).extents;
			float num = Mathf.Clamp(Mathf.Max(extents.x, Mathf.Max(extents.y, extents.z)) * 0.2f, 0.045f, 0.24f);
			Vector3 val = (Vector3)((index % 6) switch
			{
				0 => Vector3.up, 
				1 => Vector3.down, 
				2 => Vector3.right, 
				3 => Vector3.left, 
				4 => Vector3.forward, 
				_ => Vector3.back, 
			});
			Vector3 val2 = default(Vector3);
			((Vector3)(ref val2))..ctor(Random.Range(0f - extents.x, extents.x) * 0.22f, Random.Range(0f - extents.y, extents.y) * 0.22f, Random.Range(0f - extents.z, extents.z) * 0.22f);
			Vector3 val3 = default(Vector3);
			((Vector3)(ref val3))..ctor(val.x * extents.x * 0.78f, val.y * extents.y * 0.78f, val.z * extents.z * 0.78f);
			GameObject obj = CreateGooSphere("goo_body_patch", ((Bounds)(ref bounds)).center + val3 + val2, Quaternion.LookRotation((((Vector3)(ref val)).sqrMagnitude > 0.01f) ? val : Vector3.forward, Vector3.up) * Random.rotation, new Vector3(num * Random.Range(1.15f, 1.9f), num * Random.Range(0.18f, 0.38f), num * Random.Range(0.8f, 1.35f)), goo);
			obj.transform.SetParent(((Component)target).transform, true);
			return obj;
		}

		private static GameObject CreateGooSphere(string name, Vector3 position, Quaternion rotation, Vector3 scale, Material goo)
		{
			//IL_0013: 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_0020: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)obj).name = name;
			obj.transform.SetPositionAndRotation(position, rotation);
			obj.transform.localScale = scale;
			Collider val = default(Collider);
			if (obj.TryGetComponent<Collider>(ref val))
			{
				Object.Destroy((Object)(object)val);
			}
			Renderer val2 = default(Renderer);
			if (obj.TryGetComponent<Renderer>(ref val2))
			{
				val2.shadowCastingMode = (ShadowCastingMode)0;
				val2.receiveShadows = false;
				val2.material = goo;
			}
			return obj;
		}

		private static List<Renderer> GetTargetRenderers(GameObject root)
		{
			List<Renderer> list = new List<Renderer>();
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (ShouldUseRendererForGoo(val))
				{
					list.Add(val);
				}
			}
			return list;
		}

		private static bool ShouldUseRendererForGoo(Renderer renderer)
		{
			//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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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)
			if ((Object)(object)renderer == (Object)null || !Object.op_Implicit((Object)(object)renderer) || !renderer.enabled || IsGooCoatRenderer(renderer))
			{
				return false;
			}
			if (renderer is LineRenderer || renderer is TrailRenderer || ((object)renderer).GetType().Name.Contains("Particle"))
			{
				return false;
			}
			Bounds bounds = renderer.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			if (((Vector3)(ref size)).sqrMagnitude <= 0.0001f)
			{
				return false;
			}
			bounds = renderer.bounds;
			float x = ((Bounds)(ref bounds)).size.x;
			bounds = renderer.bounds;
			float y = ((Bounds)(ref bounds)).size.y;
			bounds = renderer.bounds;
			if (Mathf.Max(x, Mathf.Max(y, ((Bounds)(ref bounds)).size.z)) > 4.75f)
			{
				return false;
			}
			Mesh rendererMesh = GetRendererMesh(renderer);
			if ((Object)(object)rendererMesh == (Object)null)
			{
				return false;
			}
			string text = GetTransformPath(((Component)renderer).transform).ToLowerInvariant();
			if (text.Contains("collider") || text.Contains("hitbox") || text.Contains("hurtbox") || text.Contains("debug") || text.Contains("gizmo") || text.Contains("ui") || text.Contains("icon"))
			{
				return false;
			}
			if (IsSuspiciousUtilitySphere(renderer, rendererMesh, text))
			{
				return false;
			}
			return true;
		}

		private static bool ShouldUseRendererForTint(Renderer renderer)
		{
			//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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)renderer == (Object)null || !Object.op_Implicit((Object)(object)renderer) || !renderer.enabled || IsGooCoatRenderer(renderer))
			{
				return false;
			}
			if (renderer is LineRenderer || renderer is TrailRenderer || ((object)renderer).GetType().Name.Contains("Particle"))
			{
				return false;
			}
			Bounds bounds = renderer.bounds;
			Vector3 size = ((Bounds)(ref bounds)).size;
			if (((Vector3)(ref size)).sqrMagnitude <= 0.0001f)
			{
				return false;
			}
			string text = GetTransformPath(((Component)renderer).transform).ToLowerInvariant();
			if (text.Contains("collider") || text.Contains("hitbox") || text.Contains("hurtbox") || text.Contains("debug") || text.Contains("gizmo") || text.Contains("ui") || text.Contains("icon"))
			{
				return false;
			}
			Material[] sharedMaterials = renderer.sharedMaterials;
			if (sharedMaterials == null || sharedMaterials.Length == 0)
			{
				return true;
			}
			bool result = false;
			Material[] array = sharedMaterials;
			foreach (Material val in array)
			{
				if (!((Object)(object)val == (Object)null) && (!val.HasProperty("_Color") || val.color.a > 0.18f))
				{
					result = true;
					break;
				}
			}
			return result;
		}

		private static GameObject FindVisualRoot(GameObject effectRoot)
		{
			Transform val = effectRoot.transform;
			GameObject result = effectRoot;
			int num = CountGooRenderers(effectRoot);
			for (int i = 0; i < 5; i++)
			{
				if (!((Object)(object)val.parent != (Object)null))
				{
					break;
				}
				val = val.parent;
				int num2 = CountGooRenderers(((Component)val).gameObject);
				if (num2 > num && num2 <= 24 && HasReasonableRendererBounds(((Component)val).gameObject))
				{
					result = ((Component)val).gameObject;
					num = num2;
				}
			}
			return result;
		}

		private static int CountGooRenderers(GameObject root)
		{
			int num = 0;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (ShouldUseRendererForGoo(componentsInChildren[i]))
				{
					num++;
				}
			}
			return num;
		}

		private static bool HasReasonableRendererBounds(GameObject root)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: 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)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			bool flag = false;
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(root.transform.position, Vector3.zero);
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				if (ShouldUseRendererForGoo(val))
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			if (!flag)
			{
				return false;
			}
			return Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)) <= 5.5f;
		}

		private static int CountTintableRenderers(GameObject root)
		{
			int num = 0;
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				if (ShouldUseRendererForTint(componentsInChildren[i]))
				{
					num++;
				}
			}
			return num;
		}

		private static Mesh? GetRendererMesh(Renderer renderer)
		{
			SkinnedMeshRenderer val = (SkinnedMeshRenderer)(object)((renderer is SkinnedMeshRenderer) ? renderer : null);
			if (val != null)
			{
				return val.sharedMesh;
			}
			MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>();
			if (component == null)
			{
				return null;
			}
			return component.sharedMesh;
		}

		private static bool IsSuspiciousUtilitySphere(Renderer renderer, Mesh mesh, string lowerName)
		{
			//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_0009: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			Bounds bounds = renderer.bounds;
			float num = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z));
			float num2 = Mathf.Max(0.001f, Mathf.Min(((Bounds)(ref bounds)).size.x, Mathf.Min(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)));
			bool num3 = num / num2 < 1.28f;
			bool flag = lowerName.Contains("range") || lowerName.Contains("vision") || lowerName.Contains("sight") || lowerName.Contains("detect") || lowerName.Contains("trigger") || lowerName.Contains("area") || lowerName.Contains("scan") || lowerName.Contains("sphere");
			if (num3 && num > 1.2f)
			{
				if (!flag)
				{
					return mesh.vertexCount < 900;
				}
				return true;
			}
			return false;
		}

		private static string GetTransformPath(Transform transform)
		{
			string text = ((Object)transform).name;
			Transform parent = transform.parent;
			while ((Object)(object)parent != (Object)null)
			{
				text = ((Object)parent).name + "/" + text;
				parent = parent.parent;
			}
			return text;
		}

		private static void AddWorldGooShell(Transform parent, Material goo, Bounds bounds, float expand, string name)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: 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)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)obj).name = name;
			obj.transform.position = ((Bounds)(ref bounds)).center;
			obj.transform.rotation = Random.rotation;
			obj.transform.localScale = new Vector3(Mathf.Max(((Bounds)(ref bounds)).size.x * expand, 0.22f), Mathf.Max(((Bounds)(ref bounds)).size.y * expand, 0.22f), Mathf.Max(((Bounds)(ref bounds)).size.z * expand, 0.22f));
			obj.transform.SetParent(parent, true);
			Collider val = default(Collider);
			if (obj.TryGetComponent<Collider>(ref val))
			{
				Object.Destroy((Object)(object)val);
			}
			Renderer val2 = default(Renderer);
			if (obj.TryGetComponent<Renderer>(ref val2))
			{
				val2.material = goo;
			}
		}

		private static void AddWorldGooBlobs(Transform parent, Material goo, Bounds bounds, int count)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			//IL_006c: 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_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: 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)
			//IL_00c6: 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_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(Mathf.Max(((Bounds)(ref bounds)).extents.x, Mathf.Max(((Bounds)(ref bounds)).extents.y, ((Bounds)(ref bounds)).extents.z)) * 0.22f, 0.075f, 0.42f);
			Collider val = default(Collider);
			Renderer val2 = default(Renderer);
			for (int i = 0; i < count; i++)
			{
				Vector3 extents = ((Bounds)(ref bounds)).extents;
				Vector3 position = ((Bounds)(ref bounds)).center + new Vector3(Random.Range(0f - extents.x, extents.x), Random.Range(0f - extents.y, extents.y), Random.Range(0f - extents.z, extents.z));
				int num2 = Random.Range(0, 3);
				float num3 = ((Random.value < 0.5f) ? (-1f) : 1f);
				switch (num2)
				{
				case 0:
					position.x = ((Bounds)(ref bounds)).center.x + extents.x * num3;
					break;
				case 1:
					position.y = ((Bounds)(ref bounds)).center.y + extents.y * num3;
					break;
				default:
					position.z = ((Bounds)(ref bounds)).center.z + extents.z * num3;
					break;
				}
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj).name = "goo_surface_blob";
				obj.transform.position = position;
				obj.transform.rotation = Random.rotation;
				float num4 = Random.Range(num * 0.7f, num * 1.35f);
				obj.transform.localScale = new Vector3(num4 * Random.Range(0.8f, 1.6f), num4 * Random.Range(0.35f, 0.85f), num4 * Random.Range(0.8f, 1.6f));
				obj.transform.SetParent(parent, true);
				if (obj.TryGetComponent<Collider>(ref val))
				{
					Object.Destroy((Object)(object)val);
				}
				if (obj.TryGetComponent<Renderer>(ref val2))
				{
					val2.material = goo;
				}
			}
		}

		private void ApplyGooCoat(GameObject root)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_005a: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: 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_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: 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)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)gooCoat != (Object)null)
			{
				Object.Destroy((Object)(object)gooCoat);
			}
			Bounds renderBounds = GetRenderBounds(root);
			gooCoat = new GameObject("SlimeGun_GooCoat");
			gooCoat.transform.SetParent(root.transform, false);
			gooCoat.transform.localPosition = root.transform.InverseTransformPoint(((Bounds)(ref renderBounds)).center);
			gooCoat.transform.localRotation = Quaternion.identity;
			gooCoat.transform.localScale = Vector3.one;
			Material material = CreateGooMaterial();
			Vector3 lossyScale = root.transform.lossyScale;
			Vector3 val = default(Vector3);
			((Vector3)(ref val))..ctor(((Bounds)(ref renderBounds)).extents.x / Mathf.Max(0.001f, Mathf.Abs(lossyScale.x)), ((Bounds)(ref renderBounds)).extents.y / Mathf.Max(0.001f, Mathf.Abs(lossyScale.y)), ((Bounds)(ref renderBounds)).extents.z / Mathf.Max(0.001f, Mathf.Abs(lossyScale.z)));
			Collider val2 = default(Collider);
			Renderer val3 = default(Renderer);
			for (int i = 0; i < 5; i++)
			{
				float num = 1.08f + (float)i * 0.09f;
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj).name = "goo_body_shell";
				obj.transform.SetParent(gooCoat.transform, false);
				obj.transform.localPosition = new Vector3(Random.Range(0f - val.x, val.x) * 0.08f, Random.Range(0f - val.y, val.y) * 0.06f, Random.Range(0f - val.z, val.z) * 0.08f);
				obj.transform.localScale = new Vector3(val.x * 2f * num, val.y * 2f * num, val.z * 2f * num);
				obj.transform.localRotation = Random.rotation;
				if (obj.TryGetComponent<Collider>(ref val2))
				{
					Object.Destroy((Object)(object)val2);
				}
				if (obj.TryGetComponent<Renderer>(ref val3))
				{
					val3.material = material;
				}
			}
			float num2 = Mathf.Clamp(Mathf.Max(new float[3] { val.x, val.y, val.z }) * 0.32f, 0.12f, 0.55f);
			Collider val4 = default(Collider);
			Renderer val5 = default(Renderer);
			for (int j = 0; j < 36; j++)
			{
				GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj2).name = "goo_surface_blob";
				obj2.transform.SetParent(gooCoat.transform, false);
				Vector3 onUnitSphere = Random.onUnitSphere;
				obj2.transform.localPosition = new Vector3(onUnitSphere.x * val.x * Random.Range(0.82f, 1.18f), onUnitSphere.y * val.y * Random.Range(0.82f, 1.18f), onUnitSphere.z * val.z * Random.Range(0.82f, 1.18f));
				obj2.transform.localScale = new Vector3(Random.Range(0.85f, 1.75f) * num2, Random.Range(0.24f, 0.56f) * num2, Random.Range(0.85f, 1.75f) * num2);
				obj2.transform.localRotation = Random.rotation;
				if (obj2.TryGetComponent<Collider>(ref val4))
				{
					Object.Destroy((Object)(object)val4);
				}
				if (obj2.TryGetComponent<Renderer>(ref val5))
				{
					val5.material = material;
				}
			}
		}

		private static Bounds GetRenderBounds(GameObject root)
		{
			//IL_0010: 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_0085: 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_007f: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>();
			bool flag = false;
			Bounds bounds = default(Bounds);
			((Bounds)(ref bounds))..ctor(root.transform.position, Vector3.one);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null) && Object.op_Implicit((Object)(object)val) && !IsGooCoatRenderer(val))
				{
					if (!flag)
					{
						bounds = val.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref bounds)).Encapsulate(val.bounds);
					}
				}
			}
			if (!flag)
			{
				return new Bounds(root.transform.position, Vector3.one);
			}
			return bounds;
		}

		private static bool IsGooCoatRenderer(Renderer renderer)
		{
			Transform val = ((Component)renderer).transform;
			while ((Object)(object)val != (Object)null)
			{
				if (((Object)val).name == "SlimeGun_GooCoat")
				{
					return true;
				}
				val = val.parent;
			}
			return false;
		}

		private static Material CreateGooMaterial()
		{
			//IL_0026: 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_002c: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: 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)
			Shader val = Shader.Find("Hidden/Internal-Colored");
			Material val2 = (((Object)(object)val != (Object)null) ? new Material(val) : new Material(Shader.Find("Standard")));
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(0.06f, 1f, 0.16f, 0.34f);
			if (val2.HasProperty("_Color"))
			{
				val2.SetColor("_Color", val3);
			}
			if (val2.HasProperty("_BaseColor"))
			{
				val2.SetColor("_BaseColor", val3);
			}
			try
			{
				val2.SetFloat("_Mode", 3f);
				val2.SetInt("_SrcBlend", 5);
				val2.SetInt("_DstBlend", 10);
				val2.SetInt("_ZWrite", 0);
				val2.SetInt("_ZTest", 8);
				val2.SetInt("_Cull", 0);
				val2.DisableKeyword("_ALPHATEST_ON");
				val2.EnableKeyword("_ALPHABLEND_ON");
				val2.DisableKeyword("_ALPHAPREMULTIPLY_ON");
				val2.renderQueue = 4000;
			}
			catch
			{
			}
			try
			{
				val2.SetFloat("_Surface", 1f);
				val2.SetFloat("_Blend", 0f);
				val2.EnableKeyword("_SURFACE_TYPE_TRANSPARENT");
			}
			catch
			{
			}
			if (val2.HasProperty("_EmissionColor"))
			{
				val2.EnableKeyword("_EMISSION");
				val2.SetColor("_EmissionColor", new Color(0.035f, 1.4f, 0.06f));
			}
			return val2;
		}

		private void ClearTint()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			foreach (MaterialTintState tintedState in tintedStates)
			{
				if (!((Object)(object)tintedState.material == (Object)null))
				{
					if (tintedState.material.HasProperty("_Color"))
					{
						tintedState.material.SetColor("_Color", tintedState.originalColor);
					}
					if (tintedState.material.HasProperty("_BaseColor"))
					{
						tintedState.material.SetColor("_BaseColor", tintedState.originalColor);
					}
					if (tintedState.material.HasProperty("_EmissionColor"))
					{
						tintedState.material.SetColor("_EmissionColor", tintedState.originalEmission);
					}
					if (!tintedState.hadEmission)
					{
						tintedState.material.DisableKeyword("_EMISSION");
					}
				}
			}
			tintedStates.Clear();
			foreach (RendererTintState rendererTintState in rendererTintStates)
			{
				if ((Object)(object)rendererTintState.renderer != (Object)null && Object.op_Implicit((Object)(object)rendererTintState.renderer))
				{
					rendererTintState.renderer.SetPropertyBlock(rendererTintState.originalBlock);
				}
			}
			rendererTintStates.Clear();
			if ((Object)(object)gooCoat != (Object)null)
			{
				Object.Destroy((Object)(object)gooCoat);
				gooCoat = null;
			}
			foreach (GameObject gooPatch in gooPatches)
			{
				if ((Object)(object)gooPatch != (Object)null && Object.op_Implicit((Object)(object)gooPatch))
				{
					Object.Destroy((Object)(object)gooPatch);
				}
			}
			gooPatches.Clear();
		}
	}
	public sealed class SlimeGlob : MonoBehaviour
	{
		private readonly HashSet<int> hitInstanceIds = new HashSet<int>();

		private float spawnTime;

		private float expiresAt;

		private float slowAmount;

		private float slowDuration;

		private float tickInterval;

		private int enemyDamagePerTick;

		private int playerHealPerTick;

		private SlimeGunNetworkProxy? networkProxy;

		private const float ContactRadius = 0.9f;

		internal void Initialize(float lifetime, float slowAmount, float slowDuration, float tickInterval, int enemyDamagePerTick, int playerHealPerTick, SlimeGunNetworkProxy? networkProxy)
		{
			spawnTime = Time.time;
			expiresAt = Time.time + lifetime;
			this.slowAmount = slowAmount;
			this.slowDuration = slowDuration;
			this.tickInterval = tickInterval;
			this.enemyDamagePerTick = enemyDamagePerTick;
			this.playerHealPerTick = playerHealPerTick;
			this.networkProxy = networkProxy;
		}

		private void Update()
		{
			if (Time.time >= expiresAt)
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
			else if (Time.time - spawnTime >= 0.15f)
			{
				CheckOverlaps();
			}
		}

		private void OnTriggerEnter(Collider other)
		{
			if (!(Time.time - spawnTime < 0.15f))
			{
				TryApplyToCollider(other);
			}
		}

		private void CheckOverlaps()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Collider[] array = Physics.OverlapSphere(((Component)this).transform.position, 0.9f, -1, (QueryTriggerInteraction)2);
			foreach (Collider val in array)
			{
				if ((Object)(object)val != (Object)null && TryApplyToCollider(val))
				{
					break;
				}
			}
		}

		private bool TryApplyToCollider(Collider other)
		{
			Enemy val = SlimeCombat.FindEnemy(other);
			if ((Object)(object)val != (Object)null && Object.op_Implicit((Object)(object)val) && hitInstanceIds.Add(((Object)val).GetInstanceID()))
			{
				if ((Object)(object)networkProxy != (Object)null && SemiFunc.IsMultiplayer())
				{
					networkProxy.RequestEnemyHit(val, slowDuration, slowAmount, enemyDamagePerTick, tickInterval);
					SlimeEffect.ApplyVisualToEnemy(val, slowDuration, slowAmount, enemyDamagePerTick, tickInterval);
				}
				else
				{
					SlimeEffect.ApplyToEnemy(val, slowDuration, slowAmount, enemyDamagePerTick, tickInterval);
				}
				Debug.Log((object)("[SlimeGun] Glob hit enemy: " + ((Object)val).name));
				Splat();
				return true;
			}
			PlayerController val2 = SlimeCombat.FindPlayer(other);
			if ((Object)(object)val2 != (Object)null && Object.op_Implicit((Object)(object)val2) && hitInstanceIds.Add(((Object)val2).GetInstanceID()))
			{
				if ((Object)(object)networkProxy != (Object)null && SemiFunc.IsMultiplayer())
				{
					networkProxy.RequestPlayerHit(val2, slowDuration, slowAmount, playerHealPerTick, tickInterval);
					SlimeEffect.ApplyVisualToPlayer(val2, slowDuration, slowAmount, playerHealPerTick, tickInterval);
				}
				else
				{
					SlimeEffect.ApplyToPlayer(val2, slowDuration, slowAmount, playerHealPerTick, tickInterval);
				}
				Debug.Log((object)("[SlimeGun] Glob hit player: " + ((Object)val2).name));
				Splat();
				return true;
			}
			return false;
		}

		private void Splat()
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
		}
	}
	public sealed class SlimeGunController : MonoBehaviour
	{
		private sealed class HeldGunState
		{
			public float SlimeTank;

			public float FireRequestedUntil;

			public float SprayAccumulator;

			public float Pressure;

			public float NextNetworkSprayAt;

			public bool Initialized;

			public Component? Battery;
		}

		private static readonly FieldInfo? PlayerAvatarIsLocalField = typeof(PlayerAvatar).GetField("isLocal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo? GrabbedPhysGrabObjectField = typeof(PhysGrabber).GetField("grabbedPhysGrabObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo? HeldByLocalPlayerField = typeof(PhysGrabObject).GetField("heldByLocalPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly FieldInfo? ToggleImpulseField = typeof(ItemToggle).GetField("toggleImpulse", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly Dictionary<int, HeldGunState> HeldGunStates = new Dictionary<int, HeldGunState>();

		private static readonly Dictionary<Type, FieldInfo?> BatteryLifeFields = new Dictionary<Type, FieldInfo>();

		private static readonly Dictionary<Type, FieldInfo?> BatteryActiveFields = new Dictionary<Type, FieldInfo>();

		private PlayerController? playerController;

		private float slimeTank;

		private float nextGlobAt;

		private bool inputUnavailableLogged;

		private const float GlobFireInterval = 0.05f;

		private const float TriggerRequestWindow = 0.18f;

		private const float PressureRisePerSecond = 7.5f;

		private const float PressureFallPerSecond = 5.5f;

		private const float SprayDropletsPerSecond = 70f;

		private const int MaxDropletsPerFrame = 6;

		private const float GlobLifetime = 0.75f;

		private const float GlobLaunchUpward = 0.1f;

		private const float SprayConeAngle = 2.25f;

		private static Material? _slimeMaterial;

		internal const string SlimeGunItemName = "Slime Gun";

		private const string BarrelMarkerName = "SlimeGun Barrel Origin";

		public float TankFraction
		{
			get
			{
				if (!(Plugin.TankCapacity.Value > 0f))
				{
					return 0f;
				}
				return slimeTank / Plugin.TankCapacity.Value;
			}
		}

		internal static void OnItemGunShoot(ItemGun gun)
		{
			if (SlimeGunRuntime.Enabled && !((Object)(object)gun == (Object)null) && Object.op_Implicit((Object)(object)gun))
			{
				PhysGrabObject val = ((Component)gun).GetComponent<PhysGrabObject>() ?? ((Component)gun).GetComponentInParent<PhysGrabObject>();
				int key = (((Object)(object)val != (Object)null) ? ((Object)val).GetInstanceID() : ((Object)gun).GetInstanceID());
				if (!HeldGunStates.TryGetValue(key, out HeldGunState value))
				{
					value = new HeldGunState
					{
						SlimeTank = Plugin.TankCapacity.Value,
						Initialized = true
					};
					HeldGunStates[key] = value;
				}
				value.FireRequestedUntil = Time.time + 0.18f;
				value.Pressure = Mathf.Max(value.Pressure, 0.25f);
			}
		}

		internal static void OnPhysGrabObjectUpdate(PhysGrabObject physGrabObject)
		{
			if (!SlimeGunRuntime.Enabled || (Object)(object)physGrabObject == (Object)null || !Object.op_Implicit((Object)(object)physGrabObject))
			{
				return;
			}
			ItemAttributes val = ((Component)physGrabObject).GetComponent<ItemAttributes>() ?? ((Component)physGrabObject).GetComponentInChildren<ItemAttributes>(true) ?? ((Component)physGrabObject).GetComponentInParent<ItemAttributes>();
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.item == (Object)null) && !(val.item.itemName != "Slime Gun"))
			{
				int instanceID = ((Object)physGrabObject).GetInstanceID();
				if (!HeldGunStates.TryGetValue(instanceID, out HeldGunState value))
				{
					value = new HeldGunState();
					HeldGunStates[instanceID] = value;
				}
				if (!value.Initialized)
				{
					value.SlimeTank = Plugin.TankCapacity.Value;
					value.Battery = FindBattery(((Component)physGrabObject).gameObject);
					SetBattery(value);
					value.Initialized = true;
				}
				if (!IsHeldByLocalPlayer(physGrabObject))
				{
					UpdateSprayState(value, firing: false, null, null, null);
					SetBattery(value);
					return;
				}
				bool firing;
				bool num = TryGetItemUseHeld(physGrabObject, out firing) && firing;
				bool flag = Time.time < value.FireRequestedUntil;
				bool firing2 = num || flag;
				Transform val2 = FindDeep(((Component)physGrabObject).transform, "SlimeGun Barrel Origin") ?? ((Component)physGrabObject).transform;
				Transform aim = (((Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance.cameraGameObject != (Object)null) ? PlayerController.instance.cameraGameObject.transform : val2);
				SlimeGunNetworkProxy networkProxy = EnsureNetworkProxy(physGrabObject);
				UpdateSprayState(value, firing2, val2, aim, networkProxy);
				BroadcastRemoteSpray(value, firing2, val2, aim, networkProxy);
				SetBattery(value);
			}
		}

		private void Start()
		{
			playerController = ((Component)this).GetComponent<PlayerController>();
			if ((Object)(object)playerController != (Object)null)
			{
				slimeTank = Plugin.TankCapacity.Value;
				Debug.Log((object)$"[SlimeGun] Controller attached to {((Object)playerController).name}. Tank={slimeTank:0.0}");
			}
		}

		private void Update()
		{
			if (!SlimeGunRuntime.Enabled || (Object)(object)playerController == (Object)null)
			{
				return;
			}
			Transform barrel;
			Transform aim;
			bool firing;
			if (!IsLocalController())
			{
				RechargeTank();
			}
			else if (!TryGetHeldSlimeGun(out barrel, out aim) || !TryGetFireHeld(out firing))
			{
				RechargeTank();
			}
			else if (firing && slimeTank > 0f)
			{
				slimeTank = Mathf.Max(0f, slimeTank - Plugin.TankDrainRate.Value * Time.deltaTime);
				if (Time.time >= nextGlobAt)
				{
					nextGlobAt = Time.time + 0.05f;
					FireSprayBurst(barrel, aim);
				}
			}
			else
			{
				RechargeTank();
			}
		}

		private bool IsLocalController()
		{
			if ((Object)(object)playerController == (Object)null || !Object.op_Implicit((Object)(object)playerController))
			{
				return false;
			}
			if ((Object)(object)PlayerController.instance != (Object)null && (Object)(object)PlayerController.instance != (Object)(object)playerController)
			{
				return false;
			}
			PlayerAvatar playerAvatarScript = playerController.playerAvatarScript;
			if ((Object)(object)playerAvatarScript == (Object)null || !Object.op_Implicit((Object)(object)playerAvatarScript))
			{
				return (Object)(object)PlayerController.instance == (Object)(object)playerController;
			}
			object obj = PlayerAvatarIsLocalField?.GetValue(playerAvatarScript);
			if (obj is bool)
			{
				return (bool)obj;
			}
			return (Object)(object)PlayerController.instance == (Object)(object)playerController;
		}

		private bool TryGetFireHeld(out bool firing)
		{
			try
			{
				firing = SemiFunc.InputHold((InputKey)2);
				return true;
			}
			catch (Exception ex)
			{
				firing = false;
				if (!inputUnavailableLogged)
				{
					inputUnavailableLogged = true;
					Debug.LogWarning((object)("[SlimeGun] Fire input is unavailable; slime firing is disabled for this player controller. " + ex.GetType().Name + ": " + ex.Message));
				}
				return false;
			}
		}

		private static bool TryGetItemUseHeld(PhysGrabObject physGrabObject, out bool firing)
		{
			bool flag = false;
			try
			{
				flag = SemiFunc.InputHold((InputKey)2);
			}
			catch
			{
				flag = false;
			}
			ItemToggle val = ((Component)physGrabObject).GetComponent<ItemToggle>() ?? ((Component)physGrabObject).GetComponentInChildren<ItemToggle>(true) ?? ((Component)physGrabObject).GetComponentInParent<ItemToggle>();
			bool flag2 = default(bool);
			int num;
			if ((Object)(object)val != (Object)null)
			{
				object obj2 = ToggleImpulseField?.GetValue(val);
				if (obj2 is bool)
				{
					flag2 = (bool)obj2;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			bool flag3 = (byte)((uint)num & (flag2 ? 1u : 0u)) != 0;
			firing = flag || ((Object)(object)val != (Object)null && (val.toggleState || flag3));
			return true;
		}

		private static bool IsHeldByLocalPlayer(PhysGrabObject physGrabObject)
		{
			object obj = HeldByLocalPlayerField?.GetValue(physGrabObject);
			if (obj is bool)
			{
				return (bool)obj;
			}
			PhysGrabber instance = PhysGrabber.instance;
			if ((Object)(object)instance == (Object)null || !Object.op_Implicit((Object)(object)instance))
			{
				return false;
			}
			object? obj2 = GrabbedPhysGrabObjectField?.GetValue(instance);
			PhysGrabObject val = (PhysGrabObject)((obj2 is PhysGrabObject) ? obj2 : null);
			if ((Object)(object)val != (Object)null)
			{
				return (Object)(object)val == (Object)(object)physGrabObject;
			}
			return false;
		}

		private bool TryGetHeldSlimeGun(out Transform barrel, out Transform aim)
		{
			barrel = null;
			aim = null;
			PhysGrabber instance = PhysGrabber.instance;
			if ((Object)(object)instance == (Object)null || !Object.op_Implicit((Object)(object)instance))
			{
				return false;
			}
			object? obj = GrabbedPhysGrabObjectField?.GetValue(instance);
			PhysGrabObject val = (PhysGrabObject)((obj is PhysGrabObject) ? obj : null);
			if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val))
			{
				return false;
			}
			ItemAttributes val2 = ((Component)val).GetComponent<ItemAttributes>() ?? ((Component)val).GetComponentInChildren<ItemAttributes>(true) ?? ((Component)val).GetComponentInParent<ItemAttributes>();
			if ((Object)(object)val2 == (Object)null || (Object)(object)val2.item == (Object)null || val2.item.itemName != "Slime Gun")
			{
				return false;
			}
			barrel = FindDeep(((Component)val).transform, "SlimeGun Barrel Origin") ?? ((Component)val).transform;
			aim = (Transform)(((Object)(object)playerController.cameraGameObject != (Object)null) ? ((object)playerController.cameraGameObject.transform) : ((object)barrel));
			return true;
		}

		private void RechargeTank()
		{
			slimeTank = Mathf.Min(Plugin.TankCapacity.Value, slimeTank + Plugin.TankRechargeRate.Value * Time.deltaTime);
		}

		private static void RechargeTank(HeldGunState state)
		{
			state.SlimeTank = Mathf.Min(Plugin.TankCapacity.Value, state.SlimeTank + Plugin.TankRechargeRate.Value * Time.deltaTime);
		}

		private static void UpdateSprayState(HeldGunState state, bool firing, Transform? barrel, Transform? aim, SlimeGunNetworkProxy? networkProxy)
		{
			float num = ((firing && state.SlimeTank > 0f) ? 1f : 0f);
			float num2 = ((num > state.Pressure) ? 7.5f : 5.5f);
			state.Pressure = Mathf.MoveTowards(state.Pressure, num, num2 * Time.deltaTime);
			if (state.Pressure <= 0.02f || (Object)(object)barrel == (Object)null || (Object)(object)aim == (Object)null || state.SlimeTank <= 0f)
			{
				state.SprayAccumulator = 0f;
				if (!firing)
				{
					RechargeTank(state);
				}
				return;
			}
			float num3 = Mathf.Min(Plugin.TankDrainRate.Value, 4f);
			state.SlimeTank = Mathf.Max(0f, state.SlimeTank - num3 * state.Pressure * Time.deltaTime);
			state.SprayAccumulator += Time.deltaTime * Mathf.Lerp(28f, 70f, state.Pressure);
			int num4 = Mathf.Min(6, Mathf.FloorToInt(state.SprayAccumulator));
			if (num4 > 0)
			{
				state.SprayAccumulator -= num4;
				for (int i = 0; i < num4; i++)
				{
					FireGlob(barrel, aim, state.Pressure, networkProxy);
				}
			}
		}

		private static void BroadcastRemoteSpray(HeldGunState state, bool firing, Transform barrel, Transform aim, SlimeGunNetworkProxy? networkProxy)
		{
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (firing && !(state.Pressure <= 0.05f) && !((Object)(object)networkProxy == (Object)null) && !(Time.time < state.NextNetworkSprayAt))
			{
				state.NextNetworkSprayAt = Time.time + 0.08f;
				networkProxy.BroadcastSpray(barrel.position, aim.forward, state.Pressure);
			}
		}

		private static SlimeGunNetworkProxy? EnsureNetworkProxy(PhysGrabObject physGrabObject)
		{
			PhotonView val = ((Component)physGrabObject).GetComponent<PhotonView>() ?? ((Component)physGrabObject).GetComponentInChildren<PhotonView>(true) ?? ((Component)physGrabObject).GetComponentInParent<PhotonView>();
			if ((Object)(object)val == (Object)null || !Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			SlimeGunNetworkProxy slimeGunNetworkProxy = ((Component)val).GetComponent<SlimeGunNetworkProxy>();
			if ((Object)(object)slimeGunNetworkProxy == (Object)null || !Object.op_Implicit((Object)(object)slimeGunNetworkProxy))
			{
				slimeGunNetworkProxy = ((Component)val).gameObject.AddComponent<SlimeGunNetworkProxy>();
			}
			slimeGunNetworkProxy.SetPhotonView(val);
			return slimeGunNetworkProxy;
		}

		private static Component? FindBattery(GameObject root)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if ((Object)(object)val != (Object)null && ((object)val).GetType().Name == "ItemBattery")
				{
					TrySetBatteryActive(val, active: true);
					return val;
				}
			}
			return null;
		}

		private static void SetBattery(HeldGunState state)
		{
			if (!((Object)(object)state.Battery == (Object)null) && Object.op_Implicit((Object)(object)state.Battery))
			{
				Type type = ((object)state.Battery).GetType();
				if (!BatteryLifeFields.TryGetValue(type, out FieldInfo value))
				{
					value = type.GetField("batteryLife", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					BatteryLifeFields[type] = value;
				}
				if (value != null)
				{
					value.SetValue(state.Battery, Mathf.Clamp(state.SlimeTank, 0f, Plugin.TankCapacity.Value));
				}
				TrySetBatteryActive(state.Battery, active: true);
			}
		}

		private static void TrySetBatteryActive(Component battery, bool active)
		{
			Type type = ((object)battery).GetType();
			if (!BatteryActiveFields.TryGetValue(type, out FieldInfo value))
			{
				value = type.GetField("batteryActive", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				BatteryActiveFields[type] = value;
			}
			value?.SetValue(battery, active);
		}

		private static void FireSprayBurst(Transform barrel, Transform aim, float pressure = 1f)
		{
			for (int i = 0; i < 2; i++)
			{
				FireGlob(barrel, aim, pressure, null);
			}
		}

		private static void FireGlob(Transform barrel, Transform aim, float pressure, SlimeGunNetworkProxy? networkProxy)
		{
			//IL_0001: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//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_00d7: 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)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = barrel.right * Random.Range(-0.024f, 0.024f);
			Vector3 val2 = barrel.up * Random.Range(-0.02f, 0.02f);
			GameObject obj = CreateGlobObject(barrel.position + val + val2);
			Vector3 val3 = Quaternion.Euler(Random.Range(-2.25f, 2.25f), Random.Range(-2.25f, 2.25f), Random.Range(-2f, 2f)) * aim.forward;
			Rigidbody val4 = default(Rigidbody);
			if (obj.TryGetComponent<Rigidbody>(ref val4))
			{
				float num = Mathf.Max(Plugin.GlobSpeed.Value, 12f);
				float num2 = Mathf.Lerp(num * 0.7f, num * 1.15f, pressure);
				float num3 = Random.Range(num2 * 0.82f, num2);
				val4.velocity = ((Vector3)(ref val3)).normalized * num3 + Vector3.up * Random.Range(0f, 0.1f);
			}
			obj.AddComponent<SlimeGlob>().Initialize(0.75f, Plugin.SlowAmount.Value, Plugin.SlimeDuration.Value, Plugin.TickInterval.Value, Mathf.RoundToInt(Plugin.DamagePerTick.Value), Mathf.RoundToInt(Plugin.HealPerTick.Value), networkProxy);
		}

		internal static void SpawnRemoteVisualSpray(Vector3 barrelPosition, Vector3 aimForward, float pressure, int seed)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			State state = Random.state;
			Random.InitState(seed);
			try
			{
				int num = Mathf.Clamp(Mathf.RoundToInt(Mathf.Lerp(2f, 6f, pressure)), 2, 6);
				Vector3 val = ((((Vector3)(ref aimForward)).sqrMagnitude > 0.01f) ? ((Vector3)(ref aimForward)).normalized : Vector3.forward);
				Rigidbody val3 = default(Rigidbody);
				for (int i = 0; i < num; i++)
				{
					GameObject obj = CreateGlobObject(barrelPosition);
					Vector3 val2 = Quaternion.Euler(Random.Range(-2.25f, 2.25f), Random.Range(-2.25f, 2.25f), Random.Range(-2f, 2f)) * val;
					if (obj.TryGetComponent<Rigidbody>(ref val3))
					{
						float num2 = Mathf.Max(Plugin.GlobSpeed.Value, 12f);
						float num3 = Mathf.Lerp(num2 * 0.7f, num2 * 1.15f, pressure);
						val3.velocity = ((Vector3)(ref val2)).normalized * Random.Range(num3 * 0.82f, num3);
					}
					obj.AddComponent<SlimeVisualGlob>().Initialize(0.75f);
				}
			}
			finally
			{
				Random.state = state;
			}
		}

		private static GameObject CreateGlobObject(Vector3 position)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
			((Object)obj).name = "SlimeGlob";
			obj.transform.position = position;
			obj.transform.localScale = new Vector3(Random.Range(0.075f, 0.135f), Random.Range(0.055f, 0.11f), Random.Range(0.075f, 0.135f));
			Collider val = default(Collider);
			if (obj.TryGetComponent<Collider>(ref val))
			{
				val.isTrigger = true;
			}
			Rigidbody obj2 = obj.AddComponent<Rigidbody>();
			obj2.useGravity = true;
			obj2.collisionDetectionMode = (CollisionDetectionMode)2;
			obj2.useGravity = false;
			obj2.drag = 1.4f;
			obj2.angularDrag = 2f;
			Renderer val2 = default(Renderer);
			if (obj.TryGetComponent<Renderer>(ref val2))
			{
				val2.material = GetOrCreateSlimeMaterial();
			}
			return obj;
		}

		private static Material GetOrCreateSlimeMaterial()
		{
			if ((Object)(object)_slimeMaterial != (Object)null && Object.op_Implicit((Object)(object)_slimeMaterial))
			{
				return _slimeMaterial;
			}
			_slimeMaterial = CreateSlimeMaterial();
			return _slimeMaterial;
		}

		private static Material CreateSlimeMaterial()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_0036: 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)
			GameObject val = GameObject.CreatePrimitive((PrimitiveType)0);
			Material val2;
			try
			{
				val2 = new Material(val.GetComponent<Renderer>().sharedMaterial);
			}
			finally
			{
				Object.Destroy((Object)(object)val);
			}
			val2.color = new Color(0.18f, 0.95f, 0.12f, 1f);
			TrySetTransparent(val2);
			if (val2.HasProperty("_EmissionColor"))
			{
				val2.EnableKeyword("_EMISSION");
				val2.SetColor("_EmissionColor", new Color(0.04f, 0.55f, 0.04f));
			}
			return val2