Decompiled source of Corvette v0.4.2

plugins/Corvette.dll

Decompiled 15 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("Corvette")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.4.2.0")]
[assembly: AssemblyInformationalVersion("0.4.2")]
[assembly: AssemblyProduct("Corvette")]
[assembly: AssemblyTitle("Corvette")]
[assembly: AssemblyVersion("0.4.2.0")]
namespace Corvette;

public class Airship : MonoBehaviour
{
	private const string LevelKey = "vvlee_air_level";

	private const string InputRpc = "VVLEE_AirInput";

	private const string FuelKey = "vvlee_air_fuel";

	private const string FuelRpc = "VVLEE_AirFuel";

	private const float AirborneHeight = 1.5f;

	private const float InputHold = 0.6f;

	private const float SendInterval = 0.2f;

	private const float LeadUp = 2.5f;

	private const float LeadDown = 5f;

	private const float MessageInterval = 8f;

	public float Level = float.NegativeInfinity;

	private ZNetView m_nview;

	private Ship m_ship;

	private WearNTear m_wear;

	private Rigidbody m_body;

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

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

	private float m_input;

	private float m_inputTime = -99f;

	private float m_sendTimer;

	private float m_lastSent;

	private float m_messageTimer;

	private float m_wearTimer;

	private float m_baseBackward;

	private float m_baseSteer;

	private float m_spin;

	private GameObject m_lit;

	private static float SeaLevel
	{
		get
		{
			if (!((Object)(object)ZoneSystem.instance != (Object)null))
			{
				return 30f;
			}
			return ZoneSystem.instance.m_waterLevel;
		}
	}

	public bool Crippled => HealthPercent() < CorvettePlugin.AirshipCrippledHealth.Value;

	private void Awake()
	{
		//IL_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Expected O, but got Unknown
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_ship = ((Component)this).GetComponent<Ship>();
		m_wear = ((Component)this).GetComponent<WearNTear>();
		m_body = ((Component)this).GetComponent<Rigidbody>();
		if ((Object)(object)m_ship != (Object)null)
		{
			m_baseBackward = m_ship.m_backwardForce;
			m_baseSteer = m_ship.m_stearForce;
		}
		Transform val = ((Component)this).transform.Find("corvette");
		if ((Object)(object)val != (Object)null)
		{
			foreach (Transform item in val)
			{
				Transform val2 = item;
				if (((Object)val2).name == "AirProp")
				{
					m_props.Add(val2);
				}
				else if (((Object)val2).name == "AirRotor")
				{
					m_rotors.Add(val2);
				}
			}
		}
		object lit;
		if (!((Object)(object)val != (Object)null))
		{
			lit = null;
		}
		else
		{
			Transform obj = val.Find("BoilerLit");
			lit = ((obj != null) ? ((Component)obj).gameObject : null);
		}
		m_lit = (GameObject)lit;
		if (!((Object)(object)m_nview == (Object)null) && m_nview.GetZDO() != null)
		{
			m_nview.Register<float>("VVLEE_AirInput", (Action<long, float>)RPC_Input);
			m_nview.Register("VVLEE_AirFuel", (Action<long>)RPC_AddFuel);
			Level = m_nview.GetZDO().GetFloat("vvlee_air_level", float.NegativeInfinity);
		}
	}

	private float HealthPercent()
	{
		if ((Object)(object)m_wear == (Object)null || (Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return 100f;
		}
		return m_wear.GetHealthPercentage() * 100f;
	}

	private float HullY()
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		return m_body.worldCenterOfMass.y - m_ship.m_waterLevelOffset;
	}

	private float Altitude()
	{
		return HullY() - SeaLevel;
	}

	public float GetFuel()
	{
		if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid())
		{
			return 0f;
		}
		return m_nview.GetZDO().GetFloat("vvlee_air_fuel", 0f);
	}

	public bool HasSteam()
	{
		if (CorvettePlugin.AirshipRequireFuel.Value)
		{
			return GetFuel() > 0f;
		}
		return true;
	}

	public void AddFuel()
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
		{
			m_nview.InvokeRPC("VVLEE_AirFuel", Array.Empty<object>());
		}
	}

	private void RPC_AddFuel(long sender)
	{
		if (m_nview.IsOwner())
		{
			float num = Mathf.Min(GetFuel() + 1f, (float)CorvettePlugin.AirshipFuelCapacity.Value);
			m_nview.GetZDO().Set("vvlee_air_fuel", num);
		}
	}

	private void RPC_Input(long sender, float input)
	{
		m_input = Mathf.Clamp(input, -1f, 1f);
		m_inputTime = Time.time;
	}

	private void Update()
	{
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Invalid comparison between Unknown and I4
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || (Object)(object)m_ship == (Object)null || (Object)(object)m_body == (Object)null)
		{
			return;
		}
		float deltaTime = Time.deltaTime;
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.GetControlledShip() == (Object)(object)m_ship)
		{
			float num = 0f;
			if (!InputBlocked())
			{
				if (ZInput.GetButton("Jump") || ZInput.GetButton("JoyJump"))
				{
					num += 1f;
				}
				if (ZInput.GetButton("Crouch") || ZInput.GetButton("JoyCrouch"))
				{
					num -= 1f;
				}
			}
			m_sendTimer -= deltaTime;
			if (num != m_lastSent || (num != 0f && m_sendTimer <= 0f))
			{
				m_sendTimer = 0.2f;
				m_lastSent = num;
				m_nview.InvokeRPC("VVLEE_AirInput", new object[1] { num });
			}
			if (num > 0f && !HasSteam())
			{
				Message("$vvlee_air_nofuel");
			}
			else if (num > 0f && HealthPercent() < CorvettePlugin.AirshipNoClimbHealth.Value)
			{
				Message("$vvlee_air_noclimb");
			}
		}
		m_messageTimer -= deltaTime;
		if ((Object)(object)localPlayer != (Object)null && m_ship.IsPlayerInBoat(localPlayer))
		{
			bool flag = Altitude() > 1.5f;
			if (flag && !HasSteam())
			{
				Message("$vvlee_air_nofuel");
			}
			else if (flag && CorvettePlugin.AirshipRequireFuel.Value && GetFuel() < 2f)
			{
				Message("$vvlee_air_lowfuel");
			}
			else if (Crippled && Altitude() > CorvettePlugin.AirshipEmergencyAltitude.Value + 5f)
			{
				Message("$vvlee_air_crippled");
			}
			else if (Altitude() > CorvettePlugin.AirshipWearAltitude.Value)
			{
				Message("$vvlee_air_wear");
			}
			else if (Altitude() > CorvettePlugin.AirshipWarnAltitude.Value)
			{
				Message("$vvlee_air_warn");
			}
		}
		bool flag2 = (CorvettePlugin.AirshipRequireFuel.Value ? (GetFuel() > 0f) : (Altitude() > 1.5f));
		if ((Object)(object)m_lit != (Object)null && m_lit.activeSelf != flag2)
		{
			m_lit.SetActive(flag2);
		}
		bool flag3 = HasSteam() && (Altitude() > 1.5f || (int)m_ship.GetSpeedSetting() > 0);
		m_spin = Mathf.MoveTowards(m_spin, flag3 ? 1f : 0f, deltaTime * 0.5f);
		if (!(m_spin > 0.001f))
		{
			return;
		}
		float num2 = 540f * m_spin * deltaTime;
		foreach (Transform prop in m_props)
		{
			prop.Rotate(0f, 0f, num2, (Space)1);
		}
		foreach (Transform rotor in m_rotors)
		{
			rotor.Rotate(0f, 0f, num2 * 1.4f, (Space)1);
		}
	}

	private static bool InputBlocked()
	{
		if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible() && !InventoryGui.IsVisible())
		{
			return Minimap.IsOpen();
		}
		return true;
	}

	private void Message(string text)
	{
		if (!(m_messageTimer > 0f) && !((Object)(object)MessageHud.instance == (Object)null))
		{
			m_messageTimer = 8f;
			MessageHud.instance.ShowMessage((MessageType)2, text, 0, (Sprite)null, false, true);
		}
	}

	private void FixedUpdate()
	{
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || (Object)(object)m_ship == (Object)null || (Object)(object)m_body == (Object)null)
		{
			return;
		}
		if (!m_nview.IsOwner())
		{
			Level = m_nview.GetZDO().GetFloat("vvlee_air_level", float.NegativeInfinity);
			return;
		}
		float fixedDeltaTime = Time.fixedDeltaTime;
		float seaLevel = SeaLevel;
		float num = HullY();
		float num2 = HealthPercent();
		bool flag = num2 < CorvettePlugin.AirshipCrippledHealth.Value;
		float value = CorvettePlugin.AirshipClimbRate.Value;
		float num3 = (float.IsNegativeInfinity(Level) ? num : Level);
		float num4 = ((Time.time - m_inputTime < 0.6f) ? m_input : 0f);
		if (num2 < CorvettePlugin.AirshipNoClimbHealth.Value)
		{
			num4 = Mathf.Min(num4, 0f);
		}
		if (CorvettePlugin.AirshipRequireFuel.Value)
		{
			float num5 = GetFuel();
			if (num5 > 0f && num - seaLevel > 1.5f)
			{
				num5 = Mathf.Max(0f, num5 - fixedDeltaTime / CorvettePlugin.AirshipSecondsPerCoal.Value);
				m_nview.GetZDO().Set("vvlee_air_fuel", num5);
			}
			if (num5 <= 0f)
			{
				num4 = Mathf.Min(num4, 0f);
				num3 -= value * 0.5f * fixedDeltaTime;
			}
		}
		num3 += num4 * value * fixedDeltaTime;
		if (flag)
		{
			float num6 = seaLevel + CorvettePlugin.AirshipEmergencyAltitude.Value;
			if (num3 > num6)
			{
				num3 = Mathf.Max(num6, num3 - value * 0.5f * fixedDeltaTime);
			}
		}
		num3 = Mathf.Min(num3, seaLevel + CorvettePlugin.AirshipMaxAltitude.Value);
		num3 = Mathf.Clamp(num3, num - 5f, num + 2.5f);
		num3 = Mathf.Max(num3, seaLevel);
		if (Mathf.Abs(num3 - Level) > 0.001f)
		{
			Level = num3;
			m_nview.GetZDO().Set("vvlee_air_level", num3);
		}
		float num7 = (flag ? CorvettePlugin.AirshipCrippledSpeed.Value : 1f);
		m_ship.m_backwardForce = m_baseBackward * num7 * num7;
		m_ship.m_stearForce = m_baseSteer * num7 * num7;
		if (num - seaLevel > CorvettePlugin.AirshipWearAltitude.Value && (Object)(object)m_wear != (Object)null)
		{
			m_wearTimer += fixedDeltaTime;
			if (m_wearTimer >= 1f)
			{
				float num8 = m_nview.GetZDO().GetFloat(ZDOVars.s_health, m_wear.m_health);
				float num9 = m_wear.m_health * CorvettePlugin.AirshipWearPerSecond.Value / 100f * m_wearTimer;
				m_wearTimer = 0f;
				WearUtil.SetHealth(m_nview, Mathf.Max(1f, num8 - num9));
			}
		}
	}
}
public class AirshipBoiler : MonoBehaviour, Hoverable, Interactable
{
	private const float HoldRepeat = 0.2f;

	public EffectList m_fuelAddedEffects = new EffectList();

	private Airship m_airship;

	private float m_lastUse;

	private void Awake()
	{
		m_airship = ((Component)this).GetComponentInParent<Airship>();
	}

	private static string FuelName()
	{
		GameObject val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab("Coal") : null);
		ItemDrop val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<ItemDrop>() : null);
		if (!((Object)(object)val2 != (Object)null))
		{
			return "$item_coal";
		}
		return val2.m_itemData.m_shared.m_name;
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$vvlee_air_boiler");
	}

	public string GetHoverText()
	{
		if ((Object)(object)m_airship == (Object)null)
		{
			return "";
		}
		string text = FuelName();
		return Localization.instance.Localize($"$vvlee_air_boiler ({text} {Mathf.CeilToInt(m_airship.GetFuel())}/{CorvettePlugin.AirshipFuelCapacity.Value})\n" + "[<color=yellow><b>$KEY_Use</b></color>] $piece_smelter_add " + text);
	}

	public bool Interact(Humanoid user, bool hold, bool alt)
	{
		//IL_00b0: 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_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)
		if ((Object)(object)m_airship == (Object)null)
		{
			return false;
		}
		if (hold && Time.time - m_lastUse < 0.2f)
		{
			return false;
		}
		m_lastUse = Time.time;
		string text = FuelName();
		if (m_airship.GetFuel() > (float)(CorvettePlugin.AirshipFuelCapacity.Value - 1))
		{
			((Character)user).Message((MessageType)2, "$msg_itsfull", 0, (Sprite)null, false);
			return false;
		}
		Inventory inventory = user.GetInventory();
		if (inventory == null || !inventory.HaveItem(text, true))
		{
			((Character)user).Message((MessageType)2, "$msg_donthaveany " + text, 0, (Sprite)null, false);
			return false;
		}
		inventory.RemoveItem(text, 1, -1, true);
		m_airship.AddFuel();
		m_fuelAddedEffects.Create(((Component)this).transform.position, ((Component)this).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
		((Character)user).Message((MessageType)2, "$msg_added " + text, 0, (Sprite)null, false);
		return true;
	}

	public float GetHoverOffset()
	{
		return 0f;
	}

	public bool UseItem(Humanoid user, ItemData item)
	{
		return false;
	}
}
[HarmonyPatch(typeof(Ship), "CustomFixedUpdate")]
public static class AirshipFloatPatch
{
	private static Airship s_current;

	private static void Prefix(Ship __instance)
	{
		s_current = ((Component)__instance).GetComponent<Airship>();
	}

	private static void Postfix()
	{
		s_current = null;
	}

	public static float GetLevel(Vector3 point, ref WaterVolume previous)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		float waterLevel = Floating.GetWaterLevel(point, ref previous);
		if (!((Object)(object)s_current != (Object)null))
		{
			return waterLevel;
		}
		return Mathf.Max(waterLevel, s_current.Level);
	}

	private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
	{
		MethodInfo original = AccessTools.Method(typeof(Floating), "GetWaterLevel", new Type[2]
		{
			typeof(Vector3),
			typeof(WaterVolume).MakeByRefType()
		}, (Type[])null);
		MethodInfo replacement = AccessTools.Method(typeof(AirshipFloatPatch), "GetLevel", (Type[])null, (Type[])null);
		int count = 0;
		foreach (CodeInstruction instruction in instructions)
		{
			if (original != null && CodeInstructionExtensions.Calls(instruction, original))
			{
				instruction.operand = replacement;
				count++;
			}
			yield return instruction;
		}
		if (count == 0)
		{
			CorvettePlugin.Log.LogError((object)"Airship: Ship.CustomFixedUpdate water level calls not found; airships will not fly.");
		}
	}
}
[HarmonyPatch(typeof(Player), "SetControls")]
public static class AirshipHelmInputPatch
{
	private static void Prefix(Player __instance, ref bool jump, ref bool crouch)
	{
		if (jump || crouch)
		{
			Ship controlledShip = __instance.GetControlledShip();
			if (!((Object)(object)controlledShip == (Object)null) && !((Object)(object)((Component)controlledShip).GetComponent<Airship>() == (Object)null))
			{
				jump = false;
				crouch = false;
			}
		}
	}
}
[HarmonyPatch(typeof(Turret), "UpdateAttack")]
public static class BallistaReload
{
	private const float CheckInterval = 2f;

	private static readonly Dictionary<Turret, float> s_nextCheck = new Dictionary<Turret, float>();

	private static readonly Collider[] s_colliders = (Collider[])(object)new Collider[256];

	private static readonly HashSet<Container> s_seen = new HashSet<Container>();

	private static int s_mask;

	private static void Postfix(Turret __instance)
	{
		//IL_00e3: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Unknown result type (might be due to invalid IL or missing references)
		if (!CorvettePlugin.BallistaAutoReload.Value || __instance.m_maxAmmo <= 0)
		{
			return;
		}
		float time = Time.time;
		if (s_nextCheck.TryGetValue(__instance, out var value) && time < value)
		{
			return;
		}
		if (s_nextCheck.Count > 512)
		{
			s_nextCheck.Clear();
		}
		s_nextCheck[__instance] = time + 2f;
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
		{
			return;
		}
		int ammo = __instance.GetAmmo();
		int num = __instance.m_maxAmmo - ammo;
		if (num > 0)
		{
			string requiredType = ((ammo > 0) ? __instance.GetAmmoType() : null);
			if (TakeAmmo(__instance, requiredType, num, out var type, out var taken))
			{
				ZDO zDO = component.GetZDO();
				zDO.Set(ZDOVars.s_ammo, ammo + taken, false);
				zDO.Set(ZDOVars.s_ammoType, type);
				__instance.m_addAmmoEffect.Create(((Component)__instance).transform.position, ((Component)__instance).transform.rotation, (Transform)null, 1f, -1, default(ZDOID));
			}
		}
	}

	private static bool TakeAmmo(Turret turret, string requiredType, int wanted, out string type, out int taken)
	{
		//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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: 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)
		type = null;
		taken = 0;
		if (s_mask == 0)
		{
			s_mask = LayerMask.GetMask(new string[5] { "piece", "piece_nonsolid", "item", "vehicle", "Default" });
		}
		Vector3 position = ((Component)turret).transform.position;
		int num = Physics.OverlapSphereNonAlloc(position, CorvettePlugin.BallistaReloadRange.Value, s_colliders, s_mask);
		Container val = null;
		ItemData val2 = null;
		float num2 = float.MaxValue;
		s_seen.Clear();
		for (int i = 0; i < num; i++)
		{
			Container componentInParent = ((Component)s_colliders[i]).GetComponentInParent<Container>();
			if ((Object)(object)componentInParent == (Object)null || !s_seen.Add(componentInParent))
			{
				continue;
			}
			float num3 = Vector3.Distance(((Component)componentInParent).transform.position, position);
			if (num3 >= num2 || componentInParent.IsInUse() || (componentInParent.m_checkGuardStone && !PrivateArea.CheckAccess(((Component)componentInParent).transform.position, 0f, false, false)))
			{
				continue;
			}
			Inventory inventory = componentInParent.GetInventory();
			if (inventory != null)
			{
				ItemData val3 = FindAmmo(turret, inventory, requiredType);
				if (val3 != null)
				{
					val = componentInParent;
					val2 = val3;
					num2 = num3;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		ZNetView val4 = ((Component)val).GetComponent<ZNetView>() ?? ((Component)val).GetComponentInParent<ZNetView>();
		if ((Object)(object)val4 == (Object)null || !val4.IsValid())
		{
			return false;
		}
		if (!val4.IsOwner())
		{
			val4.ClaimOwnership();
		}
		type = ((Object)val2.m_dropPrefab).name;
		taken = Mathf.Min(wanted, val2.m_stack);
		return val.GetInventory().RemoveItem(val2, taken);
	}

	private static ItemData FindAmmo(Turret turret, Inventory inventory, string requiredType)
	{
		//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_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		foreach (ItemData allItem in inventory.GetAllItems())
		{
			if ((Object)(object)allItem.m_dropPrefab == (Object)null)
			{
				continue;
			}
			string name = ((Object)allItem.m_dropPrefab).name;
			if (requiredType != null && name != requiredType)
			{
				continue;
			}
			foreach (AmmoType item in turret.m_allowedAmmo)
			{
				if ((Object)(object)item.m_ammo != (Object)null && ((Object)item.m_ammo).name == name)
				{
					return allItem;
				}
			}
		}
		return null;
	}
}
public interface IGunWear
{
	bool CanFire();

	void AddShot();
}
internal static class WearUtil
{
	public static void SetHealth(ZNetView nview, float health)
	{
		nview.GetZDO().Set(ZDOVars.s_health, health);
		nview.InvokeRPC(ZNetView.Everybody, "RPC_HealthChanged", new object[1] { health });
	}
}
public class CannonDurability : MonoBehaviour, Hoverable, IGunWear
{
	[HarmonyPatch(typeof(WearNTear), "RPC_Repair")]
	private static class WearNTearRepair
	{
		private static void Postfix(WearNTear __instance)
		{
			CannonDurability component = ((Component)__instance).GetComponent<CannonDurability>();
			if ((Object)(object)component != (Object)null)
			{
				component.ResetShots();
			}
			ShipGunWear component2 = ((Component)__instance).GetComponent<ShipGunWear>();
			if ((Object)(object)component2 != (Object)null)
			{
				component2.ResetShots();
			}
		}
	}

	private const string ShotsKey = "vvlee_cannon_shots";

	private const float MinHealthFraction = 0.1f;

	private ZNetView m_nview;

	private WearNTear m_wear;

	private int Shots
	{
		get
		{
			if (!((Object)(object)m_nview != (Object)null) || !m_nview.IsValid())
			{
				return 0;
			}
			return m_nview.GetZDO().GetInt("vvlee_cannon_shots", 0);
		}
	}

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_wear = ((Component)this).GetComponent<WearNTear>();
	}

	public bool CanFire()
	{
		int value = CorvettePlugin.MaxShots.Value;
		if (value > 0)
		{
			return Shots < value;
		}
		return true;
	}

	public void AddShot()
	{
		int value = CorvettePlugin.MaxShots.Value;
		if (value > 0 && !((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
		{
			int num = Shots + 1;
			m_nview.GetZDO().Set("vvlee_cannon_shots", num);
			if ((Object)(object)m_wear != (Object)null)
			{
				float num2 = Mathf.Clamp01((float)num / (float)value);
				WearUtil.SetHealth(m_nview, m_wear.m_health * Mathf.Lerp(1f, 0.1f, num2));
			}
		}
	}

	public void ResetShots()
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner())
		{
			m_nview.GetZDO().Set("vvlee_cannon_shots", 0);
		}
	}

	public string GetHoverText()
	{
		int value = CorvettePlugin.MaxShots.Value;
		if (value <= 0 || (Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return GetHoverName();
		}
		int num = Mathf.Max(0, value - Shots);
		string text = "$piece_vvlee_cannon\n$vvlee_cannon_durability: " + num + " / " + value;
		if (num == 0)
		{
			text += "\n<color=red>$vvlee_cannon_needs_repair</color>";
		}
		return Localization.instance.Localize(text);
	}

	public string GetHoverName()
	{
		return Localization.instance.Localize("$piece_vvlee_cannon");
	}

	public float GetHoverOffset()
	{
		return 0f;
	}
}
public class ShipGunWear : MonoBehaviour, IGunWear
{
	private const string ShotsKey = "vvlee_ship_shots";

	private ZNetView m_nview;

	private WearNTear m_wear;

	private void Awake()
	{
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_wear = ((Component)this).GetComponent<WearNTear>();
	}

	public bool CanFire()
	{
		if ((Object)(object)m_wear == (Object)null || (Object)(object)m_nview == (Object)null || !m_nview.IsValid())
		{
			return true;
		}
		return m_wear.GetHealthPercentage() >= CorvettePlugin.ShipCeaseFireHealth.Value / 100f;
	}

	public void ResetShots()
	{
		if ((Object)(object)m_nview != (Object)null && m_nview.IsValid() && m_nview.IsOwner())
		{
			m_nview.GetZDO().Set("vvlee_ship_shots", 0);
		}
	}

	public void AddShot()
	{
		if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid())
		{
			int num = m_nview.GetZDO().GetInt("vvlee_ship_shots", 0) + 1;
			m_nview.GetZDO().Set("vvlee_ship_shots", num);
			int value = CorvettePlugin.ShipFreeShots.Value;
			if (!((Object)(object)m_wear == (Object)null) && value > 0 && num > value)
			{
				float num2 = m_nview.GetZDO().GetFloat(ZDOVars.s_health, m_wear.m_health);
				float num3 = m_wear.m_health * CorvettePlugin.ShipWearPerShot.Value / 100f;
				WearUtil.SetHealth(m_nview, Mathf.Max(1f, num2 - num3));
			}
		}
	}
}
public static class CannonTrees
{
	private class CannonBlast : MonoBehaviour
	{
	}

	[HarmonyPatch(typeof(Projectile), "SpawnOnHit")]
	private static class ProjectileSpawnOnHit
	{
		private static void Prefix(Projectile __instance, out bool __state)
		{
			__state = s_spawning;
			s_spawning = IsCannonSource((Component)(object)__instance);
		}

		private static void Finalizer(bool __state)
		{
			s_spawning = __state;
		}
	}

	[HarmonyPatch(typeof(Aoe), "CustomFixedUpdate")]
	private static class AoeFixedUpdate
	{
		private static void Prefix(Aoe __instance, out bool __state)
		{
			__state = s_spawning;
			s_spawning = IsCannonSource((Component)(object)__instance);
		}

		private static void Finalizer(bool __state)
		{
			s_spawning = __state;
		}
	}

	[HarmonyPatch(typeof(Projectile), "Setup")]
	private static class ProjectileSetup
	{
		private static void Postfix(Projectile __instance)
		{
			Tag((Component)(object)__instance);
		}
	}

	[HarmonyPatch(typeof(Aoe), "Setup")]
	private static class AoeSetup
	{
		private static void Postfix(Aoe __instance)
		{
			Tag((Component)(object)__instance);
		}
	}

	[HarmonyPatch(typeof(Projectile), "OnHit")]
	private static class ProjectileOnHit
	{
		private static void Prefix(Projectile __instance, out bool __state)
		{
			__state = s_hitting;
			s_hitting = IsCannonSource((Component)(object)__instance);
		}

		private static void Finalizer(bool __state)
		{
			s_hitting = __state;
		}
	}

	[HarmonyPatch(typeof(Aoe), "OnHit")]
	private static class AoeOnHit
	{
		private static void Prefix(Aoe __instance, out bool __state)
		{
			__state = s_hitting;
			s_hitting = IsCannonSource((Component)(object)__instance);
		}

		private static void Finalizer(bool __state)
		{
			s_hitting = __state;
		}
	}

	[HarmonyPatch(typeof(TreeBase), "Damage")]
	private static class TreeBaseDamage
	{
		private static void Prefix(HitData hit)
		{
			AddChop(hit);
		}
	}

	[HarmonyPatch(typeof(TreeLog), "Damage")]
	private static class TreeLogDamage
	{
		private static void Prefix(HitData hit)
		{
			AddChop(hit);
		}
	}

	[HarmonyPatch(typeof(Destructible), "Damage")]
	private static class DestructibleDamage
	{
		private static void Prefix(Destructible __instance, HitData hit)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)__instance.GetDestructibleType() == 2)
			{
				AddChop(hit);
			}
		}
	}

	private const short ToolTier = 10;

	private static bool s_spawning;

	private static bool s_hitting;

	private static bool IsCannonSource(Component source)
	{
		if (!((Object)(object)source.GetComponent<CorvetteShell>() != (Object)null))
		{
			return (Object)(object)source.GetComponent<CannonBlast>() != (Object)null;
		}
		return true;
	}

	private static void Tag(Component spawned)
	{
		if (s_spawning && (Object)(object)spawned.GetComponent<CannonBlast>() == (Object)null)
		{
			spawned.gameObject.AddComponent<CannonBlast>();
		}
	}

	private static void AddChop(HitData hit)
	{
		if (!s_hitting || hit == null)
		{
			return;
		}
		float value = CorvettePlugin.TreeDamage.Value;
		if (!(value <= 0f) && !(hit.m_damage.m_chop > 0f))
		{
			hit.m_damage.m_chop = ((DamageTypes)(ref hit.m_damage)).GetTotalDamage() * value / 100f;
			if (hit.m_toolTier < 10)
			{
				hit.m_toolTier = 10;
			}
		}
	}
}
public class CorvetteGuns : MonoBehaviour
{
	private class Cannon
	{
		public Transform Mount;

		public Transform Body;

		public Transform Neck;

		public Transform Eye;

		public string Kind;

		public Character Target;

		public float ScanTimer;

		public float ReadyTime;

		public bool Aimed;

		public int ShotsInBurst;

		public int CanisterVolleys;
	}

	private const float ScanInterval = 0.5f;

	private const float TurnRate = 90f;

	private const float MaxPitchUp = 40f;

	private const float MaxPitchDown = 25f;

	private const float FireAimTolerance = 3f;

	private const float HitNoise = 40f;

	private const float CartMaxSpeed = 0.3f;

	private const float SeatRadius = 0.6f;

	private const float FriendlyCheckRadius = 0.4f;

	private static readonly RaycastHit[] s_hits = (RaycastHit[])(object)new RaycastHit[64];

	private static bool s_canisterWarned;

	private readonly List<Cannon> m_cannons = new List<Cannon>();

	private ZNetView m_nview;

	private Ship m_ship;

	private IGunWear m_wear;

	private Vagon m_cart;

	private Transform m_captainSeat;

	private Transform m_helmSeat;

	private Rigidbody m_body;

	private EffectList m_shootEffect;

	private ItemData m_staff;

	private GameObject m_projectilePrefab;

	private float m_projectileVel;

	private float m_projectileGravity;

	private float m_projectileAccuracy;

	private ItemData m_canisterStaff;

	private GameObject m_canisterPrefab;

	private float m_canisterVel;

	private float m_canisterGravity;

	private float m_canisterSpread;

	private int m_losMask;

	private int m_friendlyMask;

	private bool m_ready;

	private void Awake()
	{
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Expected O, but got Unknown
		m_nview = ((Component)this).GetComponent<ZNetView>();
		m_ship = ((Component)this).GetComponent<Ship>();
		m_wear = ((Component)this).GetComponent<IGunWear>();
		m_cart = ((Component)this).GetComponent<Vagon>();
		Transform val = ((Component)this).transform.Find("CaptainSeat");
		Chair val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponentInChildren<Chair>(true) : null);
		m_captainSeat = (Object.op_Implicit((Object)(object)val2) ? val2.m_attachPoint : null);
		m_helmSeat = (((Object)(object)m_ship != (Object)null && (Object)(object)m_ship.m_shipControlls != (Object)null) ? m_ship.m_shipControlls.m_attachPoint : null);
		m_body = ((Component)this).GetComponent<Rigidbody>();
		foreach (Transform item in ((Component)this).transform)
		{
			Transform val3 = item;
			if (((Object)val3).name.StartsWith("CorvetteCannon_"))
			{
				Cannon cannon = new Cannon
				{
					Mount = val3,
					Body = Utils.FindChild(val3, "BodyRotation", (IterativeSearchType)0),
					Neck = Utils.FindChild(val3, "NeckRotation", (IterativeSearchType)0),
					Eye = Utils.FindChild(val3, "Eye", (IterativeSearchType)0),
					Kind = ((Object)val3).name.Substring(((Object)val3).name.LastIndexOf('_') + 1),
					ScanTimer = Random.Range(0f, 0.5f)
				};
				if (!((Object)(object)cannon.Body == (Object)null) && !((Object)(object)cannon.Eye == (Object)null))
				{
					m_cannons.Add(cannon);
				}
			}
		}
		m_losMask = LayerMask.GetMask(new string[4] { "terrain", "static_solid", "Default", "piece" });
		m_friendlyMask = LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "vehicle" });
	}

	private bool Setup()
	{
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		if (m_ready)
		{
			return true;
		}
		if ((Object)(object)ZNetScene.instance == (Object)null)
		{
			return false;
		}
		GameObject prefab = ZNetScene.instance.GetPrefab("StaffClusterbomb");
		ItemDrop val = (Object.op_Implicit((Object)(object)prefab) ? prefab.GetComponent<ItemDrop>() : null);
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		m_staff = val.m_itemData;
		Attack attack = m_staff.m_shared.m_attack;
		m_projectilePrefab = ZNetScene.instance.GetPrefab("VVLEE_CannonShell");
		if ((Object)(object)m_projectilePrefab == (Object)null)
		{
			m_projectilePrefab = attack.m_attackProjectile;
		}
		if ((Object)(object)m_projectilePrefab == (Object)null)
		{
			return false;
		}
		m_projectileVel = Mathf.Max(attack.m_projectileVel, CorvettePlugin.ShellSpeed.Value);
		m_projectileAccuracy = attack.m_projectileAccuracy;
		Projectile component = m_projectilePrefab.GetComponent<Projectile>();
		m_projectileGravity = (Object.op_Implicit((Object)(object)component) ? component.m_gravity : 0f);
		GameObject prefab2 = ZNetScene.instance.GetPrefab("StaffLightning");
		ItemDrop val2 = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponent<ItemDrop>() : null);
		m_canisterPrefab = CorvettePlugin.CanisterPrefab;
		if ((Object)(object)val2 != (Object)null && (Object)(object)m_canisterPrefab != (Object)null)
		{
			m_canisterStaff = val2.m_itemData;
			Attack attack2 = m_canisterStaff.m_shared.m_attack;
			m_canisterVel = attack2.m_projectileVel;
			m_canisterSpread = attack2.m_projectileAccuracy;
			Projectile component2 = m_canisterPrefab.GetComponent<Projectile>();
			m_canisterGravity = (Object.op_Implicit((Object)(object)component2) ? component2.m_gravity : 0f);
		}
		else if (!s_canisterWarned)
		{
			s_canisterWarned = true;
			CorvettePlugin.Log.LogWarning((object)$"Canister shot unavailable (Dundr item={(Object)(object)val2 != (Object)null}, bolt prefab={(Object)(object)m_canisterPrefab != (Object)null}); cannons fire shells only.");
		}
		GameObject prefab3 = ZNetScene.instance.GetPrefab("piece_turret");
		Turret val3 = (Object.op_Implicit((Object)(object)prefab3) ? prefab3.GetComponent<Turret>() : null);
		m_shootEffect = (EffectList)(Object.op_Implicit((Object)(object)val3) ? ((object)val3.m_shootEffect) : ((object)new EffectList()));
		m_ready = true;
		return true;
	}

	private void Update()
	{
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !Setup())
		{
			return;
		}
		float deltaTime = Time.deltaTime;
		bool flag = (Object)(object)m_ship == (Object)null || IsShipCommanded();
		if ((Object)(object)m_cart != (Object)null)
		{
			flag = IsCartEmplaced();
		}
		bool flag2 = m_nview.IsOwner();
		foreach (Cannon cannon in m_cannons)
		{
			if (!flag)
			{
				cannon.Target = null;
				Rotate(cannon, 0f, 0f, deltaTime);
				continue;
			}
			cannon.ScanTimer -= deltaTime;
			if (cannon.ScanTimer <= 0f)
			{
				cannon.ScanTimer = 0.5f;
				cannon.Target = FindTarget(cannon);
			}
			cannon.Aimed = false;
			if ((Object)(object)cannon.Target != (Object)null && !cannon.Target.IsDead() && Solve(cannon, cannon.Target, out var yaw, out var pitch))
			{
				cannon.Aimed = Rotate(cannon, yaw, pitch, deltaTime);
			}
			else
			{
				cannon.Target = null;
				Rotate(cannon, 0f, 0f, deltaTime);
			}
			float num = (((Object)(object)m_ship != (Object)null) ? CorvettePlugin.ShipFireRange.Value : CorvettePlugin.FireRange.Value);
			if (flag2 && cannon.Aimed && Time.time >= cannon.ReadyTime && (m_wear == null || m_wear.CanFire()) && Vector3.Distance(((Component)cannon.Target).transform.position, cannon.Eye.position) <= num && !IsFriendlyInLineOfFire(cannon.Eye.position, cannon.Target.GetCenterPoint()))
			{
				if (UseCanister(cannon.Eye.position, cannon.Target))
				{
					FireCanister(cannon);
				}
				else
				{
					Fire(cannon);
				}
				m_wear?.AddShot();
			}
		}
	}

	private bool IsFriendlyInLineOfFire(Vector3 eye, Vector3 point)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = point - eye;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (magnitude < 0.1f)
		{
			return false;
		}
		int num = Physics.SphereCastNonAlloc(eye, 0.4f, val / magnitude, s_hits, magnitude, m_friendlyMask, (QueryTriggerInteraction)1);
		for (int i = 0; i < num; i++)
		{
			Collider collider = ((RaycastHit)(ref s_hits[i])).collider;
			if (!((Object)(object)collider == (Object)null) && !((Component)collider).transform.IsChildOf(((Component)this).transform))
			{
				if ((Object)(object)((Component)collider).GetComponentInParent<Ship>() != (Object)null || (Object)(object)((Component)collider).GetComponentInParent<Vagon>() != (Object)null)
				{
					return true;
				}
				Piece componentInParent = ((Component)collider).GetComponentInParent<Piece>();
				if ((Object)(object)componentInParent != (Object)null && componentInParent.IsPlacedByPlayer())
				{
					return true;
				}
			}
		}
		return false;
	}

	private bool IsShipCommanded()
	{
		if (!m_ship.HasPlayerOnboard())
		{
			return false;
		}
		if (!CorvettePlugin.RequireCrew.Value)
		{
			return true;
		}
		if (!IsSeatOccupied(m_helmSeat))
		{
			return IsSeatOccupied(m_captainSeat);
		}
		return true;
	}

	private static bool IsSmallFlyer(Character c)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		float value = CorvettePlugin.SmallFlyerSize.Value;
		if (value <= 0f || !c.IsFlying())
		{
			return false;
		}
		CapsuleCollider component = ((Component)c).GetComponent<CapsuleCollider>();
		if ((Object)(object)component == (Object)null)
		{
			return false;
		}
		float y = ((Component)c).transform.localScale.y;
		return Mathf.Max(component.height, component.radius * 2f) * y <= value;
	}

	private static bool IsSeatOccupied(Transform seat)
	{
		//IL_000a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)seat != (Object)null)
		{
			return (Object)(object)Player.GetClosestPlayer(seat.position, 0.6f) != (Object)null;
		}
		return false;
	}

	private bool IsCartEmplaced()
	{
		//IL_003f: 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 (m_cart.InUse())
		{
			return false;
		}
		if ((Object)(object)m_body != (Object)null)
		{
			Vector3 linearVelocity = m_body.linearVelocity;
			if (((Vector3)(ref linearVelocity)).sqrMagnitude > 0.09f)
			{
				return false;
			}
		}
		return Player.IsPlayerInRange(((Component)this).transform.position, CorvettePlugin.CartCrewRange.Value);
	}

	private bool UseCanister(Vector3 eye, Character target)
	{
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		float value = CorvettePlugin.CanisterRange.Value;
		if (value > 0f && m_canisterStaff != null)
		{
			return Vector3.Distance(((Component)target).transform.position, eye) <= value;
		}
		return false;
	}

	private Character FindTarget(Cannon cannon)
	{
		//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_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_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		float num = (((Object)(object)m_ship != (Object)null) ? CorvettePlugin.ShipRange.Value : CorvettePlugin.Range.Value);
		float value = CorvettePlugin.MinRange.Value;
		Player localPlayer = Player.m_localPlayer;
		Vector3 position = cannon.Eye.position;
		Character result = null;
		float num2 = float.MaxValue;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if ((Object)(object)allCharacter == (Object)null || allCharacter.IsDead() || allCharacter.IsPlayer() || allCharacter.IsTamed())
			{
				continue;
			}
			float num3 = Vector3.Distance(((Component)allCharacter).transform.position, position);
			if (!(num3 > num) && !(num3 >= num2) && (!(num3 < value) || UseCanister(position, allCharacter)) && (!((Object)(object)localPlayer != (Object)null) || BaseAI.IsEnemy((Character)(object)localPlayer, allCharacter)))
			{
				BaseAI baseAI = allCharacter.GetBaseAI();
				if ((CorvettePlugin.TargetPassiveAnimals.Value || !(baseAI is AnimalAI)) && !IsSmallFlyer(allCharacter) && Solve(cannon, allCharacter, out var _, out var _) && !Physics.Linecast(position, allCharacter.GetCenterPoint(), m_losMask) && !IsFriendlyInLineOfFire(position, allCharacter.GetCenterPoint()))
				{
					result = allCharacter;
					num2 = num3;
				}
			}
		}
		return result;
	}

	private bool Solve(Cannon cannon, Character target, out float yaw, out float pitch)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: 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_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: 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_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: 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_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		yaw = 0f;
		pitch = 0f;
		Vector3 position = cannon.Eye.position;
		Vector3 centerPoint = target.GetCenterPoint();
		bool flag = UseCanister(position, target);
		float num = (flag ? m_canisterVel : m_projectileVel);
		float num2 = Vector3.Distance(centerPoint, position) / num;
		Vector3 val = centerPoint + target.GetVelocity() * num2 - position;
		Vector3 val2 = default(Vector3);
		((Vector3)(ref val2))..ctor(val.x, 0f, val.z);
		float magnitude = ((Vector3)(ref val2)).magnitude;
		if (magnitude < 0.01f)
		{
			return false;
		}
		float num3 = (flag ? m_canisterGravity : m_projectileGravity);
		float num6;
		if (num3 > 0.01f)
		{
			float num4 = num * num;
			float num5 = num4 * num4 - num3 * (num3 * magnitude * magnitude + 2f * val.y * num4);
			if (num5 < 0f)
			{
				return false;
			}
			num6 = Mathf.Atan((num4 - Mathf.Sqrt(num5)) / (num3 * magnitude));
		}
		else
		{
			num6 = Mathf.Atan2(val.y, magnitude);
		}
		Vector3 val3 = val2 / magnitude * Mathf.Cos(num6) + Vector3.up * Mathf.Sin(num6);
		Vector3 val4 = cannon.Mount.InverseTransformDirection(val3);
		yaw = Mathf.Atan2(val4.x, val4.z) * 57.29578f;
		pitch = (0f - Mathf.Asin(Mathf.Clamp(val4.y, -1f, 1f))) * 57.29578f;
		float num7 = ((cannon.Kind == "chaser") ? CorvettePlugin.ChaserArc.Value : ((cannon.Kind == "field") ? CorvettePlugin.FieldArc.Value : CorvettePlugin.BroadsideArc.Value));
		if (Mathf.Abs(yaw) <= num7 && pitch >= -40f)
		{
			return pitch <= 25f;
		}
		return false;
	}

	private static bool Rotate(Cannon cannon, float yaw, float pitch, float dt)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: 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_0026: 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_0073: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		Quaternion val = Quaternion.Euler(pitch, yaw, 0f);
		cannon.Body.localRotation = Quaternion.RotateTowards(cannon.Body.localRotation, val, 90f * dt);
		if ((Object)(object)cannon.Neck != (Object)null)
		{
			cannon.Neck.localRotation = Quaternion.Euler(0f, cannon.Body.localEulerAngles.y, 0f);
		}
		return Quaternion.Angle(cannon.Body.localRotation, val) <= 3f;
	}

	private void FireCanister(Cannon cannon)
	{
		//IL_0078: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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_0166: Unknown result type (might be due to invalid IL or missing references)
		//IL_016b: 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)
		//IL_0175: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0231: Unknown result type (might be due to invalid IL or missing references)
		//IL_0236: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0258: Unknown result type (might be due to invalid IL or missing references)
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0285: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
		cannon.ReadyTime = Time.time + CorvettePlugin.CanisterCooldown.Value + Random.Range(0f, 0.8f);
		int value = CorvettePlugin.CanisterBurstSize.Value;
		if (value > 0 && ++cannon.CanisterVolleys >= value)
		{
			cannon.CanisterVolleys = 0;
			cannon.ReadyTime += CorvettePlugin.CanisterBurstCooldown.Value;
		}
		Transform eye = cannon.Eye;
		m_shootEffect.Create(eye.position, eye.rotation, (Transform)null, 1f, -1, default(ZDOID));
		Player val = Player.m_localPlayer;
		if ((Object)(object)val != (Object)null && (Object)(object)m_ship != (Object)null && !m_ship.IsPlayerInBoat(val))
		{
			val = null;
		}
		SharedData shared = m_canisterStaff.m_shared;
		DamageTypes damage = default(DamageTypes);
		((DamageTypes)(ref damage)).Add(m_canisterStaff.GetDamage(shared.m_maxQuality, (float)Game.m_worldLevel), 1);
		((DamageTypes)(ref damage)).Modify((shared.m_attack.m_damageMultiplier > 0f) ? shared.m_attack.m_damageMultiplier : 1f);
		((DamageTypes)(ref damage)).Modify(CorvettePlugin.DamageMultiplier.Value);
		damage.m_pierce += ((DamageTypes)(ref damage)).GetTotalDamage() * CorvettePlugin.CanisterPierce.Value / 100f;
		int value2 = CorvettePlugin.CanisterPellets.Value;
		Vector3 val2 = Vector3.Cross(eye.forward, Vector3.up);
		for (int i = 0; i < value2; i++)
		{
			Vector3 val3 = Quaternion.AngleAxis(Random.Range(0f - m_canisterSpread, m_canisterSpread), val2) * eye.forward;
			val3 = Quaternion.AngleAxis(Random.Range(0f - m_canisterSpread, m_canisterSpread), Vector3.up) * val3;
			HitData val4 = new HitData();
			val4.m_damage = damage;
			val4.m_toolTier = (short)shared.m_toolTier;
			val4.m_pushForce = shared.m_attackForce;
			val4.m_backstabBonus = shared.m_backstabBonus;
			val4.m_staggerMultiplier = shared.m_attack.m_staggerMultiplier;
			val4.m_blockable = shared.m_blockable;
			val4.m_dodgeable = shared.m_dodgeable;
			val4.m_skill = shared.m_skillType;
			val4.m_itemWorldLevel = (byte)Game.m_worldLevel;
			val4.m_hitType = (HitType)16;
			GameObject obj = Object.Instantiate<GameObject>(m_canisterPrefab, eye.position, Quaternion.LookRotation(val3));
			CorvetteShell corvetteShell = obj.AddComponent<CorvetteShell>();
			corvetteShell.Ship = ((Component)this).transform;
			corvetteShell.Gunner = (Character)(object)val;
			corvetteShell.Skill = val4.m_skill;
			corvetteShell.Canister = true;
			IProjectile component = obj.GetComponent<IProjectile>();
			if (component != null)
			{
				component.Setup((Character)(object)val, val3 * m_canisterVel, (i == 0) ? 40f : 0f, val4, m_canisterStaff, (ItemData)null);
			}
		}
	}

	private void Fire(Cannon cannon)
	{
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: 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_00cd: 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_00dd: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0126: Expected O, but got Unknown
		//IL_01bd: 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_0246: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_029c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f7: Unknown result type (might be due to invalid IL or missing references)
		cannon.CanisterVolleys = 0;
		cannon.ReadyTime = Time.time + CorvettePlugin.Cooldown.Value + Random.Range(0f, 0.8f);
		int value = CorvettePlugin.BurstSize.Value;
		if (value > 0 && ++cannon.ShotsInBurst >= value)
		{
			cannon.ShotsInBurst = 0;
			cannon.ReadyTime += CorvettePlugin.BurstCooldown.Value;
		}
		Transform eye = cannon.Eye;
		m_shootEffect.Create(eye.position, eye.rotation, (Transform)null, 1f, -1, default(ZDOID));
		Vector3 forward = eye.forward;
		Vector3 val = Vector3.Cross(forward, Vector3.up);
		float projectileAccuracy = m_projectileAccuracy;
		forward = Quaternion.AngleAxis(Random.Range(0f - projectileAccuracy, projectileAccuracy), val) * forward;
		forward = Quaternion.AngleAxis(Random.Range(0f - projectileAccuracy, projectileAccuracy), Vector3.up) * forward;
		Player val2 = Player.m_localPlayer;
		if ((Object)(object)val2 != (Object)null && (Object)(object)m_ship != (Object)null && !m_ship.IsPlayerInBoat(val2))
		{
			val2 = null;
		}
		HitData val3 = new HitData();
		val3.m_toolTier = (short)m_staff.m_shared.m_toolTier;
		val3.m_pushForce = m_staff.m_shared.m_attackForce;
		val3.m_backstabBonus = m_staff.m_shared.m_backstabBonus;
		val3.m_staggerMultiplier = m_staff.m_shared.m_attack.m_staggerMultiplier;
		Attack attack = m_staff.m_shared.m_attack;
		((DamageTypes)(ref val3.m_damage)).Add(m_staff.GetDamage(m_staff.m_shared.m_maxQuality, (float)Game.m_worldLevel), 1);
		((DamageTypes)(ref val3.m_damage)).Modify((attack.m_damageMultiplier > 0f) ? attack.m_damageMultiplier : 1f);
		((DamageTypes)(ref val3.m_damage)).Modify(CorvettePlugin.DamageMultiplier.Value);
		val3.m_blockable = m_staff.m_shared.m_blockable;
		val3.m_dodgeable = m_staff.m_shared.m_dodgeable;
		val3.m_skill = m_staff.m_shared.m_skillType;
		val3.m_itemWorldLevel = (byte)Game.m_worldLevel;
		val3.m_hitType = (HitType)16;
		if ((Object)(object)m_staff.m_shared.m_attackStatusEffect != (Object)null)
		{
			val3.m_statusEffectHash = m_staff.m_shared.m_attackStatusEffect.NameHash();
		}
		GameObject obj = Object.Instantiate<GameObject>(m_projectilePrefab, eye.position, Quaternion.LookRotation(forward));
		CorvetteShell corvetteShell = obj.AddComponent<CorvetteShell>();
		corvetteShell.Ship = ((Component)this).transform;
		corvetteShell.Gunner = (Character)(object)val2;
		corvetteShell.BaseDamage = ((DamageTypes)(ref val3.m_damage)).GetTotalDamage();
		corvetteShell.Skill = val3.m_skill;
		IProjectile component = obj.GetComponent<IProjectile>();
		if (component != null)
		{
			component.Setup((Character)(object)val2, forward * m_projectileVel, 40f, val3, m_staff, (ItemData)null);
		}
	}
}
public class CorvetteShell : MonoBehaviour
{
	public Transform Ship;

	public Character Gunner;

	public float BaseDamage;

	public SkillType Skill;

	public bool BonusApplied;

	public bool Canister;
}
[HarmonyPatch(typeof(Projectile), "OnHit")]
public static class ProjectileOnHitPatch
{
	private static bool Prefix(Projectile __instance, Collider collider)
	{
		if ((Object)(object)collider == (Object)null)
		{
			return true;
		}
		CorvetteShell component = ((Component)__instance).GetComponent<CorvetteShell>();
		if ((Object)(object)component == (Object)null || (Object)(object)component.Ship == (Object)null)
		{
			return true;
		}
		if (((Component)collider).transform.IsChildOf(component.Ship))
		{
			return false;
		}
		ApplyDirectHit(__instance, component, collider);
		return true;
	}

	private static void ApplyDirectHit(Projectile projectile, CorvetteShell shell, Collider collider)
	{
		//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_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Expected O, but got Unknown
		//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0105: 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_0136: Unknown result type (might be due to invalid IL or missing references)
		if (shell.BonusApplied)
		{
			return;
		}
		GameObject val = Projectile.FindHitObject(collider);
		Character val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Character>() : null);
		if ((Object)(object)val2 == (Object)null || val2.IsDead() || FriendlyFire.IsProtected(val, shell.Gunner))
		{
			return;
		}
		shell.BonusApplied = true;
		Vector3 forward = ((Component)projectile).transform.forward;
		if (shell.Canister)
		{
			val2.Stagger(forward);
			return;
		}
		HitData val3 = new HitData();
		val3.m_damage.m_blunt = shell.BaseDamage * CorvettePlugin.DirectHitBlunt.Value / 100f;
		val3.m_damage.m_pierce = shell.BaseDamage * CorvettePlugin.DirectHitPierce.Value / 100f;
		val3.m_pushForce = CorvettePlugin.DirectHitKnockback.Value;
		val3.m_staggerMultiplier = 2f;
		val3.m_point = collider.ClosestPoint(((Component)projectile).transform.position);
		val3.m_dir = forward;
		val3.m_hitCollider = collider;
		val3.m_ranged = true;
		val3.m_skill = shell.Skill;
		val3.m_hitType = (HitType)16;
		val3.m_itemWorldLevel = (byte)Game.m_worldLevel;
		val3.SetAttacker(shell.Gunner);
		val2.Damage(val3);
		if (CorvettePlugin.DirectHitStagger.Value)
		{
			val2.Stagger(forward);
		}
	}
}
public class CorvetteHull : MonoBehaviour
{
	public Vector3 CenterOfMass;

	public float BaseWaterLevelOffset;

	private void Awake()
	{
		//IL_0012: 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_006a: 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)
		Rigidbody component = ((Component)this).GetComponent<Rigidbody>();
		if ((Object)(object)component != (Object)null)
		{
			component.centerOfMass = CenterOfMass;
		}
		Ship component2 = ((Component)this).GetComponent<Ship>();
		if (!((Object)(object)component2 == (Object)null))
		{
			component2.m_waterLevelOffset = BaseWaterLevelOffset - CorvettePlugin.WaterlineOffset.Value;
			if ((Object)(object)component2.m_floatCollider != (Object)null)
			{
				Transform transform = ((Component)component2.m_floatCollider).transform;
				Vector3 localPosition = transform.localPosition;
				transform.localPosition = new Vector3(localPosition.x, localPosition.y, CorvettePlugin.BowTrim.Value);
			}
		}
	}
}
public class CorvetteDredge : MonoBehaviour
{
	private const float Interval = 0.25f;

	private const int MaxOpsPerTick = 8;

	private const float KeelY = -1.6f;

	private const float BilgeY = -0.7f;

	private const float Clearance = 1f;

	private const float DigDelta = 0.5f;

	private static readonly string[] DigOps = new string[3] { "digg_v3", "digg_v2", "digg" };

	private Ship m_ship;

	private ZNetView m_nview;

	private GameObject m_digPrefab;

	private float m_timer;

	private float m_logTimer;

	private int m_next;

	private int m_dug;

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

	private void Awake()
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: 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_00b1: 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)
		m_ship = ((Component)this).GetComponent<Ship>();
		m_nview = ((Component)this).GetComponent<ZNetView>();
		for (float num = -15f; num <= 14.01f; num += 2f)
		{
			float num2 = Mathf.Clamp01(Mathf.Abs(num) / 13f);
			float num3 = Mathf.Lerp(4.4f, 1f, num2 * num2);
			m_points.Add(new Vector3(0f, -1.6f, num));
			m_points.Add(new Vector3(num3 * 0.55f, -1.6f, num));
			m_points.Add(new Vector3((0f - num3) * 0.55f, -1.6f, num));
			m_points.Add(new Vector3(num3 + 0.6f, -0.7f, num));
			m_points.Add(new Vector3(0f - num3 - 0.6f, -0.7f, num));
		}
	}

	private void Update()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Invalid comparison between Unknown and I4
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		if (!CorvettePlugin.ReverseDredge.Value || (Object)(object)m_ship == (Object)null || (Object)(object)m_nview == (Object)null || !m_nview.IsValid() || !m_nview.IsOwner() || (int)m_ship.GetSpeedSetting() != 1)
		{
			return;
		}
		m_timer -= Time.deltaTime;
		m_logTimer -= Time.deltaTime;
		if (m_timer > 0f)
		{
			return;
		}
		m_timer = 0.25f;
		if ((Object)(object)m_digPrefab == (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
		{
			string[] digOps = DigOps;
			foreach (string text in digOps)
			{
				GameObject prefab = ZNetScene.instance.GetPrefab(text);
				if ((Object)(object)prefab != (Object)null && (Object)(object)prefab.GetComponent<TerrainOp>() != (Object)null)
				{
					m_digPrefab = prefab;
					break;
				}
			}
		}
		if ((Object)(object)m_digPrefab == (Object)null || (Object)(object)ZoneSystem.instance == (Object)null)
		{
			return;
		}
		int num = 0;
		float num2 = default(float);
		for (int j = 0; j < m_points.Count; j++)
		{
			if (num >= 8)
			{
				break;
			}
			Vector3 val = ((Component)this).transform.TransformPoint(m_points[m_next]);
			m_next = (m_next + 1) % m_points.Count;
			if (ZoneSystem.instance.GetGroundHeight(val, ref num2))
			{
				float num3 = val.y - 1f;
				if (!(num2 <= num3))
				{
					Object.Instantiate<GameObject>(m_digPrefab, new Vector3(val.x, num3 + 0.5f, val.z), Quaternion.identity);
					num++;
				}
			}
		}
		m_dug += num;
		if (m_dug > 0 && m_logTimer <= 0f)
		{
			m_logTimer = 5f;
			CorvettePlugin.Log.LogInfo((object)$"Reverse dredge: {m_dug} dig operations under the hull.");
			m_dug = 0;
		}
	}
}
[HarmonyPatch(typeof(Ship), "GetWindAngleFactor")]
public static class CorvetteDownwindBoost
{
	private static void Postfix(Ship __instance, ref float __result)
	{
		//IL_0078: 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)
		if ((Object)(object)EnvMan.instance == (Object)null || (Object)(object)((Component)__instance).GetComponent<CorvetteHull>() == (Object)null)
		{
			return;
		}
		Airship component = ((Component)__instance).GetComponent<Airship>();
		float num = (((Object)(object)component != (Object)null) ? CorvettePlugin.AirshipDownwindSpeed.Value : CorvettePlugin.DownwindSpeed.Value);
		if ((Object)(object)component != (Object)null && component.Crippled)
		{
			float value = CorvettePlugin.AirshipCrippledSpeed.Value;
			__result *= value * value;
		}
		if (!(num <= 1f))
		{
			float num2 = Vector3.Dot(EnvMan.instance.GetWindDir(), ((Component)__instance).transform.forward);
			if (!(num2 <= 0f))
			{
				float num3 = num2 * num2 * (3f - 2f * num2);
				__result *= Mathf.Lerp(1f, num * num, num3);
			}
		}
	}
}
public class CorvetteRig : MonoBehaviour
{
	public const float FurledScale = 0.07f;

	private const float HalfScale = 0.55f;

	private Ship m_ship;

	private Transform[] m_pivots = (Transform[])(object)new Transform[0];

	private Transform[] m_sails = (Transform[])(object)new Transform[0];

	private float m_set = 0.07f;

	private void Awake()
	{
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		m_ship = ((Component)this).GetComponent<Ship>();
		Transform val = ((Component)this).transform.Find("corvette");
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		List<Transform> list = new List<Transform>();
		List<Transform> list2 = new List<Transform>();
		foreach (Transform item in val)
		{
			Transform val2 = item;
			if (!(((Object)val2).name != "YardPivot"))
			{
				list.Add(val2);
				Transform val3 = val2.Find("SailFull/sail");
				if ((Object)(object)val3 != (Object)null)
				{
					list2.Add(val3);
				}
			}
		}
		m_pivots = list.ToArray();
		m_sails = list2.ToArray();
	}

	private void Update()
	{
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Invalid comparison between Unknown and I4
		//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_004e: 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_0058: 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_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c9: Invalid comparison between Unknown and I4
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_0136: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_ship == (Object)null || m_pivots.Length == 0)
		{
			return;
		}
		if ((Object)(object)m_ship.m_mastObject != (Object)null)
		{
			Quaternion val = Quaternion.Inverse(((Component)this).transform.rotation) * m_ship.m_mastObject.transform.rotation;
			Quaternion val2 = Quaternion.Euler(0f, ((Quaternion)(ref val)).eulerAngles.y, 0f);
			Transform[] pivots = m_pivots;
			foreach (Transform obj in pivots)
			{
				obj.localRotation = Quaternion.RotateTowards(obj.localRotation, val2, 40f * Time.deltaTime);
			}
		}
		float num = 0.07f;
		Speed speedSetting = m_ship.GetSpeedSetting();
		if ((int)speedSetting != 3)
		{
			if ((int)speedSetting == 4)
			{
				num = 1f;
			}
		}
		else
		{
			num = 0.55f;
		}
		if (!Mathf.Approximately(m_set, num))
		{
			m_set = Mathf.MoveTowards(m_set, num, 0.5f * Time.deltaTime);
			Vector3 localScale = default(Vector3);
			((Vector3)(ref localScale))..ctor(1f, m_set, Mathf.Max(0.07f, m_set));
			Transform[] pivots = m_sails;
			for (int i = 0; i < pivots.Length; i++)
			{
				pivots[i].localScale = localScale;
			}
		}
	}
}
[BepInPlugin("com.vvlee.corvette", "Corvette", "0.4.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
public class CorvettePlugin : BaseUnityPlugin
{
	public const string ModGuid = "com.vvlee.corvette";

	public const string ModName = "Corvette";

	public const string ModVersion = "0.4.2";

	public const string ShipPrefabName = "VVLEE_Corvette";

	public const string ZeppelinPrefabName = "VVLEE_AirshipZeppelin";

	public const string VtolPrefabName = "VVLEE_AirshipVtol";

	internal static ManualLogSource Log;

	internal static GameObject CanisterPrefab;

	public const string CannonPrefabName = "VVLEE_Cannon";

	public const string CannonCartPrefabName = "VVLEE_CannonCart";

	public const string ShellPrefabName = "VVLEE_CannonShell";

	public const string BaseShipPrefab = "VikingShip_Ashlands";

	public const string TurretPrefab = "piece_turret";

	public const string CartPrefab = "Cart";

	public const string StaffPrefab = "StaffClusterbomb";

	public const string CanisterPrefabName = "VVLEE_CanisterShot";

	public const string CanisterStaffPrefab = "StaffLightning";

	public const string LanternPrefab = "piece_dvergr_lantern";

	public const string HoodedLanternPrefab = "piece_hoodedlantern";

	public const string ThronePrefab = "piece_moose_throne";

	public const string SmelterPrefab = "smelter";

	public const string BoilerFuelPrefab = "Coal";

	public const string CaptainSeatName = "CaptainSeat";

	public const string CannonPrefix = "CorvetteCannon_";

	public static ConfigEntry<float> Cooldown;

	public static ConfigEntry<int> BurstSize;

	public static ConfigEntry<float> BurstCooldown;

	public static ConfigEntry<float> Range;

	public static ConfigEntry<float> ShipRange;

	public static ConfigEntry<float> MinRange;

	public static ConfigEntry<float> DamageMultiplier;

	public static ConfigEntry<float> DirectHitBlunt;

	public static ConfigEntry<float> DirectHitPierce;

	public static ConfigEntry<float> DirectHitKnockback;

	public static ConfigEntry<bool> DirectHitStagger;

	public static ConfigEntry<float> TreeDamage;

	public static ConfigEntry<float> FireRange;

	public static ConfigEntry<float> ShipFireRange;

	public static ConfigEntry<float> CanisterRange;

	public static ConfigEntry<int> CanisterPellets;

	public static ConfigEntry<float> CanisterPierce;

	public static ConfigEntry<float> CanisterCooldown;

	public static ConfigEntry<int> CanisterBurstSize;

	public static ConfigEntry<float> CanisterBurstCooldown;

	public static ConfigEntry<float> ShellSpeed;

	public static ConfigEntry<float> BroadsideArc;

	public static ConfigEntry<float> ChaserArc;

	public static ConfigEntry<float> FieldArc;

	public static ConfigEntry<bool> RequireCrew;

	public static ConfigEntry<float> CartCrewRange;

	public static ConfigEntry<bool> TargetPassiveAnimals;

	public static ConfigEntry<float> SmallFlyerSize;

	public static ConfigEntry<float> WaterlineOffset;

	public static ConfigEntry<float> BowTrim;

	public static ConfigEntry<float> DownwindSpeed;

	public static ConfigEntry<bool> ReverseDredge;

	public static ConfigEntry<float> AirshipMaxAltitude;

	public static ConfigEntry<float> AirshipWarnAltitude;

	public static ConfigEntry<float> AirshipWearAltitude;

	public static ConfigEntry<float> AirshipWearPerSecond;

	public static ConfigEntry<float> AirshipNoClimbHealth;

	public static ConfigEntry<float> AirshipCrippledHealth;

	public static ConfigEntry<float> AirshipEmergencyAltitude;

	public static ConfigEntry<float> AirshipCrippledSpeed;

	public static ConfigEntry<float> AirshipClimbRate;

	public static ConfigEntry<float> AirshipDownwindSpeed;

	public static ConfigEntry<bool> AirshipRequireFuel;

	public static ConfigEntry<int> AirshipFuelCapacity;

	public static ConfigEntry<float> AirshipSecondsPerCoal;

	public static ConfigEntry<bool> FriendlyFireProtection;

	public static ConfigEntry<float> EarthStaffEitr;

	public static ConfigEntry<bool> BallistaAutoReload;

	public static ConfigEntry<float> BallistaReloadRange;

	public static ConfigEntry<int> MaxShots;

	public static ConfigEntry<int> ShipFreeShots;

	public static ConfigEntry<float> ShipWearPerShot;

	public static ConfigEntry<float> ShipCeaseFireHealth;

	private const float ShipCenterOfMassY = 0.9f;

	private const float FieldCannonScale = 1.25f;

	private const float CartCannonScale = 0.9f;

	private int m_vehicleLayer;

	private float m_axisHeight = 0.62f;

	private void Awake()
	{
		//IL_000b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		//IL_0018: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Expected O, but got Unknown
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d2: Expected O, but got Unknown
		//IL_010a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Expected O, but got Unknown
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0156: Expected O, but got Unknown
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Expected O, but got Unknown
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Expected O, but got Unknown
		//IL_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: Expected O, but got Unknown
		//IL_0296: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Expected O, but got Unknown
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e2: Expected O, but got Unknown
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Expected O, but got Unknown
		//IL_034a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0354: Expected O, but got Unknown
		//IL_038c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0396: Expected O, but got Unknown
		//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d1: Expected O, but got Unknown
		//IL_0409: Unknown result type (might be due to invalid IL or missing references)
		//IL_0413: Expected O, but got Unknown
		//IL_044b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0455: Expected O, but got Unknown
		//IL_0482: Unknown result type (might be due to invalid IL or missing references)
		//IL_048c: Expected O, but got Unknown
		//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ce: Expected O, but got Unknown
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_0510: Expected O, but got Unknown
		//IL_0548: Unknown result type (might be due to invalid IL or missing references)
		//IL_0552: Expected O, but got Unknown
		//IL_058a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0594: Expected O, but got Unknown
		//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d6: Expected O, but got Unknown
		//IL_060e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0618: Expected O, but got Unknown
		//IL_063e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0648: Expected O, but got Unknown
		//IL_0680: Unknown result type (might be due to invalid IL or missing references)
		//IL_068a: Expected O, but got Unknown
		//IL_06b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ba: Expected O, but got Unknown
		//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fc: Expected O, but got Unknown
		//IL_0734: Unknown result type (might be due to invalid IL or missing references)
		//IL_073e: Expected O, but got Unknown
		//IL_0776: Unknown result type (might be due to invalid IL or missing references)
		//IL_0780: Expected O, but got Unknown
		//IL_07b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c2: Expected O, but got Unknown
		//IL_07e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f2: Expected O, but got Unknown
		//IL_082a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0834: Expected O, but got Unknown
		//IL_086c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0876: Expected O, but got Unknown
		//IL_08ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_08b8: Expected O, but got Unknown
		//IL_08f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_08fa: Expected O, but got Unknown
		//IL_0932: Unknown result type (might be due to invalid IL or missing references)
		//IL_093c: Expected O, but got Unknown
		//IL_0974: Unknown result type (might be due to invalid IL or missing references)
		//IL_097e: Expected O, but got Unknown
		//IL_09b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_09c0: Expected O, but got Unknown
		//IL_09f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a02: Expected O, but got Unknown
		//IL_0a3a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a44: Expected O, but got Unknown
		//IL_0a7c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a86: Expected O, but got Unknown
		//IL_0aac: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab6: Expected O, but got Unknown
		//IL_0ae7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0af1: Expected O, but got Unknown
		//IL_0b29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b33: Expected O, but got Unknown
		//IL_0b67: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b71: Expected O, but got Unknown
		//IL_0ba5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0baf: Expected O, but got Unknown
		//IL_0be7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bf1: Expected O, but got Unknown
		//IL_0c29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c33: Expected O, but got Unknown
		//IL_0c59: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c63: Expected O, but got Unknown
		//IL_0c9b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ca5: Expected O, but got Unknown
		//IL_0cdd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ce7: Expected O, but got Unknown
		//IL_0d0d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0d17: Expected O, but got Unknown
		//IL_0d21: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
		{
			IsAdminOnly = true
		};
		Cooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "Cooldown", 5f, new ConfigDescription("Seconds between shots for each cannon.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 60f), new object[1] { val }));
		BurstSize = ((BaseUnityPlugin)this).Config.Bind<int>("Cannons", "BurstSize", 10, new ConfigDescription("Each cannon takes an extra pause after this many shots. 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000), new object[1] { val }));
		BurstCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "BurstCooldown", 5f, new ConfigDescription("Extra seconds a cannon waits after every BurstSize shots, on top of its normal cooldown.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), new object[1] { val }));
		Range = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "MaxRange", 150f, new ConfigDescription("Maximum targeting range in meters of the placed Cannon and the Cannon cart. Creatures outside the loaded area cannot be targeted.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), new object[1] { val }));
		ShipRange = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "ShipMaxRange", 100f, new ConfigDescription("Maximum targeting range in meters of the Corvette's guns.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), new object[1] { val }));
		FireRange = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "FireRange", 140f, new ConfigDescription("The placed Cannon and the Cannon cart track a target out to MaxRange but only open fire once it is within this distance (m).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), new object[1] { val }));
		ShipFireRange = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "ShipFireRange", 100f, new ConfigDescription("The Corvette's and airships' guns track a target out to ShipMaxRange but only open fire once it is within this distance (m).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), new object[1] { val }));
		MinRange = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "MinRange", 6f, new ConfigDescription("Cannons will not fire at targets closer than this (keeps the blast away from the gun).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 20f), new object[1] { val }));
		DamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "DamageMultiplier", 1f, new ConfigDescription("Multiplier applied on top of the Staff of Fracturing damage at maximum quality and maximum skill.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), new object[1] { val }));
		DirectHitBlunt = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "DirectHitBlunt", 50f, new ConfigDescription("Extra blunt damage on a direct hit, in percent of the shell's total damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), new object[1] { val }));
		DirectHitPierce = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "DirectHitPierce", 30f, new ConfigDescription("Extra pierce damage on a direct hit, in percent of the shell's total damage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 500f), new object[1] { val }));
		DirectHitKnockback = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "DirectHitKnockback", 150f, new ConfigDescription("Knockback force of a direct hit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), new object[1] { val }));
		DirectHitStagger = ((BaseUnityPlugin)this).Config.Bind<bool>("Cannons", "DirectHitStagger", true, new ConfigDescription("A direct hit staggers the creature.", (AcceptableValueBase)null, new object[1] { val }));
		CanisterRange = ((BaseUnityPlugin)this).Config.Bind<float>("Canister", "CanisterRange", 30f, new ConfigDescription("Hostiles within this distance (m) of a gun are engaged with canister shot (Dundr bolts) instead of a shell. 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), new object[1] { val }));
		CanisterPellets = ((BaseUnityPlugin)this).Config.Bind<int>("Canister", "CanisterPellets", 60, new ConfigDescription("Bolts per canister volley.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 300), new object[1] { val }));
		CanisterPierce = ((BaseUnityPlugin)this).Config.Bind<float>("Canister", "CanisterPierce", 200f, new ConfigDescription("Pierce damage added to every bolt, in percent of the bolt's damage (a fully upgraded Dundr).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), new object[1] { val }));
		CanisterCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Canister", "CanisterCooldown", 5f, new ConfigDescription("Seconds between canister volleys for each cannon.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 60f), new object[1] { val }));
		CanisterBurstSize = ((BaseUnityPlugin)this).Config.Bind<int>("Canister", "CanisterBurstSize", 3, new ConfigDescription("A cannon takes an extra pause after this many canister volleys in a row. 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100), new object[1] { val }));
		CanisterBurstCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("Canister", "CanisterBurstCooldown", 5f, new ConfigDescription("Extra seconds a cannon waits after CanisterBurstSize canister volleys in a row.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), new object[1] { val }));
		TreeDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "TreeDamage", 100f, new ConfigDescription("Cannon fire fells trees: a hit on a tree, log, stump or bush also deals this percentage of its damage as chop damage. 0 = cannons cannot harm trees (vanilla damage types).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1000f), new object[1] { val }));
		ShellSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "ShellSpeed", 70f, new ConfigDescription("Muzzle velocity of cannon shells in m/s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 150f), new object[1] { val }));
		BroadsideArc = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "BroadsideArc", 35f, new ConfigDescription("Horizontal traverse (degrees to each side) of the Corvette's broadside guns.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 90f), new object[1] { val }));
		ChaserArc = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "ChaserArc", 35f, new ConfigDescription("Horizontal traverse (degrees to each side) of the Corvette's bow and stern chasers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 90f), new object[1] { val }));
		FieldArc = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "FieldArc", 60f, new ConfigDescription("Horizontal traverse (degrees to each side) of the placed cannon and the cannon cart.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 180f), new object[1] { val }));
		RequireCrew = ((BaseUnityPlugin)this).Config.Bind<bool>("Cannons", "RequireCrew", true, new ConfigDescription("Ship guns only operate while someone is at the helm or sitting in the captain's seat. If disabled, they fire whenever any player is aboard.", (AcceptableValueBase)null, new object[1] { val }));
		CartCrewRange = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "CartCrewRange", 5f, new ConfigDescription("The cannon cart only fires while it is parked (nobody pulling it, not moving) and a player is within this many meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[1] { val }));
		TargetPassiveAnimals = ((BaseUnityPlugin)this).Config.Bind<bool>("Cannons", "TargetPassiveAnimals", false, new ConfigDescription("Also fire at passive animals (deer, hares...).", (AcceptableValueBase)null, new object[1] { val }));
		SmallFlyerSize = ((BaseUnityPlugin)this).Config.Bind<float>("Cannons", "IgnoreFlyersSmallerThan", 1.2f, new ConfigDescription("Cannons ignore flying creatures whose body is no larger than this (m), such as Deathsquitos and bats. 0 = attack all flyers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), new object[1] { val }));
		WaterlineOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Ship", "WaterlineOffset", 0f, new ConfigDescription("Raises (+) or lowers (-) how high the Corvette floats, in meters. Applies to newly loaded ships.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-2f, 2f), new object[1] { val }));
		BowTrim = ((BaseUnityPlugin)this).Config.Bind<float>("Ship", "BowTrim", 1.5f, new ConfigDescription("Fore-and-aft trim of the Corvette. Positive values lift the bow, negative values lower it. Applies to newly loaded ships.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), new object[1] { val }));
		DownwindSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Ship", "DownwindSpeed", 2f, new ConfigDescription("Sailing speed of the Corvette with the wind dead astern, as a multiple of the Drakkar's. Fades out toward a beam wind; upwind speed is unchanged. 1 = same as the Drakkar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[1] { val }));
		ReverseDredge = ((BaseUnityPlugin)this).Config.Bind<bool>("Ship", "ReverseDredge", true, new ConfigDescription("While the Corvette is in reverse, terrain touching the keel is dug away so the ship can back off a shoal.", (AcceptableValueBase)null, new object[1] { val }));
		AirshipMaxAltitude = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "MaxAltitude", 800f, new ConfigDescription("Highest altitude (m above sea level) an airship can climb to.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(50f, 1500f), new object[1] { val }));
		AirshipWarnAltitude = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "WarnAltitude", 500f, new ConfigDescription("Above this altitude (m) the crew gets a warning.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1500f), new object[1] { val }));
		AirshipWearAltitude = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "WearAltitude", 600f, new ConfigDescription("Above this altitude (m) the airship slowly loses durability.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1500f), new object[1] { val }));
		AirshipWearPerSecond = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "WearPerSecond", 0.2f, new ConfigDescription("Durability lost per second above WearAltitude, in percent of maximum.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[1] { val }));
		AirshipNoClimbHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "NoClimbHealth", 50f, new ConfigDescription("Below this durability (percent) an airship cannot climb.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { val }));
		AirshipCrippledHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "CrippledHealth", 30f, new ConfigDescription("Below this durability (percent) an airship sinks slowly to EmergencyAltitude and moves at CrippledSpeed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { val }));
		AirshipEmergencyAltitude = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "EmergencyAltitude", 100f, new ConfigDescription("Altitude (m) a crippled airship sinks to.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1500f), new object[1] { val }));
		AirshipCrippledSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "CrippledSpeed", 0.5f, new ConfigDescription("Speed of a crippled airship as a fraction of normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), new object[1] { val }));
		AirshipClimbRate = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "ClimbRate", 4f, new ConfigDescription("Climb and descent rate in m/s.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), new object[1] { val }));
		AirshipDownwindSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "DownwindSpeed", 1.5f, new ConfigDescription("Airship speed with the wind dead astern, as a multiple of the Drakkar's. Upwind speed is unchanged.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), new object[1] { val }));
		AirshipRequireFuel = ((BaseUnityPlugin)this).Config.Bind<bool>("Airship", "RequireFuel", true, new ConfigDescription("Airships need coal in the boiler to climb and to stay up. Without fuel they sink slowly.", (AcceptableValueBase)null, new object[1] { val }));
		AirshipFuelCapacity = ((BaseUnityPlugin)this).Config.Bind<int>("Airship", "FuelCapacity", 50, new ConfigDescription("Coal the boiler holds.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 500), new object[1] { val }));
		AirshipSecondsPerCoal = ((BaseUnityPlugin)this).Config.Bind<float>("Airship", "SecondsPerCoal", 60f, new ConfigDescription("Seconds of flight one coal lasts. Fuel only burns while the airship is off the water.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 3600f), new object[1] { val }));
		MaxShots = ((BaseUnityPlugin)this).Config.Bind<int>("Durability", "CannonMaxShots", 10000, new ConfigDescription("Shots a placed Cannon can fire before it must be repaired with the hammer. 0 = unlimited.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 100000), new object[1] { val }));
		ShipFreeShots = ((BaseUnityPlugin)this).Config.Bind<int>("Durability", "ShipFreeShots", 10000, new ConfigDescription("Total shots a Corvette can fire before further shots start wearing down the hull. 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1000000), new object[1] { val }));
		ShipWearPerShot = ((BaseUnityPlugin)this).Config.Bind<float>("Durability", "ShipWearPerShot", 0.1f, new ConfigDescription("Hull health lost per shot once ShipFreeShots is exceeded, in percent of maximum hull health.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), new object[1] { val }));
		ShipCeaseFireHealth = ((BaseUnityPlugin)this).Config.Bind<float>("Durability", "ShipCeaseFireHealth", 30f, new ConfigDescription("Ship guns stop firing while hull health is below this percentage.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { val }));
		BallistaAutoReload = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "BallistaAutoReload", true, new ConfigDescription("Vanilla ballistas refill themselves with ballista ammunition from the nearest chest.", (AcceptableValueBase)null, new object[1] { val }));
		BallistaReloadRange = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BallistaReloadRange", 10f, new ConfigDescription("How far (m) a ballista looks for a chest to refill from.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 50f), new object[1] { val }));
		EarthStaffEitr = ((BaseUnityPlugin)this).Config.Bind<float>("General", "EarthStaffEitr", 5f, new ConfigDescription("Eitr used by each cast of the Earth Staff. Applied when the game starts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[1] { val }));
		FriendlyFireProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "FriendlyFireProtection", true, new ConfigDescription("Ballistas never target players or tamed creatures, and projectiles from ballistas, catapults, cannons and players (and their blasts) do not hurt players, tamed creatures, ships, carts or player-built pieces. Monster attacks are unaffected.", (AcceptableValueBase)null, new object[1] { val }));
		new Harmony("com.vvlee.corvette").PatchAll(typeof(CorvettePlugin).Assembly);
		AddLocalizations();
		PrefabManager.OnVanillaPrefabsAvailable += CreatePrefabs;
	}

	private static void AddLocalizations()
	{
		CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
		string text = "English";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "piece_vvlee_corvette", "Corvette" },
			{ "piece_vvlee_corvette_desc", "Age-of-sail corvette. 8 guns per broadside, 2 bow chasers and 2 stern chasers, all firing Staff of Fracturing shells." },
			{ "piece_vvlee_zeppelin", "Airship (Zeppelin)" },
			{ "piece_vvlee_zeppelin_desc", "A corvette hull slung under a canvas envelope. Same 20 guns. At the helm: hold Jump to climb, Crouch to descend. Launch it on water." },
			{ "piece_vvlee_vtol", "Airship (Rotor)" },
			{ "piece_vvlee_vtol_desc", "A corvette hull lifted by four rotors on its yards. Same 20 guns. At the helm: hold Jump to climb, Crouch to descend. Launch it on water." },
			{ "vvlee_air_boiler", "Boiler" },
			{ "vvlee_air_nofuel", "The boiler is cold - add coal" },
			{ "vvlee_air_lowfuel", "The boiler is almost out of coal" },
			{ "vvlee_air_warn", "Altitude warning: the hull will start to strain if you climb higher" },
			{ "vvlee_air_wear", "Too high: the airship is losing durability" },
			{ "vvlee_air_noclimb", "Hull too damaged to climb - repair it" },
			{ "vvlee_air_crippled", "Hull critical: descending" },
			{ "piece_vvlee_cannon", "Cannon" },
			{ "piece_vvlee_cannon_desc", "Defensive cannon. Automatically fires Staff of Fracturing shells at hostile creatures in front of it. Wears out with use; repair it with the hammer." },
			{ "vvlee_cannon_durability", "Shots left" },
			{ "vvlee_cannon_needs_repair", "Worn out - repair with the hammer" },
			{ "piece_vvlee_cannoncart", "Cannon cart" },
			{ "item_vvlee_staffearth", "Earth Staff" },
			{ "item_vvlee_staffearth_desc", "Shapes the land and harms nothing. Primary: a yellow orb that digs out the ground where it lands. Secondary: a red orb that raises it." },
			{ "piece_vvlee_cannoncart_desc", "A cannon mounted on a cart. Pull it into position and stay close: it only fires while parked with a player within 5 m. The gun points to the rear." }
		});
		text = "Chinese_Trad";
		localization.AddTranslation(ref text, new Dictionary<string, string>
		{
			{ "piece_vvlee_corvette", "克爾維特艦" },
			{ "piece_vvlee_corvette_desc", "風帆時代輕型護衛艦。兩舷各 8 門炮、艦首與艦尾各 2 門追擊炮,發射碎裂法杖炮彈。舵手或船長就位時艦炮才會開火。" },
			{ "piece_vvlee_zeppelin", "飛船(齊柏林式)" },
			{ "piece_vvlee_zeppelin_desc", "以帆布氣囊吊掛克爾維特艦船身的飛船,火炮配置相同(20 門)。操舵時按住跳躍鍵上升、蹲下鍵下降。請在水面上建造。" },
			{ "piece_vvlee_vtol", "飛船(旋翼式)" },
			{ "piece_vvlee_vtol_desc", "以橫桁兩端四具旋翼升空的克爾維特艦船身,火炮配置相同(20 門)。操舵時按住跳躍鍵上升、蹲下鍵下降。請在水面上建造。" },
			{ "vvlee_air_boiler", "鍋爐" },
			{ "vvlee_air_nofuel", "鍋爐沒有火——請加煤炭" },
			{ "vvlee_air_lowfuel", "鍋爐的煤炭快燒完了" },
			{ "vvlee_air_warn", "高度警告:再往上飛船身會開始受損" },
			{ "vvlee_air_wear", "飛太高了:飛船正在損失耐久" },
			{ "vvlee_air_noclimb", "船身受損過重,無法爬升——請修理" },
			{ "vvlee_air_crippled", "船身瀕臨解體:正在緩降" },
			{ "piece_vvlee_cannon", "火炮" },
			{ "piece_vvlee_cannon_desc", "防禦用火炮。自動對前方的敵對生物發射碎裂法杖炮彈。開火會損耗,需用錘子修理。" },
			{ "vvlee_cannon_durability", "剩餘開火次數" },
			{ "vvlee_cannon_needs_repair", "已耗損,請用錘子修理" },
			{ "piece_vvlee_cannoncart", "拖曳火炮" },
			{ "piece_vvlee_cannoncart_desc", "架在板車上的火炮,炮口朝後。拖到定位放下後,周圍 5 公尺內有人才會開火。" },
			{ "item_vvlee_staffearth", "大地法杖" },
			{ "item_vvlee_staffearth_desc", "沒有攻擊力,只能改變地形