Decompiled source of HarpoonLongboat v1.0.0

HarpoonLongboat.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Threading;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("HarpoonLongboat")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HarpoonLongboat")]
[assembly: AssemblyTitle("HarpoonLongboat")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace HarpoonLongboat
{
	public class BoatCatapult : MonoBehaviour
	{
		public struct HudData
		{
			public float Angle;

			public float Aim;

			public float Power;

			public int AmmoCount;

			public string AmmoName;

			public float Cooldown;

			public bool Deployed;
		}

		public Catapult Source;

		public Transform Lift;

		public Transform PitchPivot;

		public static readonly HashSet<BoatCatapult> Active = new HashSet<BoatCatapult>();

		private ZNetView m_nview;

		private Container m_store;

		private Transform m_arm;

		private Transform m_shoot;

		private Quaternion m_armBaseRot = Quaternion.identity;

		private Quaternion m_pivotBaseRot = Quaternion.identity;

		private float m_angle;

		private float m_yaw;

		private float m_power = 0.5f;

		private bool m_deployed;

		private float m_recoil;

		private float m_fireTimer;

		private float m_hintTimer;

		private bool m_init;

		private readonly List<Transform> m_legs = new List<Transform>();

		private readonly List<Vector3> m_legBase = new List<Vector3>();

		private void OnEnable()
		{
			Active.Add(this);
			m_init = false;
		}

		private void OnDisable()
		{
			Active.Remove(this);
		}

		public static BoatCatapult GetSeated(Player player)
		{
			if ((Object)(object)player == (Object)null || ((Character)player).IsDead() || !((Character)player).IsAttached() || (Object)(object)player.GetAttachPoint() == (Object)null)
			{
				return null;
			}
			foreach (BoatCatapult item in Active)
			{
				if ((Object)(object)item != (Object)null && player.GetAttachPoint().IsChildOf(((Component)item).transform))
				{
					return item;
				}
			}
			return null;
		}

		public HudData GetHudData()
		{
			HudData result = default(HudData);
			result.Angle = m_angle;
			result.Aim = m_yaw;
			result.Power = m_power;
			result.AmmoCount = 0;
			result.AmmoName = "";
			result.Cooldown = Mathf.Max(0f, m_fireTimer);
			result.Deployed = m_deployed;
			Inventory val = StoreInventory();
			if (val != null)
			{
				foreach (ItemData allItem in val.GetAllItems())
				{
					if (allItem != null && allItem.m_shared != null && allItem.m_shared.m_name != null)
					{
						result.AmmoCount++;
						if (result.AmmoName.Length == 0)
						{
							result.AmmoName = allItem.m_shared.m_name;
						}
					}
				}
			}
			return result;
		}

		private Inventory StoreInventory()
		{
			if ((Object)(object)m_store == (Object)null)
			{
				Transform root = ((Component)this).transform.root;
				m_store = ((Component)root).GetComponentInChildren<Container>();
			}
			if (!((Object)(object)m_store != (Object)null))
			{
				return null;
			}
			return m_store.GetInventory();
		}

		private void EnsureInit()
		{
			//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_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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)
			if (m_init)
			{
				return;
			}
			m_init = true;
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_store = ((Component)((Component)this).transform.root).GetComponentInChildren<Container>();
			if ((Object)(object)Source != (Object)null)
			{
				m_arm = (((Object)(object)Source.m_arm != (Object)null) ? Source.m_arm.transform : null);
				m_shoot = Source.m_shootPoint;
				((Behaviour)Source).enabled = false;
			}
			if ((Object)(object)m_arm != (Object)null)
			{
				m_armBaseRot = m_arm.localRotation;
			}
			if ((Object)(object)PitchPivot != (Object)null)
			{
				m_pivotBaseRot = PitchPivot.localRotation;
			}
			if (m_legs.Count == 0)
			{
				Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					if (((Object)val).name.ToLowerInvariant().StartsWith("leg"))
					{
						m_legs.Add(val);
						m_legBase.Add(val.localPosition);
					}
				}
			}
			m_angle = Mathf.Clamp(BoatCatapultConfig.DefaultAngle.Value, BoatCatapultConfig.AngleMin.Value, BoatCatapultConfig.AngleMax.Value);
			m_power = BoatCatapultConfig.DefaultPower.Value;
		}

		private void Update()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			EnsureInit();
			if (BoatCatapultConfig.Enabled.Value)
			{
				float deltaTime = Time.deltaTime;
				int num = ((!BoatCatapultConfig.InvertPitch.Value) ? 1 : (-1));
				m_recoil = Mathf.MoveTowards(m_recoil, 0f, deltaTime * 3f);
				m_fireTimer -= deltaTime;
				m_hintTimer -= deltaTime;
				float num2 = Mathf.Sin(MathF.PI * Mathf.Clamp01(m_recoil)) * 35f * m_recoil;
				if ((Object)(object)PitchPivot != (Object)null)
				{
					PitchPivot.localRotation = m_pivotBaseRot * Quaternion.Euler((float)num * m_angle - num2, 0f, 0f);
				}
				if ((Object)(object)Lift != (Object)null)
				{
					Lift.localRotation = Quaternion.Euler(0f, m_yaw, 0f);
					float num3 = (m_deployed ? BoatCatapultConfig.DeployHeight.Value : 0f);
					Lift.localPosition = new Vector3(0f, num3, 0f);
				}
				float num4 = (m_deployed ? ((0f - BoatCatapultConfig.DeployHeight.Value) * 1.15f) : 0f);
				for (int i = 0; i < m_legs.Count; i++)
				{
					m_legs[i].localPosition = m_legBase[i] + new Vector3(0f, num4, 0f);
				}
				Player localPlayer = Player.m_localPlayer;
				if (!((Object)(object)localPlayer == (Object)null) && !((Character)localPlayer).IsDead() && ((Character)localPlayer).IsAttached() && !((Object)(object)localPlayer.GetAttachPoint() == (Object)null) && localPlayer.GetAttachPoint().IsChildOf(((Component)this).transform))
				{
					HandleInput(localPlayer);
				}
			}
		}

		private void HandleInput(Player player)
		{
			if (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
			{
				if (Input.GetKeyDown((KeyCode)273))
				{
					m_power = Mathf.Clamp01(m_power + BoatCatapultConfig.PowerStep.Value);
					ShowHint(player, PowerText(m_power));
				}
				if (Input.GetKeyDown((KeyCode)274))
				{
					m_power = Mathf.Clamp01(m_power - BoatCatapultConfig.PowerStep.Value);
					ShowHint(player, PowerText(m_power));
				}
				if (Input.GetKeyDown((KeyCode)102))
				{
					TryFire(player);
				}
				return;
			}
			bool flag = Input.GetKey((KeyCode)273) || Input.GetKey((KeyCode)119);
			bool flag2 = Input.GetKey((KeyCode)274) || Input.GetKey((KeyCode)115);
			if (flag && !flag2)
			{
				m_angle = Mathf.Clamp(m_angle + BoatCatapultConfig.AngleSpeed.Value * Time.deltaTime, BoatCatapultConfig.AngleMin.Value, BoatCatapultConfig.AngleMax.Value);
				ShowHint(player, "Angle " + Mathf.RoundToInt(m_angle) + "°");
			}
			else if (flag2 && !flag)
			{
				m_angle = Mathf.Clamp(m_angle - BoatCatapultConfig.AngleSpeed.Value * Time.deltaTime, BoatCatapultConfig.AngleMin.Value, BoatCatapultConfig.AngleMax.Value);
				ShowHint(player, "Angle " + Mathf.RoundToInt(m_angle) + "°");
			}
			bool flag3 = Input.GetKey((KeyCode)275) || Input.GetKey((KeyCode)100);
			bool flag4 = Input.GetKey((KeyCode)276) || Input.GetKey((KeyCode)97);
			if (flag3 && !flag4)
			{
				m_yaw = Mathf.Repeat(m_yaw + BoatCatapultConfig.YawSpeed.Value * Time.deltaTime, 360f);
				ShowHint(player, "Aim " + Mathf.RoundToInt(m_yaw) + "°");
			}
			else if (flag4 && !flag3)
			{
				m_yaw = Mathf.Repeat(m_yaw - BoatCatapultConfig.YawSpeed.Value * Time.deltaTime, 360f);
				ShowHint(player, "Aim " + Mathf.RoundToInt(m_yaw) + "°");
			}
			if (Input.GetKeyDown((KeyCode)118))
			{
				m_deployed = !m_deployed;
				ShowHint(player, m_deployed ? "Legs deployed" : "Legs retracted");
			}
			if (Input.GetKeyDown((KeyCode)116))
			{
				Eject(player);
			}
		}

		private static string PowerText(float power)
		{
			return "Power " + Mathf.RoundToInt(power * 100f) + "%";
		}

		private void ShowHint(Player player, string text)
		{
			if (!(m_hintTimer > 0f))
			{
				m_hintTimer = 0.25f;
				((Character)player).Message((MessageType)2, text, 0, (Sprite)null, false);
			}
		}

		private ItemData PickAmmo()
		{
			Inventory val = StoreInventory();
			if (val == null)
			{
				return null;
			}
			List<ItemData> allItems = val.GetAllItems();
			if (allItems == null || allItems.Count == 0)
			{
				return null;
			}
			for (int i = 0; i < allItems.Count; i++)
			{
				if (allItems[i] != null && allItems[i].m_shared != null)
				{
					return allItems[i];
				}
			}
			return null;
		}

		private void TryFire(Player player)
		{
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			if (m_fireTimer > 0f)
			{
				return;
			}
			ItemData val = PickAmmo();
			if (val == null)
			{
				((Character)player).Message((MessageType)1, "No ammo in the boat's hold.", 0, (Sprite)null, false);
				return;
			}
			Inventory val2 = StoreInventory();
			if (val2 != null)
			{
				val2.RemoveItem(val, 1);
			}
			m_fireTimer = Mathf.Max(0.2f, BoatCatapultConfig.FireCooldown.Value);
			m_recoil = 1f;
			SpawnProjectile(player, val);
			PlayEffect(((Object)(object)Source != (Object)null) ? Source.m_shootStartEffect : null, ((Object)(object)m_shoot != (Object)null) ? m_shoot.position : ((Component)this).transform.position);
			((Character)player).Message((MessageType)2, "Thunk!", 0, (Sprite)null, false);
		}

		private void SpawnProjectile(Player player, ItemData ammo)
		{
			//IL_003b: 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_0062: 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_0067: 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_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_0079: 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_0083: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: 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_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindProjectilePrefab();
			float num = (((Object)(object)Source != (Object)null) ? Source.m_launchForce : 40f) * (0.35f + 0.9f * m_power);
			Vector3 val2 = AimDir();
			Vector3 val3 = (((Object)(object)m_shoot != (Object)null) ? m_shoot.position : ((Component)this).transform.position) + val2 * 0.5f;
			Quaternion val4 = Quaternion.LookRotation(val2, Vector3.up);
			GameObject val5 = (((Object)(object)val != (Object)null) ? Object.Instantiate<GameObject>(val, val3, val4) : Object.Instantiate<GameObject>(GameObject.CreatePrimitive((PrimitiveType)0), val3, val4));
			if ((Object)(object)val == (Object)null)
			{
				Collider component = val5.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
			}
			Projectile component2 = val5.GetComponent<Projectile>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.Setup((Character)(object)player, val2 * num, ((Object)(object)Source != (Object)null) ? Source.m_hitNoise : 0f, (HitData)null, ammo, ammo);
			}
		}

		private static GameObject FindProjectilePrefab()
		{
			PrefabManager instance = PrefabManager.Instance;
			GameObject val = ((instance != null) ? instance.GetPrefab("Catapult_projectile") : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab("Catapult_projectile");
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				val = ZNetScene.instance.GetPrefab("Turret_projectile");
			}
			return val;
		}

		private Vector3 AimDir()
		{
			//IL_0017: 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_003a: 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)
			int num = (BoatCatapultConfig.InvertPitch.Value ? 1 : (-1));
			return ((Component)this).transform.rotation * Quaternion.Euler((float)num * m_angle, m_yaw, 0f) * Vector3.forward;
		}

		private void Eject(Player player)
		{
			//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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: 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_00cd: Unknown result type (might be due to invalid IL or missing references)
			float num = 0.35f + 0.9f * m_power;
			float num2 = (((Object)(object)Source != (Object)null) ? Source.m_launchForce : 40f) * num;
			Vector3 val = AimDir();
			((Character)player).Message((MessageType)2, "YEET!", 0, (Sprite)null, false);
			PlayEffect(((Object)(object)Source != (Object)null) ? Source.m_shootReleaseEffect : null, ((Object)(object)m_shoot != (Object)null) ? m_shoot.position : ((Component)this).transform.position);
			((Character)player).AttachStop();
			if (BoatCatapultConfig.EjectNoFallDamage.Value && (Object)(object)((Component)player).GetComponent<BoatCatapultEject>() == (Object)null)
			{
				((Component)player).gameObject.AddComponent<BoatCatapultEject>();
			}
			Character.SetTakeInputDelay(0.6f);
			((Character)player).ForceJump(val * num2, true);
		}

		private void PlayEffect(EffectList effects, Vector3 pos)
		{
			//IL_0006: 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_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)
			if (effects == null)
			{
				return;
			}
			try
			{
				effects.Create(pos, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID));
			}
			catch
			{
			}
		}
	}
	internal static class BoatCatapultConfig
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<bool> AddCatapult;

		public static ConfigEntry<float> Scale;

		public static ConfigEntry<float> DefaultAngle;

		public static ConfigEntry<float> AngleMin;

		public static ConfigEntry<float> AngleMax;

		public static ConfigEntry<float> AngleSpeed;

		public static ConfigEntry<float> YawSpeed;

		public static ConfigEntry<float> PowerStep;

		public static ConfigEntry<float> DefaultPower;

		public static ConfigEntry<bool> InvertPitch;

		public static ConfigEntry<float> FireCooldown;

		public static ConfigEntry<float> DeployHeight;

		public static ConfigEntry<bool> EjectNoFallDamage;

		public static void Bind(ConfigFile config)
		{
			Enabled = config.Bind<bool>("Catapult", "Enabled", true, "Enable the deck catapult.");
			AddCatapult = config.Bind<bool>("Catapult", "AddCatapult", true, "Mount a rideable catapult on the deck (tunable in the placement GUI). Requires a game restart.");
			Scale = config.Bind<float>("Catapult", "Scale", 0.5f, "Uniform scale of the catapult model.");
			Scale.Value = Mathf.Clamp(Scale.Value, 0.2f, 1f);
			DefaultAngle = config.Bind<float>("Catapult", "DefaultAngle", 25f, "Starting arm elevation in degrees.");
			AngleMin = config.Bind<float>("Catapult", "AngleMin", -10f, "Lowest arm elevation in degrees.");
			AngleMax = config.Bind<float>("Catapult", "AngleMax", 75f, "Highest arm elevation in degrees.");
			AngleSpeed = config.Bind<float>("Catapult", "AngleSpeed", 30f, "Arm raise/lower speed (deg/s).");
			YawSpeed = config.Bind<float>("Catapult", "YawSpeed", 45f, "Aim swing speed (deg/s).");
			PowerStep = config.Bind<float>("Catapult", "PowerStep", 0.08f, "Power change per Shift+Up/Down.");
			DefaultPower = config.Bind<float>("Catapult", "DefaultPower", 0.5f, "Starting power as a fraction of launch force.");
			DefaultPower.Value = Mathf.Clamp01(DefaultPower.Value);
			InvertPitch = config.Bind<bool>("Catapult", "InvertPitch", false, "Flip arm/aim direction if it swings the wrong way.");
			FireCooldown = config.Bind<float>("Catapult", "FireCooldown", 2.5f, "Minimum seconds between shots.");
			DeployHeight = config.Bind<float>("Catapult", "DeployHeight", 0.6f, "How high the machine lifts when legs are deployed with V.");
			EjectNoFallDamage = config.Bind<bool>("Catapult", "EjectNoFallDamage", true, "No fall damage when launched from the ejector seat (T).");
		}
	}
	public class BoatCatapultEject : MonoBehaviour
	{
		private static FieldInfo f_fallTimer;

		private static FieldInfo f_maxAirAltitude;

		private static bool f_lookupTried;

		private const float MaxFlightSeconds = 40f;

		private Character m_character;

		private float m_age;

		private bool m_wasGrounded;

		private void Awake()
		{
			m_character = ((Component)this).GetComponent<Character>();
			m_age = 0f;
			m_wasGrounded = (Object)(object)m_character != (Object)null && m_character.IsOnGround();
			EnsureFieldLookup();
			if ((Object)(object)m_character == (Object)null)
			{
				Object.Destroy((Object)(object)this);
			}
		}

		private void Update()
		{
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_character == (Object)null || m_character.IsDead())
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			m_age += Time.deltaTime;
			if (m_age > 40f)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			bool flag = m_character.IsOnGround();
			if (flag && !m_wasGrounded)
			{
				Object.Destroy((Object)(object)this);
				return;
			}
			m_wasGrounded = flag;
			if (flag)
			{
				return;
			}
			try
			{
				if (f_fallTimer != null)
				{
					f_fallTimer.SetValue(m_character, 0f);
				}
				if (f_maxAirAltitude != null)
				{
					f_maxAirAltitude.SetValue(m_character, ((Component)this).transform.position.y);
				}
			}
			catch
			{
				Object.Destroy((Object)(object)this);
			}
		}

		private static void EnsureFieldLookup()
		{
			if (!f_lookupTried)
			{
				f_lookupTried = true;
				Type? typeFromHandle = typeof(Character);
				f_fallTimer = typeFromHandle.GetField("m_fallTimer", BindingFlags.Instance | BindingFlags.NonPublic);
				f_maxAirAltitude = typeFromHandle.GetField("m_maxAirAltitude", BindingFlags.Instance | BindingFlags.NonPublic);
			}
		}
	}
	internal static class BoatCatapultHud
	{
		private static GUIStyle s_style;

		public static void Render()
		{
			//IL_0076: 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_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			BoatCatapult seated = BoatCatapult.GetSeated(Player.m_localPlayer);
			if (!((Object)(object)seated == (Object)null))
			{
				BoatCatapult.HudData hudData = seated.GetHudData();
				if (s_style == null)
				{
					s_style = new GUIStyle(GUI.skin.label);
					s_style.fontSize = 14;
					s_style.normal.textColor = Color.white;
				}
				float num = 270f;
				float num2 = 132f;
				float num3 = (float)Screen.height * 0.28f;
				Color color = GUI.color;
				GUI.color = new Color(0f, 0f, 0f, 0.55f);
				GUI.DrawTexture(new Rect(12f, num3, num, num2), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
				GUILayout.BeginArea(new Rect(12f + 10f, num3 + 8f, num - 20f, num2 - 16f));
				GUILayout.Label("Boat Catapult" + (hudData.Deployed ? "  (legs)" : ""), s_style, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Angle " + Mathf.RoundToInt(hudData.Angle) + "°    Aim " + Mathf.RoundToInt(hudData.Aim) + "°", s_style, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Power " + Mathf.RoundToInt(hudData.Power * 100f) + "%", s_style, Array.Empty<GUILayoutOption>());
				if (hudData.Cooldown > 0.05f)
				{
					GUILayout.Label("Reloading " + hudData.Cooldown.ToString("0.0") + "s", s_style, Array.Empty<GUILayoutOption>());
				}
				GUILayout.Label("Ammo " + hudData.AmmoCount + ((hudData.AmmoName.Length > 0) ? ("  (" + hudData.AmmoName + ")") : ""), s_style, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Shift+F fire   Shift+Up/Dn power", s_style, Array.Empty<GUILayoutOption>());
				GUILayout.EndArea();
			}
		}
	}
	internal static class BoatCatapultInput
	{
		[HarmonyPatch(typeof(ZInput), "GetButton")]
		[HarmonyPatch(typeof(ZInput), "GetButtonDown")]
		[HarmonyPatch(typeof(ZInput), "GetButtonUp")]
		private static class ZInputSpoof
		{
			private static bool Prefix(string name, ref bool __result)
			{
				if (SeatInUse() && BlockedNames.Contains(name))
				{
					__result = false;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Character), "CustomFixedUpdate")]
		private static class LockMovePatch
		{
			private static void Prefix(Character __instance)
			{
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				if (SeatInUse() && (Object)(object)__instance == (Object)(object)Player.m_localPlayer)
				{
					__instance.SetMoveDir(Vector3.zero);
					__instance.StopMovement();
				}
			}
		}

		private static readonly HashSet<string> BlockedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
		{
			"Forward", "Back", "Backward", "Left", "Right", "Jump", "Sneak", "Run", "Sprint", "Attack",
			"AttackHold", "SecondaryAttack", "SecondaryAttackHold", "Block", "BlockHold", "Dodge"
		};

		public static bool SeatInUse()
		{
			return (Object)(object)BoatCatapult.GetSeated(Player.m_localPlayer) != (Object)null;
		}
	}
	public class BoatCatapultSeat : MonoBehaviour, Interactable, Hoverable
	{
		public GameObject RootObject;

		public Transform AttachPoint;

		public string AttachAnimation = "sitting";

		public Vector3 DetachOffset = Vector3.zero;

		public bool Interact(Humanoid user, bool hold, bool alt)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (hold)
			{
				return false;
			}
			Player val = (Player)(object)((user is Player) ? user : null);
			if (val == null)
			{
				return true;
			}
			if (((Character)val).IsAttached())
			{
				return true;
			}
			if ((Object)(object)AttachPoint == (Object)null || (Object)(object)RootObject == (Object)null)
			{
				return true;
			}
			((Character)val).AttachStart(AttachPoint, RootObject, true, false, false, AttachAnimation, DetachOffset, (Transform)null);
			if (((Character)val).IsAttached())
			{
				((Character)val).Message((MessageType)2, "Catapult: Shift+F = fire, Shift+Up/Down = power, Arrows/WASD = aim, V = legs, T = eject, E = stand up", 0, (Sprite)null, false);
			}
			return true;
		}

		public bool UseItem(Humanoid user, ItemData item)
		{
			return false;
		}

		public string GetHoverText()
		{
			return "Use the boat catapult [<color=yellow>E</color>]";
		}

		public string GetHoverName()
		{
			return "Boat Catapult";
		}

		public float GetHoverOffset()
		{
			return 1f;
		}
	}
	internal static class BoatCatapultSetup
	{
		public unsafe static void Attach(GameObject ship, Bounds hull)
		{
			//IL_004c: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: 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_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindBaseCatapultPrefab();
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"Harpoon Longboat: could not find the vanilla Catapult prefab; no deck catapult added.");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(val);
			((Object)obj).name = "BoatCatapult";
			Catapult component = obj.GetComponent<Catapult>();
			StripCatapultComponents(obj);
			float value = BoatCatapultConfig.Scale.Value;
			obj.transform.localScale = new Vector3(value, value, value);
			Transform val2 = SetupLift(obj);
			Transform val3 = SetupAimPivot(val2, component);
			SetupSeat(val2, ship, val3);
			BoatCatapult boatCatapult = obj.AddComponent<BoatCatapult>();
			boatCatapult.Source = component;
			boatCatapult.Lift = val2;
			boatCatapult.PitchPivot = val3;
			Vector3 val4 = default(Vector3);
			((Vector3)(ref val4))..ctor(0f, ((Bounds)(ref hull)).max.y - 0.4f, ((Bounds)(ref hull)).center.z);
			obj.transform.SetParent(ship.transform, false);
			obj.transform.localPosition = val4;
			obj.transform.localRotation = Quaternion.identity;
			obj.transform.localScale = new Vector3(value, value, value);
			HarpoonPlacementPart harpoonPlacementPart = obj.AddComponent<HarpoonPlacementPart>();
			harpoonPlacementPart.PartName = "catapult";
			harpoonPlacementPart.ExplicitAnchor = true;
			harpoonPlacementPart.AnchorPosition = val4;
			harpoonPlacementPart.BaseScale = new Vector3(value, value, value);
			harpoonPlacementPart.BaseRotation = Quaternion.identity;
			Vector3 val5 = val4;
			Logger.LogInfo((object)("Harpoon Longboat: deck catapult mounted at ship-local " + ((object)(*(Vector3*)(&val5))/*cast due to .constrained prefix*/).ToString() + "."));
		}

		private static void StripCatapultComponents(GameObject root)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer) && !(val is LODGroup) && !(val is ParticleSystem) && !(val is ParticleSystemRenderer) && !(val is Light) && !(val is Catapult) && !(val is Animator))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static Transform SetupLift(GameObject catapult)
		{
			//IL_0005: 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_0029: 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)
			Transform transform = new GameObject("BoatCatapultLift").transform;
			transform.SetParent(catapult.transform, false);
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = Vector3.one;
			for (int num = catapult.transform.childCount - 1; num >= 0; num--)
			{
				Transform child = catapult.transform.GetChild(num);
				if (!((Object)(object)child == (Object)(object)transform))
				{
					child.SetParent(transform, true);
				}
			}
			return transform;
		}

		private static Transform SetupAimPivot(Transform lift, Catapult source)
		{
			//IL_0005: 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_0024: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = new GameObject("BoatCatapultAim").transform;
			transform.SetParent(lift, false);
			transform.localPosition = Vector3.zero;
			transform.localRotation = Quaternion.identity;
			transform.localScale = Vector3.one;
			if ((Object)(object)source != (Object)null && (Object)(object)source.m_arm != (Object)null)
			{
				Transform transform2 = source.m_arm.transform;
				transform.position = transform2.position;
				transform.localRotation = transform2.localRotation;
				transform2.SetParent(transform, true);
				transform2.localPosition = Vector3.zero;
			}
			return transform;
		}

		private static void SetupSeat(Transform parent, GameObject ship, Transform pitch)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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)
			//IL_018f: 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_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: 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_0268: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = FindPrefab("piece_chair", "piece_chair02", "piece_stool", "piece_bench02");
			GameObject val2 = null;
			string attachAnimation = "sitting";
			Vector3 detachOffset = Vector3.zero;
			Vector3? val3 = null;
			Quaternion? val4 = null;
			if ((Object)(object)val != (Object)null)
			{
				val2 = Object.Instantiate<GameObject>(val, parent);
				Chair component = val2.GetComponent<Chair>();
				if ((Object)(object)component != (Object)null)
				{
					if (!string.IsNullOrEmpty(component.m_attachAnimation))
					{
						attachAnimation = component.m_attachAnimation;
					}
					detachOffset = component.m_detachOffset;
					if ((Object)(object)component.m_attachPoint != (Object)null)
					{
						val3 = component.m_attachPoint.localPosition;
						val4 = component.m_attachPoint.localRotation;
					}
				}
				((Object)val2).name = "BoatCatapultSeat";
				StripToRenderers(val2);
				FixRenderers(val2);
				val2.transform.localPosition = new Vector3(2.2f, 1.1f, 0.4f);
				val2.transform.localRotation = Quaternion.identity;
				val2.transform.localScale = Vector3.one;
			}
			else
			{
				val2 = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)val2).name = "BoatCatapultSeat";
				val2.transform.SetParent(parent, false);
				val2.transform.localPosition = new Vector3(2.2f, 1.1f, 0.4f);
				val2.transform.localScale = new Vector3(0.5f, 0.2f, 0.6f);
			}
			Transform val5 = FindAttachPoint(val2);
			if ((Object)(object)val5 == (Object)null)
			{
				val5 = new GameObject("BoatCatapultAttach").transform;
				val5.SetParent(val2.transform, false);
				if (val3.HasValue)
				{
					val5.localPosition = val3.Value;
					if (val4.HasValue)
					{
						val5.localRotation = val4.Value;
					}
				}
				else
				{
					val5.localPosition = new Vector3(0f, 0.6f, 0.1f);
				}
			}
			BoxCollider val6 = val2.GetComponent<BoxCollider>();
			if ((Object)(object)val6 == (Object)null)
			{
				val6 = val2.AddComponent<BoxCollider>();
			}
			((Collider)val6).isTrigger = false;
			val6.center = new Vector3(0f, 0.2f, 0f);
			val6.size = new Vector3(0.5f, 0.35f, 0.5f);
			BoatCatapultSeat boatCatapultSeat = val2.AddComponent<BoatCatapultSeat>();
			boatCatapultSeat.RootObject = ship;
			boatCatapultSeat.AttachPoint = val5;
			boatCatapultSeat.AttachAnimation = attachAnimation;
			boatCatapultSeat.DetachOffset = detachOffset;
		}

		private static Transform FindAttachPoint(GameObject seat)
		{
			Transform[] componentsInChildren = seat.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)(object)seat.transform))
				{
					switch (((Object)val).name.ToLowerInvariant())
					{
					case "attach_point":
					case "attachpoint":
					case "attach":
					case "sit_anchor":
						return val;
					}
				}
			}
			return null;
		}

		private static void StripToRenderers(GameObject root)
		{
			List<Component> list = new List<Component>();
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer))
				{
					list.Add(val);
				}
			}
			foreach (Component item in list)
			{
				Object.Destroy((Object)(object)item);
			}
		}

		private static void FixRenderers(GameObject root)
		{
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true);
			foreach (Transform val in componentsInChildren)
			{
				string text = ((Object)val).name.ToLowerInvariant();
				if (text.StartsWith("worn") || text.StartsWith("broken") || text.StartsWith("destruction"))
				{
					((Component)val).gameObject.SetActive(false);
				}
			}
			MeshRenderer[] componentsInChildren2 = root.GetComponentsInChildren<MeshRenderer>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				((Renderer)componentsInChildren2[i]).enabled = true;
			}
			SkinnedMeshRenderer[] componentsInChildren3 = root.GetComponentsInChildren<SkinnedMeshRenderer>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				((Renderer)componentsInChildren3[i]).enabled = true;
			}
		}

		private static GameObject FindBaseCatapultPrefab()
		{
			PrefabManager instance = PrefabManager.Instance;
			GameObject val = ((instance != null) ? instance.GetPrefab("Catapult") : null);
			if ((Object)(object)val != (Object)null && (Object)(object)val.GetComponent<Catapult>() != (Object)null)
			{
				return val;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null && ZNetScene.instance.m_prefabs != null)
			{
				foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
				{
					if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<Catapult>() != (Object)null)
					{
						return prefab;
					}
				}
			}
			return null;
		}

		private static GameObject FindPrefab(params string[] names)
		{
			foreach (string text in names)
			{
				PrefabManager instance = PrefabManager.Instance;
				GameObject val = ((instance != null) ? instance.GetPrefab(text) : null);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				if ((Object)(object)ZNetScene.instance != (Object)null)
				{
					val = ZNetScene.instance.GetPrefab(text);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
			}
			return null;
		}
	}
	public class HarpoonLongboat : MonoBehaviour
	{
		private class ItemTarget
		{
			public ItemDrop Item;

			public int State;

			public float StateTimer;

			public Vector3 BoltStart;

			public Vector3 BoltEnd;

			public GameObject BoltObject;

			public LineRenderer Tether;

			public float CooldownUntil;
		}

		private class RecentCollect
		{
			public ItemDrop Item;

			public float Time;
		}

		private class RecentCreature
		{
			public Character Creature;

			public float Time;
		}

		private const float AimDelay = 0.25f;

		internal static readonly List<HarpoonLongboat> Instances = new List<HarpoonLongboat>();

		public Transform TurretBody;

		public Transform TurretNeck;

		public Transform TurretEye;

		private static Material s_tetherMaterial;

		private static Material s_boltMaterial;

		private ZNetView m_nview;

		private Container m_hold;

		private ShipControlls m_controls;

		private Ship m_ship;

		private Quaternion m_baseBodyRotation = Quaternion.identity;

		private Quaternion m_baseNeckRotation = Quaternion.identity;

		private float m_turnRate = 15f;

		private readonly List<ItemTarget> m_targets = new List<ItemTarget>();

		private readonly List<RecentCollect> m_recentCollects = new List<RecentCollect>();

		private readonly List<RecentCreature> m_recentCreatures = new List<RecentCreature>();

		private float m_scanTimer;

		private Character m_creature;

		private bool m_creatureReeling;

		private float m_creatureScanTimer;

		private LineRenderer m_creatureTether;

		private void Awake()
		{
			Init();
		}

		private void Init()
		{
			//IL_005e: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_hold = ((Component)this).GetComponentInChildren<Container>(true);
			m_controls = ((Component)this).GetComponentInChildren<ShipControlls>(true);
			m_ship = ((Component)this).GetComponent<Ship>();
			Piece component = ((Component)this).GetComponent<Piece>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_canBeRemoved = true;
			}
			if ((Object)(object)TurretBody != (Object)null)
			{
				m_baseBodyRotation = TurretBody.localRotation;
			}
			if ((Object)(object)TurretNeck != (Object)null)
			{
				m_baseNeckRotation = TurretNeck.localRotation;
			}
			EnsureMaterials();
			if (!Instances.Contains(this))
			{
				Instances.Add(this);
			}
		}

		private void OnDestroy()
		{
			Instances.Remove(this);
		}

		public bool IsPlayerAboard(Player player)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0067: 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)
			if ((Object)(object)player == (Object)null || (Object)(object)m_ship == (Object)null)
			{
				return false;
			}
			if (m_ship.IsPlayerInBoat(player))
			{
				return true;
			}
			if ((Object)(object)((Character)player).GetStandingOnShip() == (Object)(object)m_ship)
			{
				return true;
			}
			BoxCollider floatCollider = m_ship.m_floatCollider;
			if ((Object)(object)floatCollider != (Object)null)
			{
				Vector3 position = ((Component)player).transform.position;
				Vector3 val = ((Collider)floatCollider).ClosestPoint(position) - position;
				if (((Vector3)(ref val)).sqrMagnitude < 6.25f)
				{
					return true;
				}
			}
			return false;
		}

		private void Update()
		{
			if (!HarpoonLongboatPlugin.Enabled.Value || (Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return;
			}
			float deltaTime = Time.deltaTime;
			HandleControlsInput();
			if (!HarpoonLongboatPlugin.Active)
			{
				ReleaseCreature(remember: false);
				UpdateIdleLook(deltaTime);
				return;
			}
			if (!m_nview.IsOwner())
			{
				UpdateIdleLook(deltaTime);
				return;
			}
			PruneRecentCollects();
			PruneRecentCreatures();
			m_scanTimer += deltaTime;
			if (m_scanTimer >= 0.3f)
			{
				m_scanTimer = 0f;
				AcquireItem();
			}
			for (int i = 0; i < m_targets.Count; i++)
			{
				AdvanceItem(m_targets[i], deltaTime);
			}
			UpdateCreature(deltaTime);
			PruneDoneTargets();
			UpdateAim(deltaTime);
			UpdateVisuals();
		}

		private void HandleControlsInput()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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_0045: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			KeyboardShortcut value;
			if (LocalPlayerSteering())
			{
				bool flag = false;
				value = HarpoonLongboatPlugin.ToggleKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					HarpoonLongboatPlugin.Active = !HarpoonLongboatPlugin.Active;
					flag = true;
				}
				value = HarpoonLongboatPlugin.ModeKey.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					HarpoonLongboatPlugin.Mode = HarpoonLongboatPlugin.NextMode(HarpoonLongboatPlugin.Mode);
					flag = true;
				}
				if (flag)
				{
					ShowStatus();
				}
			}
			if (!m_nview.IsOwner() || !LocalPlayerAboard())
			{
				return;
			}
			value = HarpoonLongboatPlugin.ReelToggleKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				m_creatureReeling = !m_creatureReeling;
				ShowLineStatus();
			}
			value = HarpoonLongboatPlugin.ReleaseKey.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				if ((Object)(object)m_creature != (Object)null)
				{
					Logger.LogInfo((object)("Harpoon Longboat: manually released " + m_creature.m_name + "."));
				}
				ReleaseCreature(remember: true);
				ShowLineStatus();
			}
		}

		private bool LocalPlayerSteering()
		{
			if ((Object)(object)m_controls == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
			{
				return false;
			}
			if (m_controls.HaveValidUser())
			{
				return m_controls.GetUser() == Player.m_localPlayer.GetPlayerID();
			}
			return false;
		}

		private bool LocalPlayerAboard()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return false;
			}
			if (LocalPlayerSteering())
			{
				return true;
			}
			if ((Object)(object)m_ship != (Object)null)
			{
				return m_ship.IsPlayerInBoat(Player.m_localPlayer);
			}
			return false;
		}

		private static void ShowStatus()
		{
			ShowMessage("Harpoon Longboat: " + (HarpoonLongboatPlugin.Active ? "ON" : "OFF") + " [" + HarpoonLongboatPlugin.Mode.ToString() + "]  (H = on/off, J = mode)");
		}

		private void ShowLineStatus()
		{
			string text = ((!((Object)(object)m_creature == (Object)null)) ? (m_creature.m_name + (m_creatureReeling ? " - pulling" : " - holding")) : "no creature on the line");
			ShowMessage("Harpoon Longboat: " + text + "  (T = pull/hold, G = release)");
		}

		private static void ShowMessage(string text)
		{
			MessageHud instance = MessageHud.instance;
			if (instance != null)
			{
				instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, false);
			}
		}

		private void ReleaseCreature(bool remember)
		{
			if ((Object)(object)m_creature != (Object)null && remember)
			{
				m_recentCreatures.Add(new RecentCreature
				{
					Creature = m_creature,
					Time = Time.time
				});
			}
			m_creature = null;
			m_creatureReeling = false;
			if ((Object)(object)m_creatureTether != (Object)null)
			{
				((Component)m_creatureTether).gameObject.SetActive(false);
			}
		}

		private void PruneRecentCreatures()
		{
			for (int num = m_recentCreatures.Count - 1; num >= 0; num--)
			{
				if (Time.time - m_recentCreatures[num].Time > 20f || (Object)(object)m_recentCreatures[num].Creature == (Object)null)
				{
					m_recentCreatures.RemoveAt(num);
				}
			}
		}

		private bool IsRecentlyHooked(Character character)
		{
			for (int i = 0; i < m_recentCreatures.Count; i++)
			{
				if ((Object)(object)m_recentCreatures[i].Creature == (Object)(object)character)
				{
					return true;
				}
			}
			return false;
		}

		private static void EnsureMaterials()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_tetherMaterial == (Object)null)
			{
				Shader val = Shader.Find("Unlit/Color");
				if ((Object)(object)val == (Object)null)
				{
					val = Shader.Find("Sprites/Default");
				}
				if ((Object)(object)val != (Object)null)
				{
					s_tetherMaterial = new Material(val);
					s_tetherMaterial.color = new Color(0.78f, 0.7f, 0.52f, 0.95f);
				}
			}
			if ((Object)(object)s_boltMaterial == (Object)null)
			{
				Shader val2 = Shader.Find("Unlit/Color");
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = Shader.Find("Sprites/Default");
				}
				if ((Object)(object)val2 != (Object)null)
				{
					s_boltMaterial = new Material(val2);
					s_boltMaterial.color = new Color(0.45f, 0.38f, 0.28f, 1f);
				}
			}
		}

		private Vector3 GetHoldPoint()
		{
			//IL_0040: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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)
			if ((Object)(object)m_hold == (Object)null)
			{
				m_hold = ((Component)this).GetComponentInChildren<Container>(true);
			}
			if ((Object)(object)m_hold != (Object)null)
			{
				return ((Component)m_hold).transform.position;
			}
			return ((Component)this).transform.position + Vector3.up * 1.5f;
		}

		private Vector3 GetMuzzlePosition()
		{
			//IL_0034: 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_0023: 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)
			if (!((Object)(object)TurretEye != (Object)null))
			{
				return ((Component)this).transform.position + Vector3.up * 2f;
			}
			return TurretEye.position;
		}

		private void AcquireItem()
		{
			//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_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if (HarpoonLongboatPlugin.Mode == HarpoonLongboatPlugin.HarpoonMode.Creatures)
			{
				return;
			}
			int num = Mathf.Max(1, HarpoonLongboatPlugin.MaxTargets.Value);
			if (m_targets.Count >= num)
			{
				return;
			}
			float value = HarpoonLongboatPlugin.CollectionRange.Value;
			float num2 = value * value;
			Vector3 holdPoint = GetHoldPoint();
			bool value2 = HarpoonLongboatPlugin.WaterOnly.Value;
			ItemDrop val = null;
			float num3 = num2;
			ItemDrop[] array = Object.FindObjectsByType<ItemDrop>((FindObjectsSortMode)0);
			if (array == null)
			{
				return;
			}
			foreach (ItemDrop val2 in array)
			{
				if ((Object)(object)val2 == (Object)null || ((Component)val2).transform.IsChildOf(((Component)this).transform))
				{
					continue;
				}
				ZNetView component = ((Component)val2).GetComponent<ZNetView>();
				if ((Object)(object)component == (Object)null || !component.IsValid() || val2.m_itemData == null || val2.m_itemData.m_shared == null || val2.IsPiece() || HarpoonLongboatPlugin.IsIgnored(val2) || IsTargeted(val2) || IsRecentlyCollected(val2))
				{
					continue;
				}
				if (value2)
				{
					Floating component2 = ((Component)val2).GetComponent<Floating>();
					if ((Object)(object)component2 == (Object)null || !component2.HaveLiquidLevel())
					{
						continue;
					}
				}
				Vector3 val3 = ((Component)val2).transform.position - holdPoint;
				float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
				if (!(sqrMagnitude > num2) && sqrMagnitude < num3)
				{
					num3 = sqrMagnitude;
					val = val2;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				string text = ((val.m_itemData != null && val.m_itemData.m_shared != null) ? val.m_itemData.m_shared.m_name : ((Object)((Component)val).gameObject).name);
				Logger.LogInfo((object)("Harpoon Longboat: harpooning " + text + " at " + Mathf.RoundToInt(Mathf.Sqrt(num3)) + "m"));
				m_targets.Add(CreateItemTarget(val));
			}
		}

		private ItemTarget CreateItemTarget(ItemDrop item)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0036: Unknown result type (might be due to invalid IL or missing references)
			ItemTarget itemTarget = new ItemTarget
			{
				Item = item,
				State = 0,
				StateTimer = 0f,
				BoltStart = GetMuzzlePosition(),
				BoltEnd = ((Component)item).transform.position
			};
			EnsureItemVisuals(itemTarget);
			return itemTarget;
		}

		private void EnsureItemVisuals(ItemTarget t)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)t.Tether == (Object)null)
			{
				GameObject val = new GameObject("HarpoonTether");
				val.transform.SetParent(((Component)this).transform, false);
				LineRenderer val2 = val.AddComponent<LineRenderer>();
				val2.useWorldSpace = true;
				val2.positionCount = 2;
				val2.startWidth = 0.18f;
				val2.endWidth = 0.04f;
				val2.numCapVertices = 4;
				if ((Object)(object)s_tetherMaterial != (Object)null)
				{
					((Renderer)val2).sharedMaterial = s_tetherMaterial;
				}
				val.SetActive(false);
				t.Tether = val2;
			}
			if ((Object)(object)t.BoltObject == (Object)null)
			{
				t.BoltObject = CreateBolt("HarpoonBolt");
			}
		}

		private GameObject CreateBolt(string name)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj).name = name;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			obj.transform.SetParent(((Component)this).transform, false);
			obj.transform.localScale = new Vector3(0.14f, 0.6f, 0.14f);
			MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
			if ((Object)(object)component2 != (Object)null && (Object)(object)s_boltMaterial != (Object)null)
			{
				((Renderer)component2).sharedMaterial = s_boltMaterial;
			}
			obj.SetActive(false);
			return obj;
		}

		private void AdvanceItem(ItemTarget t, float dt)
		{
			//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_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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)
			switch (t.State)
			{
			case 0:
				t.StateTimer += dt;
				if (t.StateTimer >= 0.25f)
				{
					t.State = 1;
					t.StateTimer = 0f;
					t.BoltStart = GetMuzzlePosition();
					if ((Object)(object)t.Item != (Object)null)
					{
						t.BoltEnd = ((Component)t.Item).transform.position;
					}
				}
				break;
			case 1:
			{
				t.StateTimer += dt;
				float num = Mathf.Max(0.1f, HarpoonLongboatPlugin.BoltFlightTime.Value);
				float num2 = Mathf.Clamp01(t.StateTimer / num);
				if ((Object)(object)t.BoltObject != (Object)null)
				{
					t.BoltObject.transform.position = Vector3.Lerp(t.BoltStart, t.BoltEnd, num2);
				}
				if (num2 >= 1f)
				{
					t.State = 2;
					t.StateTimer = 0f;
					if ((Object)(object)t.BoltObject != (Object)null)
					{
						t.BoltObject.SetActive(false);
					}
				}
				break;
			}
			case 2:
				ReelItem(t, dt);
				break;
			}
		}

		private void ReelItem(ItemTarget t, float dt)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: 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)
			ItemDrop item = t.Item;
			if ((Object)(object)item == (Object)null)
			{
				CompleteItem(t);
				return;
			}
			ZNetView component = ((Component)item).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid())
			{
				CompleteItem(t);
				return;
			}
			Vector3 holdPoint = GetHoldPoint();
			Vector3 position = ((Component)item).transform.position;
			float num = Vector3.Distance(position, holdPoint);
			float value = HarpoonLongboatPlugin.CollectionRange.Value;
			if (num <= Mathf.Max(0.5f, HarpoonLongboatPlugin.DepositRange.Value))
			{
				if (TryDeposit(item))
				{
					Logger.LogInfo((object)("Harpoon Longboat: stowed " + ItemLabel(item) + " in the hold."));
					component.Destroy();
				}
				CompleteItem(t);
				return;
			}
			if (num > value * 2f)
			{
				CompleteItem(t);
				return;
			}
			if (!component.IsOwner())
			{
				component.ClaimOwnership();
			}
			if (component.IsOwner())
			{
				float num2 = Mathf.Max(1f, HarpoonLongboatPlugin.ReelSpeed.Value);
				((Component)item).transform.position = Vector3.MoveTowards(position, holdPoint, num2 * dt);
				Rigidbody component2 = ((Component)item).GetComponent<Rigidbody>();
				if ((Object)(object)component2 != (Object)null && component2.linearVelocity != Vector3.zero)
				{
					component2.linearVelocity = Vector3.zero;
				}
			}
		}

		private bool TryDeposit(ItemDrop item)
		{
			if ((Object)(object)m_hold == (Object)null)
			{
				m_hold = ((Component)this).GetComponentInChildren<Container>(true);
			}
			if ((Object)(object)m_hold == (Object)null || (Object)(object)item == (Object)null || item.m_itemData == null)
			{
				return false;
			}
			Inventory inventory = m_hold.GetInventory();
			if (inventory == null)
			{
				return false;
			}
			if (!inventory.CanAddItem(item.m_itemData, item.m_itemData.m_stack))
			{
				return false;
			}
			return inventory.AddItem(item.m_itemData.Clone());
		}

		private void CompleteItem(ItemTarget t)
		{
			if ((Object)(object)t.Item != (Object)null)
			{
				m_recentCollects.Add(new RecentCollect
				{
					Item = t.Item,
					Time = Time.time
				});
			}
			t.State = 3;
			t.CooldownUntil = Time.time;
			if ((Object)(object)t.BoltObject != (Object)null)
			{
				t.BoltObject.SetActive(false);
			}
			if ((Object)(object)t.Tether != (Object)null)
			{
				((Component)t.Tether).gameObject.SetActive(false);
			}
		}

		private void PruneDoneTargets()
		{
			for (int num = m_targets.Count - 1; num >= 0; num--)
			{
				ItemTarget itemTarget = m_targets[num];
				if (itemTarget.State == 3 && Time.time - itemTarget.CooldownUntil >= HarpoonLongboatPlugin.Cooldown.Value)
				{
					m_targets.RemoveAt(num);
				}
				else if ((Object)(object)itemTarget.Item == (Object)null)
				{
					CompleteItem(itemTarget);
					m_targets.RemoveAt(num);
				}
			}
		}

		private void PruneRecentCollects()
		{
			for (int num = m_recentCollects.Count - 1; num >= 0; num--)
			{
				if (Time.time - m_recentCollects[num].Time > 30f || (Object)(object)m_recentCollects[num].Item == (Object)null)
				{
					m_recentCollects.RemoveAt(num);
				}
			}
		}

		private bool IsTargeted(ItemDrop item)
		{
			for (int i = 0; i < m_targets.Count; i++)
			{
				if ((Object)(object)m_targets[i].Item == (Object)(object)item)
				{
					return true;
				}
			}
			return false;
		}

		private bool IsRecentlyCollected(ItemDrop item)
		{
			for (int i = 0; i < m_recentCollects.Count; i++)
			{
				if ((Object)(object)m_recentCollects[i].Item == (Object)(object)item)
				{
					return true;
				}
			}
			return false;
		}

		private void UpdateCreature(float dt)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: 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_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			if (!HarpoonLongboatPlugin.ReelCreatures.Value || HarpoonLongboatPlugin.Mode == HarpoonLongboatPlugin.HarpoonMode.Items)
			{
				if ((Object)(object)m_creature != (Object)null)
				{
					ReleaseCreature(remember: false);
				}
				return;
			}
			if ((Object)(object)m_creature != (Object)null && !IsCreatureValid(m_creature))
			{
				m_creature = null;
				m_creatureReeling = false;
			}
			m_creatureScanTimer += dt;
			if ((Object)(object)m_creature == (Object)null && m_creatureScanTimer >= 0.5f)
			{
				m_creatureScanTimer = 0f;
				AcquireCreature();
			}
			if ((Object)(object)m_creature == (Object)null)
			{
				return;
			}
			Vector3 holdPoint = GetHoldPoint();
			Vector3 position = ((Component)m_creature).transform.position;
			float num = Vector3.Distance(position, holdPoint);
			if (HarpoonLongboatPlugin.AutoRelease.Value && num <= HarpoonLongboatPlugin.CreatureReleaseRange.Value)
			{
				Logger.LogInfo((object)("Harpoon Longboat: auto-released " + m_creature.m_name + " near the boat."));
				ReleaseCreature(remember: true);
			}
			else if (m_creatureReeling && m_creature.IsOwner())
			{
				Vector3 val = holdPoint - position;
				val.y = 0f;
				if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f))
				{
					((Vector3)(ref val)).Normalize();
					m_creature.ApplyPushback(val, HarpoonLongboatPlugin.CreatureReelForce.Value);
				}
			}
		}

		private void AcquireCreature()
		{
			//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_005e: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			float value = HarpoonLongboatPlugin.CreatureRange.Value;
			float num = value * value;
			Vector3 holdPoint = GetHoldPoint();
			Character val = null;
			float num2 = num;
			Character[] array = Object.FindObjectsByType<Character>((FindObjectsSortMode)0);
			if (array == null)
			{
				return;
			}
			foreach (Character val2 in array)
			{
				if (IsCreatureValid(val2) && !IsRecentlyHooked(val2) && (val2.InWater() || val2.IsSwimming()))
				{
					Vector3 val3 = ((Component)val2).transform.position - holdPoint;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (!(sqrMagnitude > num) && sqrMagnitude < num2)
					{
						num2 = sqrMagnitude;
						val = val2;
					}
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				m_creature = val;
				m_creatureReeling = HarpoonLongboatPlugin.AutoReelOnHook.Value;
				Logger.LogInfo((object)("Harpoon Longboat: hooked " + val.m_name + " at " + Mathf.RoundToInt(Mathf.Sqrt(num2)) + "m (" + (m_creatureReeling ? "pulling" : "holding") + ")"));
			}
		}

		private bool IsCreatureValid(Character character)
		{
			//IL_0041: 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_0047: 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_004e: Invalid comparison between Unknown and I4
			if ((Object)(object)character == (Object)null || !((Component)character).gameObject.activeInHierarchy)
			{
				return false;
			}
			if (character.IsDead() || character.IsPlayer())
			{
				return false;
			}
			if (character.IsTamed() && !HarpoonLongboatPlugin.TargetTamed.Value)
			{
				return false;
			}
			Faction faction = character.GetFaction();
			if ((int)faction == 0)
			{
				return false;
			}
			if ((int)faction == 1)
			{
				return HarpoonLongboatPlugin.TargetAnimals.Value;
			}
			return HarpoonLongboatPlugin.TargetMonsters.Value;
		}

		private void UpdateAim(float dt)
		{
			//IL_0012: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: 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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_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_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: 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_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetFocus(out var focus))
			{
				UpdateIdleLook(dt);
				return;
			}
			Vector3 val = focus - GetMuzzlePosition();
			if (!(((Vector3)(ref val)).sqrMagnitude < 0.001f))
			{
				Quaternion val2 = Quaternion.LookRotation(val, Vector3.up);
				Quaternion val3 = Quaternion.Inverse(((Component)this).transform.rotation) * val2;
				Vector3 eulerAngles = ((Quaternion)(ref val3)).eulerAngles;
				float y = eulerAngles.y;
				float num = Mathf.Clamp(EulerToSigned(eulerAngles.x), -35f, 30f);
				if ((Object)(object)TurretBody != (Object)null)
				{
					Quaternion val4 = m_baseBodyRotation * Quaternion.Euler(0f, y, 0f);
					TurretBody.localRotation = Quaternion.Slerp(TurretBody.localRotation, val4, Mathf.Clamp01(m_turnRate * dt));
				}
				if ((Object)(object)TurretNeck != (Object)null)
				{
					Quaternion val5 = m_baseNeckRotation * Quaternion.Euler(num, 0f, 0f);
					TurretNeck.localRotation = Quaternion.Slerp(TurretNeck.localRotation, val5, Mathf.Clamp01(m_turnRate * dt * 0.7f));
				}
			}
		}

		private bool TryGetFocus(out Vector3 focus)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_0075: 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)
			for (int i = 0; i < m_targets.Count; i++)
			{
				ItemTarget itemTarget = m_targets[i];
				if ((itemTarget.State == 1 || itemTarget.State == 2) && (Object)(object)itemTarget.Item != (Object)null)
				{
					focus = ((Component)itemTarget.Item).transform.position;
					return true;
				}
			}
			if ((Object)(object)m_creature != (Object)null)
			{
				focus = m_creature.GetCenterPoint();
				return true;
			}
			focus = Vector3.zero;
			return false;
		}

		private void UpdateIdleLook(float dt)
		{
			//IL_001b: 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_0041: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			float time = Time.time;
			if ((Object)(object)TurretBody != (Object)null)
			{
				TurretBody.localRotation = m_baseBodyRotation * Quaternion.Euler(0f, Mathf.Sin(time * 0.3f) * 18f, 0f);
			}
			if ((Object)(object)TurretNeck != (Object)null)
			{
				TurretNeck.localRotation = m_baseNeckRotation * Quaternion.Euler(Mathf.Sin(time * 0.2f + 1f) * 8f, 0f, 0f);
			}
		}

		private void UpdateVisuals()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < m_targets.Count; i++)
			{
				ItemTarget itemTarget = m_targets[i];
				if ((Object)(object)itemTarget.BoltObject != (Object)null)
				{
					itemTarget.BoltObject.SetActive(HarpoonLongboatPlugin.ShowBolt.Value && itemTarget.State == 1);
				}
				if ((Object)(object)itemTarget.Tether != (Object)null)
				{
					bool flag = itemTarget.State == 2 && HarpoonLongboatPlugin.ShowTether.Value;
					((Component)itemTarget.Tether).gameObject.SetActive(flag);
					if (flag && (Object)(object)itemTarget.Item != (Object)null)
					{
						itemTarget.Tether.SetPosition(0, GetMuzzlePosition());
						itemTarget.Tether.SetPosition(1, ((Component)itemTarget.Item).transform.position);
					}
				}
			}
			UpdateCreatureTether();
		}

		private void UpdateCreatureTether()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)m_creature != (Object)null && HarpoonLongboatPlugin.ShowTether.Value;
			if (flag && (Object)(object)m_creatureTether == (Object)null)
			{
				GameObject val = new GameObject("HarpoonCreatureTether");
				val.transform.SetParent(((Component)this).transform, false);
				m_creatureTether = val.AddComponent<LineRenderer>();
				m_creatureTether.useWorldSpace = true;
				m_creatureTether.positionCount = 2;
				m_creatureTether.startWidth = 0.18f;
				m_creatureTether.endWidth = 0.04f;
				m_creatureTether.numCapVertices = 4;
				if ((Object)(object)s_tetherMaterial != (Object)null)
				{
					((Renderer)m_creatureTether).sharedMaterial = s_tetherMaterial;
				}
			}
			if (!((Object)(object)m_creatureTether == (Object)null))
			{
				((Component)m_creatureTether).gameObject.SetActive(flag);
				if (flag)
				{
					m_creatureTether.SetPosition(0, GetMuzzlePosition());
					m_creatureTether.SetPosition(1, ((Component)m_creature).transform.position);
				}
			}
		}

		private static string ItemLabel(ItemDrop item)
		{
			if ((Object)(object)item != (Object)null && item.m_itemData != null && item.m_itemData.m_shared != null)
			{
				return item.m_itemData.m_shared.m_name;
			}
			if (!((Object)(object)item != (Object)null))
			{
				return "item";
			}
			return ((Object)((Component)item).gameObject).name;
		}

		private static float EulerToSigned(float euler)
		{
			if (euler > 180f)
			{
				euler -= 360f;
			}
			return euler;
		}
	}
	internal static class HarpoonLongboatAppearance
	{
		private static bool s_loggedMaterials;

		private static Material s_shieldMaterialA;

		private static Material s_shieldMaterialB;

		private static Material s_metalMaterial;

		private static Material s_woodMaterial;

		private static Material s_glowMaterial;

		private static Material s_templateMaterial;

		public static void Apply(GameObject ship)
		{
			//IL_002d: 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_003a: 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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)ship == (Object)null))
			{
				s_templateMaterial = FindTemplateMaterial(ship);
				if ((Object)(object)s_templateMaterial == (Object)null)
				{
					Logger.LogWarning((object)"Harpoon Longboat: no template material found on the ship; custom decorations may render untextured.");
				}
				Bounds hullBounds = GetHullBounds(ship);
				Logger.LogInfo((object)("Harpoon Longboat: hull bounds center=" + ((object)((Bounds)(ref hullBounds)).center/*cast due to .constrained prefix*/).ToString() + " size=" + ((object)((Bounds)(ref hullBounds)).size/*cast due to .constrained prefix*/).ToString()));
				if (HarpoonLongboatPlugin.Recolor.Value)
				{
					Recolor(ship);
				}
				if (HarpoonLongboatPlugin.RemoveSail.Value)
				{
					HideSail(ship);
				}
				if (HarpoonLongboatPlugin.AddShields.Value)
				{
					AddShields(ship, hullBounds);
				}
				if (HarpoonLongboatPlugin.AddLanterns.Value)
				{
					AddLanterns(ship, hullBounds);
				}
				if (HarpoonLongboatPlugin.AddProwHarpoon.Value)
				{
					AddProwHarpoon(ship, hullBounds);
				}
				if (HarpoonLongboatPlugin.AddHearth.Value)
				{
					AddHearth(ship, hullBounds);
				}
				if (HarpoonLongboatPlugin.AddRoof.Value)
				{
					BuildRoof(ship, hullBounds);
				}
				if (BoatCatapultConfig.AddCatapult.Value)
				{
					BoatCatapultSetup.Attach(ship, hullBounds);
				}
			}
		}

		private static void HideSail(GameObject ship)
		{
			Renderer[] componentsInChildren = ship.GetComponentsInChildren<Renderer>(true);
			int num = 0;
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null) && (((Object)((Component)val).transform).name + " " + (((Object)(object)val.sharedMaterial != (Object)null) ? ((Object)val.sharedMaterial).name : "")).ToLowerInvariant().Contains("sail"))
				{
					val.enabled = false;
					num++;
				}
			}
			Logger.LogInfo((object)("Harpoon Longboat: hid " + num + " sail renderer(s)."));
		}

		private static void BuildRoof(GameObject ship, Bounds hull)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Expected O, but got Unknown
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			EnsureMaterials();
			Material sharedMaterial = MakeMaterial(new Color(HarpoonLongboatPlugin.RoofR.Value, HarpoonLongboatPlugin.RoofG.Value, HarpoonLongboatPlugin.RoofB.Value), emissive: false);
			float num = Mathf.Max(2.5f, ((Bounds)(ref hull)).extents.z * 0.6f);
			float num2 = Mathf.Max(1.2f, ((Bounds)(ref hull)).extents.x * 0.9f);
			float num3 = ((Bounds)(ref hull)).max.y - 0.6f;
			float num4 = num3 + Mathf.Max(1f, HarpoonLongboatPlugin.RoofHeight.Value);
			GameObject val = new GameObject("HarpoonRoof");
			val.transform.SetParent(ship.transform, false);
			AddPlacementPart(val, "roof");
			float num5 = 0.11f;
			float[] array = new float[4]
			{
				0f - num2,
				num2,
				0f - num2,
				num2
			};
			float[] array2 = new float[4]
			{
				0f - num,
				0f - num,
				num,
				num
			};
			for (int i = 0; i < array.Length; i++)
			{
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2);
				((Object)obj).name = "HarpoonRoofPost";
				Object.Destroy((Object)(object)obj.GetComponent<Collider>());
				obj.transform.SetParent(val.transform, false);
				obj.transform.localPosition = new Vector3(array[i], (num3 + num4) * 0.5f, array2[i]);
				obj.transform.localScale = new Vector3(num5, Mathf.Max(0.1f, (num4 - num3) * 0.5f), num5);
				MeshRenderer component = obj.GetComponent<MeshRenderer>();
				if ((Object)(object)component != (Object)null)
				{
					((Renderer)component).sharedMaterial = s_woodMaterial;
				}
			}
			float num6 = 30f;
			float num7 = num2 / Mathf.Cos(num6 * (MathF.PI / 180f));
			for (int j = -1; j <= 1; j += 2)
			{
				GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)3);
				((Object)obj2).name = "HarpoonRoofSlab";
				obj2.transform.SetParent(val.transform, false);
				obj2.transform.localPosition = new Vector3((float)j * num2 * 0.5f, num4, 0f);
				obj2.transform.localRotation = Quaternion.Euler(0f, 0f, (float)j * num6);
				obj2.transform.localScale = new Vector3(num7, 0.12f, num * 2f);
				MeshRenderer component2 = obj2.GetComponent<MeshRenderer>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Renderer)component2).sharedMaterial = sharedMaterial;
				}
				Collider component3 = obj2.GetComponent<Collider>();
				if ((Object)(object)component3 != (Object)null)
				{
					component3.isTrigger = false;
				}
			}
			GameObject obj3 = GameObject.CreatePrimitive((PrimitiveType)3);
			((Object)obj3).name = "HarpoonRoofRidge";
			Object.Destroy((Object)(object)obj3.GetComponent<Collider>());
			obj3.transform.SetParent(val.transform, false);
			obj3.transform.localPosition = new Vector3(0f, num4 + Mathf.Tan(num6 * (MathF.PI / 180f)) * num2 * 0.5f, 0f);
			obj3.transform.localScale = new Vector3(0.16f, 0.16f, num * 2f);
			MeshRenderer component4 = obj3.GetComponent<MeshRenderer>();
			if ((Object)(object)component4 != (Object)null)
			{
				((Renderer)component4).sharedMaterial = s_woodMaterial;
			}
		}

		private static void AddHearth(GameObject ship, Bounds hull)
		{
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: 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)
			GameObject val = FindHearthPrefab();
			if ((Object)(object)val == (Object)null)
			{
				Logger.LogWarning((object)"Harpoon Longboat: could not find the vanilla Hearth prefab. No hearth was added.");
				return;
			}
			Logger.LogInfo((object)("Harpoon Longboat: using hearth prefab '" + ((Object)val).name + "'."));
			GameObject val2 = Object.Instantiate<GameObject>(val);
			((Object)val2).name = "HarpoonHearth";
			Fireplace component = val2.GetComponent<Fireplace>();
			GameObject val3 = (((Object)(object)component != (Object)null) ? component.m_firePrefab : null);
			GameObject val4 = (((Object)(object)component != (Object)null) ? component.m_enabledObject : null);
			GameObject val5 = (((Object)(object)component != (Object)null) ? component.m_fullObject : null);
			StripHearthComponents(val2);
			if ((Object)(object)val4 != (Object)null)
			{
				Activate(val4.transform, val2.transform);
			}
			if ((Object)(object)val5 != (Object)null)
			{
				Activate(val5.transform, val2.transform);
			}
			if ((Object)(object)val3 != (Object)null)
			{
				GameObject obj = Object.Instantiate<GameObject>(val3);
				((Object)obj).name = "HarpoonHearthFire";
				HarpoonLongboatPlugin.StripNetworkComponents(obj);
				obj.transform.SetParent(val2.transform, false);
				obj.transform.localPosition = new Vector3(0f, 0.4f, 0f);
			}
			else
			{
				Logger.LogWarning((object)"Harpoon Longboat: hearth fire prefab was null; using the hearth's own particles only.");
			}
			EnableVisuals(val2);
			val2.transform.SetParent(ship.transform, false);
			Vector3 val6 = default(Vector3);
			((Vector3)(ref val6))..ctor(0f, ((Bounds)(ref hull)).max.y - 0.8f, ((Bounds)(ref hull)).center.z);
			val2.transform.localPosition = val6;
			val2.transform.localScale = Vector3.one;
			HarpoonPlacementPart harpoonPlacementPart = val2.AddComponent<HarpoonPlacementPart>();
			harpoonPlacementPart.PartName = "hearth";
			harpoonPlacementPart.ExplicitAnchor = true;
			harpoonPlacementPart.AnchorPosition = val6;
			harpoonPlacementPart.BaseScale = Vector3.one;
			harpoonPlacementPart.BaseRotation = Quaternion.identity;
		}

		private static void StripHearthComponents(GameObject root)
		{
			Component[] componentsInChildren = root.GetComponentsInChildren<Component>(true);
			foreach (Component val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null) && !(val is Transform) && !(val is MeshFilter) && !(val is MeshRenderer) && !(val is SkinnedMeshRenderer) && !(val is LODGroup) && !(val is ParticleSystem) && !(val is ParticleSystemRenderer) && !(val is Light) && !(val is EffectArea) && !(val is SphereCollider))
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}

		private static void EnableVisuals(GameObject root)
		{
			ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true);
			foreach (ParticleSystem val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Activate(((Component)val).transform, root.transform);
					val.Play();
				}
			}
			Light[] componentsInChildren2 = root.GetComponentsInChildren<Light>(true);
			foreach (Light val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					Activate(((Component)val2).transform, root.transform);
					((Behaviour)val2).enabled = true;
					if (val2.intensity <= 0f)
					{
						val2.intensity = 1f;
					}
				}
			}
		}

		private static void AddPlacementPart(GameObject root, string partName)
		{
			//IL_001b: 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)
			//IL_002c: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			HarpoonPlacementPart harpoonPlacementPart = root.AddComponent<HarpoonPlacementPart>();
			harpoonPlacementPart.PartName = partName;
			harpoonPlacementPart.ExplicitAnchor = true;
			harpoonPlacementPart.AnchorPosition = root.transform.localPosition;
			harpoonPlacementPart.BaseScale = root.transform.localScale;
			harpoonPlacementPart.BaseRotation = root.transform.localRotation;
		}

		private static void Activate(Transform t, Transform root)
		{
			while ((Object)(object)t != (Object)null)
			{
				if (!((Component)t).gameObject.activeSelf)
				{
					((Component)t).gameObject.SetActive(true);
				}
				if (!((Object)(object)t == (Object)(object)root))
				{
					t = t.parent;
					continue;
				}
				break;
			}
		}

		private static GameObject FindVanillaPrefab(string name)
		{
			if ((Object)(object)ZNetScene.instance == (Object)null || ZNetScene.instance.m_prefabs == null)
			{
				return null;
			}
			foreach (GameObject prefab in ZNetScene.instance.m_prefabs)
			{
				if ((Object)(object)prefab != (Object)null && string.Equals(((Object)prefab).name, name, StringComparison.OrdinalIgnoreCase))
				{
					return prefab;
				}
			}
			return null;
		}

		private static GameObject FindHearthPrefab()
		{
			if ((Object)(object)ObjectDB.instance != (Object)null)
			{
				List<Piece> allBuildPieces = ObjectDB.instance.GetAllBuildPieces(false);
				if (allBuildPieces != null)
				{
					foreach (Piece item in allBuildPieces)
					{
						if ((Object)(object)item != (Object)null && ((Object)((Component)item).gameObject).name.ToLowerInvariant().Contains("hearth"))
						{
							return ((Component)item).gameObject;
						}
					}
				}
			}
			PrefabManager instance = PrefabManager.Instance;
			GameObject val = ((instance != null) ? instance.GetPrefab("hearth") : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			if ((Object)(object)ZNetScene.instance != (Object)null)
			{
				val = ZNetScene.instance.GetPrefab("hearth");
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			return FindVanillaPrefab("hearth");
		}

		private static void Recolor(GameObject ship)
		{
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0256: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			((Color)(ref val))..ctor(HarpoonLongboatPlugin.HullR.Value, HarpoonLongboatPlugin.HullG.Value, HarpoonLongboatPlugin.HullB.Value);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(HarpoonLongboatPlugin.SailR.Value, HarpoonLongboatPlugin.SailG.Value, HarpoonLongboatPlugin.SailB.Value);
			Renderer[] componentsInChildren = ship.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val3 in componentsInChildren)
			{
				if ((Object)(object)val3 == (Object)null)
				{
					continue;
				}
				Material material = val3.material;
				if ((Object)(object)material == (Object)null || !material.HasProperty("_Color"))
				{
					continue;
				}
				string text = (((Object)((Component)val3).transform).name + " " + ((Object)material).name).ToLowerInvariant();
				if (HarpoonLongboatPlugin.LogMaterialNames.Value && !s_loggedMaterials)
				{
					Logger.LogInfo((object)("Harpoon Longboat: renderer material = '" + ((Object)((Component)val3).transform).name + "' / '" + ((Object)material).name + "'"));
				}
				if (!text.Contains("water") && !text.Contains("shadow") && !text.Contains("hatch") && !text.Contains("blackhole") && !text.Contains("pixel") && !text.Contains("insects") && !text.Contains("lighting") && !text.Contains("default-material") && !text.Contains("collider"))
				{
					Color color = material.color;
					if (text.Contains("sail") || text.Contains("cloth") || text.Contains("flag") || text.Contains("banner"))
					{
						material.color = new Color(color.r * val2.r, color.g * val2.g, color.b * val2.b, color.a);
					}
					else
					{
						material.color = new Color(color.r * val.r, color.g * val.g, color.b * val.b, color.a);
					}
				}
			}
			s_loggedMaterials = true;
		}

		private static void AddShields(GameObject ship, Bounds hull)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			EnsureMaterials();
			int num = Mathf.Clamp(HarpoonLongboatPlugin.ShieldCount.Value, 0, 16);
			if (num == 0)
			{
				return;
			}
			float num2 = Mathf.Max(0.5f, HarpoonLongboatPlugin.ShieldSpacing.Value);
			float num3 = (float)(num - 1) * 0.5f;
			float z = ((Bounds)(ref hull)).center.z;
			GameObject val = new GameObject("HarpoonShields");
			val.transform.SetParent(ship.transform, false);
			for (int i = 0; i < num; i++)
			{
				float num4 = z + ((float)i - num3) * num2;
				for (int j = -1; j <= 1; j += 2)
				{
					GameObject obj = CreateDisc("HarpoonShield");
					obj.transform.SetParent(val.transform, false);
					obj.transform.localPosition = new Vector3((float)j * HarpoonLongboatPlugin.ShieldSideOffset.Value, HarpoonLongboatPlugin.ShieldHeight.Value, num4);
					obj.transform.localRotation = Quaternion.Euler(0f, 0f, (j > 0) ? (-90f) : 90f);
					MeshRenderer component = obj.GetComponent<MeshRenderer>();
					if ((Object)(object)component != (Object)null)
					{
						((Renderer)component).sharedMaterial = ((i % 2 == 0) ? s_shieldMaterialA : s_shieldMaterialB);
					}
				}
			}
		}

		private static void AddLanterns(GameObject ship, Bounds hull)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0034: 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_0059: 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_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			EnsureMaterials();
			GameObject val = new GameObject("HarpoonLanterns");
			val.transform.SetParent(ship.transform, false);
			AddPlacementPart(val, "lanterns");
			float num = Mathf.Max(2f, (((Bounds)(ref hull)).max.z - ((Bounds)(ref hull)).min.z) * 0.3f);
			float num2 = Mathf.Clamp(((Bounds)(ref hull)).extents.x * 0.8f, 1f, 3.5f);
			float value = HarpoonLongboatPlugin.LanternHeight.Value;
			float[] array = new float[4]
			{
				0f - num2,
				num2,
				0f - num2,
				num2
			};
			float[] array2 = new float[4]
			{
				0f - num,
				0f - num,
				num,
				num
			};
			for (int i = 0; i < array.Length; i++)
			{
				GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0);
				((Object)obj).name = "HarpoonLantern";
				Collider component = obj.GetComponent<Collider>();
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				obj.transform.SetParent(val.transform, false);
				obj.transform.localPosition = new Vector3(array[i], value, array2[i]);
				obj.transform.localScale = new Vector3(0.45f, 0.45f, 0.45f);
				MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
				if ((Object)(object)component2 != (Object)null)
				{
					((Renderer)component2).sharedMaterial = s_glowMaterial;
				}
				Light obj2 = obj.AddComponent<Light>();
				obj2.type = (LightType)2;
				obj2.color = new Color(1f, 0.72f, 0.35f);
				obj2.range = 14f;
				obj2.intensity = 1.6f;
				obj2.shadows = (LightShadows)0;
			}
		}

		private static void AddProwHarpoon(GameObject ship, Bounds hull)
		{
			//IL_007c: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: 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_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			EnsureMaterials();
			float num = 1f;
			Ship component = ship.GetComponent<Ship>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_rudderObject != (Object)null)
			{
				float z = component.m_rudderObject.transform.localPosition.z;
				if (Mathf.Abs(z) > 0.5f)
				{
					num = ((z > 0f) ? (-1f) : 1f);
				}
			}
			float num2 = ((num > 0f) ? ((Bounds)(ref hull)).max.z : ((Bounds)(ref hull)).min.z);
			GameObject val = new GameObject("HarpoonProw");
			val.transform.SetParent(ship.transform, false);
			val.transform.localPosition = new Vector3(0f, HarpoonLongboatPlugin.LanternHeight.Value - 0.2f, num2);
			val.transform.localRotation = Quaternion.Euler(-30f, (num > 0f) ? 0f : 180f, 0f);
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj).name = "HarpoonProwShaft";
			Object.Destroy((Object)(object)obj.GetComponent<Collider>());
			obj.transform.SetParent(val.transform, false);
			obj.transform.localPosition = new Vector3(0f, 0f, 1.6f);
			obj.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			obj.transform.localScale = new Vector3(0.12f, 1.8f, 0.12f);
			MeshRenderer component2 = obj.GetComponent<MeshRenderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				((Renderer)component2).sharedMaterial = s_woodMaterial;
			}
			GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj2).name = "HarpoonProwTip";
			Object.Destroy((Object)(object)obj2.GetComponent<Collider>());
			obj2.transform.SetParent(val.transform, false);
			obj2.transform.localPosition = new Vector3(0f, 0f, 3.6f);
			obj2.transform.localRotation = Quaternion.Euler(90f, 0f, 0f);
			obj2.transform.localScale = new Vector3(0.22f, 0.45f, 0.22f);
			MeshRenderer component3 = obj2.GetComponent<MeshRenderer>();
			if ((Object)(object)component3 != (Object)null)
			{
				((Renderer)component3).sharedMaterial = s_metalMaterial;
			}
		}

		private static GameObject CreateDisc(string name)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2);
			((Object)obj).name = name;
			Collider component = obj.GetComponent<Collider>();
			if ((Object)(object)component != (Object)null)
			{
				Object.Destroy((Object)(object)component);
			}
			obj.transform.localScale = new Vector3(0.75f, 0.06f, 0.75f);
			return obj;
		}

		private static void EnsureMaterials()
		{
			//IL_001d: 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_005b: 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_0099: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)s_shieldMaterialA != (Object)null))
			{
				s_shieldMaterialA = MakeMaterial(new Color(0.55f, 0.12f, 0.12f), emissive: false);
				s_shieldMaterialB = MakeMaterial(new Color(0.85f, 0.8f, 0.68f), emissive: false);
				s_metalMaterial = MakeMaterial(new Color(0.68f, 0.7f, 0.74f), emissive: false);
				s_woodMaterial = MakeMaterial(new Color(0.34f, 0.22f, 0.12f), emissive: false);
				s_glowMaterial = MakeMaterial(new Color(1f, 0.78f, 0.45f), emissive: true);
			}
		}

		private static Material FindTemplateMaterial(GameObject ship)
		{
			Renderer[] componentsInChildren = ship.GetComponentsInChildren<Renderer>(true);
			Renderer[] array = componentsInChildren;
			foreach (Renderer val in array)
			{
				if (!((Object)(object)val == (Object)null))