Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Corvette v0.4.2
plugins/Corvette.dll
Decompiled 15 hours ago
The result has been truncated due to the large size, download it to view full contents!
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", "沒有攻擊力,只能改變地形