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 RustyHeathensWarShips v0.1.3
plugins/RustyHeathensWarShips/RustyHeathensWarShips.dll
Decompiled 4 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Rusty Heathens War Ships")] [assembly: AssemblyFileVersion("0.1.3.0")] [assembly: AssemblyVersion("0.1.3.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RustyHeathens.ShipBallista { public sealed class MountedBallista : MonoBehaviour, IPlaced, IDoodadController { internal static readonly List<MountedBallista> All = new List<MountedBallista>(); private const string ParentKey = "RHSB.Ship.v1"; private const string PositionKey = "RHSB.Position.v1"; private const string RotationKey = "RHSB.Rotation.v1"; private const string ShipGuidKey = "RHSB.ParentGuid.v1"; private const string GunnerKey = "RHSB.Gunner.v1"; private const string YawKey = "RHSB.Yaw.v1"; private const string PitchKey = "RHSB.Pitch.v1"; private const string RequestRpc = "RHSB.Request.v1"; private const string ReplyRpc = "RHSB.Reply.v1"; private const string InputRpc = "RHSB.Input.v1"; private const string ReleaseRpc = "RHSB.Release.v1"; private const string DestroyRpc = "RHSB.ShipGone.v1"; internal ZNetView View; internal Ship Ship; internal GameObject LastInheritedProjectile; private Turret turret; private WearNTear wear; private Rigidbody body; private Transform seat; private Collider[] colliders; private Renderer[] renderers; private bool[] colliderEnabled; private bool[] rendererEnabled; private bool visible = true; private bool wasOwner; private long parentPeer; private float nextPosition; private float nextInput; private float pendingUntil; private float lastPacketTime; private float localSince; private float weaponInputAt; private float yaw; private float pitch; private float inputYaw; private float inputPitch; private bool fire; private bool aimOutside; private bool capturedFire; private bool linkLogged; private bool legacyWarning; private Player local; private int localToken; private readonly ExitKeyLatch exitKey = new ExitKeyLatch(); private readonly ControlLease lease = new ControlLease(Guid.NewGuid().GetHashCode()); private static readonly MethodInfo DestroyPiece = AccessTools.Method(typeof(WearNTear), "Destroy", new Type[2] { typeof(HitData), typeof(bool) }, (Type[])null); internal ZDOID ParentId { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)View) || !View.IsValid()) { return ZDOID.None; } ZDO zDO = View.GetZDO(); string text = zDO.GetString("RHSB.ParentGuid.v1", ""); if (!string.IsNullOrEmpty(text)) { Ship val = ShipIdentity.Find(text); if (Object.op_Implicit((Object)(object)val)) { return ((Component)val).GetComponent<ZNetView>().GetZDO().m_uid; } } return zDO.GetZDOID("RHSB.Ship.v1"); } } private bool PersistentParent { get { if (Object.op_Implicit((Object)(object)View) && View.IsValid()) { return !string.IsNullOrEmpty(View.GetZDO().GetString("RHSB.ParentGuid.v1", "")); } return false; } } internal bool Mounted { get { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (!PersistentParent) { return ParentId != ZDOID.None; } return true; } } internal bool Ready { get { if (Mounted && Object.op_Implicit((Object)(object)Ship)) { return ((Component)Ship).GetComponent<ZNetView>().IsValid(); } return false; } } internal bool Manual { get { if (Mounted) { return View.GetZDO().GetLong("RHSB.Gunner.v1", 0L) != 0; } return false; } } private double Now { get { if (!Object.op_Implicit((Object)(object)ZNet.instance)) { return Time.realtimeSinceStartup; } return ZNet.instance.GetTimeSeconds(); } } private float YawLimit { get { if (!Manual) { if (!(turret.m_horizontalAngle < 0f)) { return Mathf.Min(180f, turret.m_horizontalAngle); } return 180f; } return 180f; } } private void Awake() { //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_0144: Unknown result type (might be due to invalid IL or missing references) turret = ((Component)this).GetComponent<Turret>(); wear = ((Component)this).GetComponent<WearNTear>(); View = ((Component)this).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)View) || !View.IsValid()) { ((Behaviour)this).enabled = false; return; } wasOwner = false; if (Mounted && Object.op_Implicit((Object)(object)wear)) { wear.m_noSupportWear = false; wear.m_staticPosition = false; } View.Register<long>("RHSB.Request.v1", (Action<long, long>)ReceiveRequest); View.Register<long, bool, int>("RHSB.Reply.v1", (Action<long, long, bool, int>)ReceiveReply); View.Register<ZPackage>("RHSB.Input.v1", (Action<long, ZPackage>)ReceiveInput); View.Register<long, int>("RHSB.Release.v1", (Action<long, long, int>)ReceiveRelease); View.Register<ZDOID>("RHSB.ShipGone.v1", (Action<long, ZDOID>)ReceiveParentDestroyed); GameObject val = new GameObject("RHSB_Gunner"); val.transform.SetParent(((Component)this).transform, false); seat = val.transform; seat.localPosition = new Vector3(0f, 0.05f, -1.35f); colliders = ((Component)this).GetComponentsInChildren<Collider>(true); renderers = ((Component)this).GetComponentsInChildren<Renderer>(true); colliderEnabled = new bool[colliders.Length]; for (int i = 0; i < colliders.Length; i++) { colliderEnabled[i] = colliders[i].enabled; } rendererEnabled = new bool[renderers.Length]; for (int j = 0; j < renderers.Length; j++) { rendererEnabled[j] = renderers[j].enabled; } All.Add(this); } public void OnPlaced() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00f4: 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) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if (Mounted) { return; } Ship placingOn = Plugin.PlacingOn; if (!Object.op_Implicit((Object)(object)placingOn) || !Object.op_Implicit((Object)(object)View) || !View.IsValid() || !View.IsOwner()) { return; } ZNetView component = ((Component)placingOn).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid()) { ZDO zDO = View.GetZDO(); string text = ShipIdentity.Ensure(placingOn); if (string.IsNullOrEmpty(text)) { Plugin.LogMount("Ship identity not ready; mount binding deferred."); return; } zDO.Set("RHSB.ParentGuid.v1", text); zDO.Set("RHSB.Ship.v1", component.GetZDO().m_uid); zDO.Set("RHSB.Position.v1", ((Component)placingOn).transform.InverseTransformPoint(((Component)this).transform.position)); Vector3 val = Vector3.ProjectOnPlane(((Component)this).transform.forward, ((Component)placingOn).transform.up); Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized, ((Component)placingOn).transform.up); zDO.Set("RHSB.Rotation.v1", Quaternion.Inverse(((Component)placingOn).transform.rotation) * val2); zDO.Set("RHSB.Gunner.v1", 0L); Ship = placingOn; SetupMovingBody(); Follow(); Plugin.LogMount("Mounted ballista on " + ((Object)((Component)placingOn).gameObject).name + " at local " + ((object)zDO.GetVec3("RHSB.Position.v1", Vector3.zero)/*cast due to .constrained prefix*/).ToString()); } } private void SetupMovingBody() { if (!Object.op_Implicit((Object)(object)body)) { body = ((Component)this).GetComponent<Rigidbody>(); if (!Object.op_Implicit((Object)(object)body)) { body = ((Component)this).gameObject.AddComponent<Rigidbody>(); } } body.isKinematic = true; body.useGravity = false; if (Object.op_Implicit((Object)(object)wear)) { wear.m_noSupportWear = false; wear.m_staticPosition = false; Plugin.ProvideShipSupport(wear, this); } ZSyncTransform component = ((Component)this).GetComponent<ZSyncTransform>(); if (Object.op_Implicit((Object)(object)component)) { ((Behaviour)component).enabled = false; } Collider[] componentsInChildren = ((Component)Ship).GetComponentsInChildren<Collider>(true); Collider[] array = colliders; foreach (Collider val in array) { if (!Object.op_Implicit((Object)(object)val)) { continue; } Collider[] array2 = componentsInChildren; foreach (Collider val2 in array2) { if (Object.op_Implicit((Object)(object)val2) && (Object)(object)val != (Object)(object)val2) { Physics.IgnoreCollision(val, val2, true); } } } } private void Follow() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_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_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) if (!Mounted || !Object.op_Implicit((Object)(object)ZNetScene.instance)) { return; } GameObject val = ZNetScene.instance.FindInstance(ParentId); Ship val2 = (Object.op_Implicit((Object)(object)val) ? val.GetComponent<Ship>() : null); string text = View.GetZDO().GetString("RHSB.ParentGuid.v1", ""); if (!string.IsNullOrEmpty(text)) { val2 = ShipIdentity.Find(text); } if (Object.op_Implicit((Object)(object)val2) && Rules.SupportedShip(((Object)((Component)val2).gameObject).name)) { if (!PersistentParent) { if (Vector3.Distance(((Component)val2).transform.TransformPoint(View.GetZDO().GetVec3("RHSB.Position.v1", Vector3.zero)), ((Component)this).transform.position) > 2f) { MissingParent(); return; } string text2 = ShipIdentity.Ensure(val2); if (string.IsNullOrEmpty(text2)) { MissingParent(); return; } if (View.IsOwner()) { View.GetZDO().Set("RHSB.ParentGuid.v1", text2); } } if ((Object)(object)Ship != (Object)(object)val2 || !Object.op_Implicit((Object)(object)body)) { Ship = val2; SetupMovingBody(); } if (!linkLogged) { linkLogged = true; Plugin.LogMount("Restored ship attachment on " + ((Object)((Component)val2).gameObject).name + "; persistent=" + PersistentParent); } ZNetView component = ((Component)Ship).GetComponent<ZNetView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsValid()) { SetVisible(show: false); return; } parentPeer = component.GetZDO().GetOwner(); ZDO zDO = View.GetZDO(); if (View.IsOwner() && zDO.GetZDOID("RHSB.Ship.v1") != component.GetZDO().m_uid) { zDO.Set("RHSB.Ship.v1", component.GetZDO().m_uid); } Vector3 val3 = ((Component)Ship).transform.TransformPoint(zDO.GetVec3("RHSB.Position.v1", Vector3.zero)); Quaternion val4 = ((Component)Ship).transform.rotation * zDO.GetQuaternion("RHSB.Rotation.v1", Quaternion.identity); ((Component)this).transform.SetPositionAndRotation(val3, val4); SetVisible(show: true); if (View.IsOwner() && Time.unscaledTime >= nextPosition) { nextPosition = Time.unscaledTime + 0.2f; zDO.SetPosition(val3); zDO.SetRotation(val4); } } else { MissingParent(); } } private void MissingParent() { Ship = null; StopLocal(); bool flag = !PersistentParent; SetVisible(flag); if (flag && !legacyWarning) { legacyWarning = true; Plugin.LogMount("Legacy ship link is unavailable. Remove/rebuild this ballista once to establish a persistent connection."); } } private void SetVisible(bool show) { if (visible == show) { return; } visible = show; for (int i = 0; i < colliders.Length; i++) { if (Object.op_Implicit((Object)(object)colliders[i])) { colliders[i].enabled = show && colliderEnabled[i]; } } for (int j = 0; j < renderers.Length; j++) { if (Object.op_Implicit((Object)(object)renderers[j])) { renderers[j].enabled = show && rendererEnabled[j]; } } } private void FixedUpdate() { if (Mounted) { Follow(); } } private void LateUpdate() { if (Mounted) { Follow(); } } private bool OwnerReady() { if (!Object.op_Implicit((Object)(object)View) || !View.IsValid()) { return false; } bool flag = View.IsOwner(); if (flag != wasOwner) { wasOwner = flag; lease.Clear(); fire = false; if (flag) { View.GetZDO().Set("RHSB.Gunner.v1", 0L); } } if (flag) { return Ready; } return false; } internal void TickOwner() { if (!Mounted) { return; } Follow(); if (OwnerReady()) { turret.m_targetPlayers = false; turret.m_targetTamed = false; turret.m_targetTamedConfig = false; turret.m_targetEnemies = true; if (lease.Player != 0L && (!lease.Active(Now) || !ValidPawn(lease.Player, lease.Peer))) { ClearLease(); } if (lease.Active(Now)) { Plugin.ClearTarget(turret); } } } private bool ValidPawn(long playerId, long peer) { //IL_004c: 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) Player player = Player.GetPlayer(playerId); if (!Object.op_Implicit((Object)(object)player) || ((Character)player).IsDead() || !Ready) { return false; } ZNetView component = ((Component)player).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && component.GetZDO().GetOwner() == peer && Vector3.Distance(((Component)player).transform.position, seat.position) <= 4f) { return Ship.IsPlayerInBoat(player); } return false; } internal void Request(Player player) { if (!((Object)(object)player != (Object)(object)Player.m_localPlayer)) { if (!Ready) { Plugin.Tell("Ship link unavailable. Rebuild this older ballista once."); return; } if (player.GetDoodadController() != null || ((Character)player).IsAttached()) { Plugin.Tell("Leave the helm or seat before operating the ballista."); return; } if ((Object)(object)((Character)player).GetStandingOnShip() != (Object)(object)Ship) { Plugin.Tell("Stand on the ship near the ballista."); return; } pendingUntil = Time.unscaledTime + 3f; Plugin.LogMount("Manual control requested by " + player.GetPlayerName()); View.InvokeRPC("RHSB.Request.v1", new object[1] { player.GetPlayerID() }); } } private void ReceiveRequest(long sender, long playerId) { if (OwnerReady()) { bool flag = lease.Acquire(playerId, sender, Now, ValidPawn(playerId, sender)); if (flag) { View.GetZDO().Set("RHSB.Gunner.v1", playerId); fire = false; Plugin.ClearTarget(turret); } Plugin.LogMount("Manual control " + (flag ? "granted" : "denied") + " for player " + playerId); View.InvokeRPC(sender, "RHSB.Reply.v1", new object[3] { playerId, flag, lease.Token }); } } private void ReceiveReply(long sender, long playerId, bool approved, int token) { //IL_0120: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)View) && View.IsValid() && View.GetZDO().GetOwner() == sender && Object.op_Implicit((Object)(object)localPlayer) && localPlayer.GetPlayerID() == playerId && !(Time.unscaledTime > pendingUntil)) { pendingUntil = 0f; if (!approved) { Plugin.Tell("Ballista is occupied, or you are too far away."); return; } if (!Ready || ((Character)localPlayer).IsDead() || localPlayer.GetDoodadController() != null || ((Character)localPlayer).IsAttached()) { View.InvokeRPC("RHSB.Release.v1", new object[2] { playerId, token }); return; } local = localPlayer; localToken = token; localSince = Time.unscaledTime; nextInput = 0f; exitKey.Reset(); Plugin.LogMount("Manual control started for " + localPlayer.GetPlayerName()); localPlayer.StartDoodadControl((IDoodadController)(object)this); ((Character)localPlayer).AttachStart(seat, (GameObject)null, false, false, true, "standing", new Vector3(0f, 0f, -0.5f), (Transform)null); Plugin.Tell("Manual ballista: mouse to aim, left mouse to fire, E to leave."); } } private void ReceiveInput(long sender, ZPackage pkg) { if (!OwnerReady() || pkg == null || pkg.GetArray().Length > 64) { return; } try { long num = pkg.ReadLong(); int token = pkg.ReadInt(); float n = pkg.ReadSingle(); float n2 = pkg.ReadSingle(); bool flag = pkg.ReadBool(); if (lease.Input(num, sender, token, Now, ValidPawn(num, sender), n, n2)) { inputYaw = Rules.Clamp(n, -180f, 180f); inputPitch = Rules.Clamp(n2, -75f, 60f); View.GetZDO().Set("RHSB.Yaw.v1", inputYaw); View.GetZDO().Set("RHSB.Pitch.v1", inputPitch); lastPacketTime = Time.unscaledTime; fire = flag && Rules.InArc(n, n2, 180f, -75f, 60f); } } catch (Exception) { } } private void ReceiveRelease(long sender, long playerId, int token) { if (OwnerReady() && lease.Matches(playerId, sender, token, Now)) { ClearLease(); } } private void ClearLease() { lease.Clear(); fire = false; View.GetZDO().Set("RHSB.Gunner.v1", 0L); Plugin.ClearTarget(turret); } internal void RotateGun() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: 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_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_02a9: Unknown result type (might be due to invalid IL or missing references) //IL_02ae: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) if (Ready && Object.op_Implicit((Object)(object)turret.m_turretBody) && Object.op_Implicit((Object)(object)turret.m_turretNeck) && Object.op_Implicit((Object)(object)turret.m_eye)) { Vector3 val = ((Component)this).transform.forward; object? value = Plugin.Target.GetValue(turret); Character val2 = (Character)((value is Character) ? value : null); if (Manual) { inputYaw = View.GetZDO().GetFloat("RHSB.Yaw.v1", 0f); inputPitch = View.GetZDO().GetFloat("RHSB.Pitch.v1", 0f); } else if (Object.op_Implicit((Object)(object)val2) && !val2.IsDead()) { val = val2.GetCenterPoint() - turret.m_eye.transform.position; Vector3 val3 = ((Component)this).transform.InverseTransformDirection(((Vector3)(ref val)).normalized); inputYaw = Rules.Clamp(Mathf.Atan2(val3.x, val3.z) * 57.29578f, 0f - YawLimit, YawLimit); float y = val3.y; Vector2 val4 = new Vector2(val3.x, val3.z); inputPitch = Rules.Clamp((0f - Mathf.Atan2(y, ((Vector2)(ref val4)).magnitude)) * 57.29578f, -30f, 45f); } else { inputYaw = 0f; inputPitch = 0f; } float num = Mathf.Max(0.1f, turret.m_turnRate) * Time.fixedDeltaTime; yaw = Mathf.MoveTowardsAngle(yaw, inputYaw, num); pitch = Mathf.MoveTowards(pitch, inputPitch, num); Quaternion val5 = ((Component)this).transform.rotation * Quaternion.Euler(pitch, yaw, 0f); turret.m_turretBody.transform.rotation = val5 * (Quaternion)Plugin.BaseBody.GetValue(turret); turret.m_turretNeck.transform.rotation = ((Component)this).transform.rotation * Quaternion.Euler(0f, yaw, 0f) * (Quaternion)Plugin.BaseNeck.GetValue(turret); Quaternion val6 = ((Object.op_Implicit((Object)(object)val2) && !Manual) ? Quaternion.LookRotation(((Vector3)(ref val)).normalized, ((Component)this).transform.up) : (((Component)this).transform.rotation * Quaternion.Euler(inputPitch, inputYaw, 0f))); Plugin.AimDiff.SetValue(turret, Object.op_Implicit((Object)(object)val2) ? Mathf.Abs(Quaternion.Dot(val5, val6)) : (-1f)); if (View.IsOwner() && lease.Active(Now) && fire && Time.unscaledTime - lastPacketTime < 0.4f && Mathf.Abs(Mathf.DeltaAngle(yaw, inputYaw)) < 1f && Mathf.Abs(pitch - inputPitch) < 1f && Plugin.HasAmmo(turret) && !Plugin.IsCooling(turret) && LineSafe()) { Plugin.Shoot.Invoke(turret, null); } } } internal bool LineSafe() { //IL_002c: 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_0046: 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_0098: Unknown result type (might be due to invalid IL or missing references) if (!Ready || !Object.op_Implicit((Object)(object)turret.m_eye)) { return false; } RaycastHit[] array = Physics.RaycastAll(new Ray(turret.m_eye.transform.position, turret.m_eye.transform.forward), Mathf.Max(5f, turret.m_viewDistance), -1, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val = array2[num]; if (!((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)this).transform)) { if ((Object)(object)((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Ship>() == (Object)(object)Ship) { return false; } Character componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Character>(); if (Object.op_Implicit((Object)(object)componentInParent) && (componentInParent.IsPlayer() || componentInParent.IsTamed())) { return false; } return true; } } return true; } private void Update() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: 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: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)local)) { return; } bool flag = Menu.IsVisible() || InventoryGui.IsVisible() || Console.IsVisible() || TextInput.IsVisible() || (Object.op_Implicit((Object)(object)Chat.instance) && Chat.instance.HasFocus()); bool flag2 = exitKey.Poll(Input.GetKey((KeyCode)101), Input.GetKeyDown((KeyCode)101)); if (!Ready || ((Character)local).IsDead() || (object)local.GetDoodadController() != this || flag || flag2 || Input.GetKeyDown((KeyCode)27)) { StopLocal(); } else if (View.GetZDO().GetLong("RHSB.Gunner.v1", 0L) != local.GetPlayerID() && Time.unscaledTime > localSince + 2.5f) { StopLocal(); } else if (!(Time.unscaledTime < nextInput)) { nextInput = Time.unscaledTime + 0.1f; GameCamera instance = GameCamera.instance; if (Object.op_Implicit((Object)(object)instance)) { Vector3 val = ((Component)this).transform.InverseTransformDirection(((Component)instance).transform.forward); float num = Mathf.Atan2(val.x, val.z) * 57.29578f; float y = val.y; Vector2 val2 = new Vector2(val.x, val.z); float num2 = (0f - Mathf.Atan2(y, ((Vector2)(ref val2)).magnitude)) * 57.29578f; aimOutside = !Rules.InArc(num, num2, 180f, -75f, 60f); ZPackage val3 = new ZPackage(); val3.Write(local.GetPlayerID()); val3.Write(localToken); val3.Write(num); val3.Write(num2); val3.Write(capturedFire && Time.unscaledTime - weaponInputAt < 0.3f); View.InvokeRPC("RHSB.Input.v1", new object[1] { val3 }); } } } internal void CaptureWeaponInput(ref bool attack, ref bool attackHold, ref bool secondary, ref bool secondaryHold) { capturedFire = GunnerInput.Consume(ref attack, ref attackHold, ref secondary, ref secondaryHold); weaponInputAt = Time.unscaledTime; } internal void StopLocal() { Player val = local; if (Object.op_Implicit((Object)(object)val)) { ((Character)val).AttachStop(); if ((object)val.GetDoodadController() == this) { val.StopDoodadControl(); } else { OnUseStop(val); } local = null; } } public void OnUseStop(Player player) { Plugin.LogMount("Manual control released by " + player.GetPlayerName()); if (Object.op_Implicit((Object)(object)View) && View.IsValid()) { View.InvokeRPC("RHSB.Release.v1", new object[2] { player.GetPlayerID(), localToken }); } ((Character)player).AttachStop(); local = null; } public void ApplyControlls(Vector3 move, Vector3 look, bool run, bool autoRun, bool block) { } public Component GetControlledComponent() { return (Component)(object)this; } public Vector3 GetPosition() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)seat)) { return ((Component)this).transform.position; } return seat.position; } public bool IsValid() { if (Object.op_Implicit((Object)(object)this)) { return Ready; } return false; } private void OnGUI() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)local)) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 18, alignment = (TextAnchor)4 }; GUI.Label(new Rect((float)(Screen.width / 2 - 300), (float)(Screen.height - 100), 600f, 70f), "WAR SHIPS — MANUAL\nMouse: aim | LMB: fire | E: automatic\nAmmo: " + turret.GetAmmo() + (aimOutside ? " | Aim outside firing arc" : ""), val); GUI.Label(new Rect((float)(Screen.width / 2 - 12), (float)(Screen.height / 2 - 16), 24f, 32f), "+", val); } } internal void ParentDestroyed() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) if (Mounted && Object.op_Implicit((Object)(object)View) && View.IsValid()) { if (View.IsOwner()) { DestroyMount(); return; } View.InvokeRPC("RHSB.ShipGone.v1", new object[1] { ParentId }); } } private void ReceiveParentDestroyed(long sender, ZDOID parent) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)View) && View.IsValid() && View.IsOwner() && sender == parentPeer && parent == ParentId) { DestroyMount(); } } private void DestroyMount() { StopLocal(); if (Object.op_Implicit((Object)(object)wear) && View.IsOwner()) { DestroyPiece.Invoke(wear, new object[2] { null, false }); } } private void OnDestroy() { StopLocal(); All.Remove(this); } } [BepInPlugin("com.rustyheathens.warships", "Rusty Heathens War Ships", "0.1.3")] public sealed class Plugin : BaseUnityPlugin { [HarmonyPatch(typeof(Turret), "Awake")] private static class TurretSpawn { private static void Postfix(Turret __instance) { EnsureMount(__instance); } } [HarmonyPatch(typeof(ZNetScene), "CreateObject")] private static class RestoredObject { private static void Postfix(GameObject __result) { if (Object.op_Implicit((Object)(object)__result)) { ShipIdentity.Ensure(__result.GetComponent<Ship>()); EnsureMount(__result.GetComponent<Turret>()); } } } [HarmonyPatch(typeof(Ship), "Awake")] private static class ShipSpawn { private static void Postfix(Ship __instance) { ShipIdentity.Ensure(__instance); } } [HarmonyPatch(typeof(Player), "PieceRayTest")] private static class DeckPlacementRay { private static bool Prefix(Player __instance, ref Vector3 __0, ref Vector3 __1, ref Piece __2, ref Heightmap __3, ref Collider __4, ref bool __result) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) object? value = Ghost.GetValue(__instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.GetComponent<Turret>())) { Piece selectedPiece = __instance.GetSelectedPiece(); if (Rules.Ballista((selectedPiece != null) ? ((Object)((Component)selectedPiece).gameObject).name : null) && Object.op_Implicit((Object)(object)GameCamera.instance)) { int num = (int)RayMask.GetValue(__instance) | LayerMask.GetMask(new string[2] { "vehicle", "piece" }); Transform transform = ((Component)GameCamera.instance).transform; RaycastHit val2 = default(RaycastHit); if (!Physics.Raycast(transform.position, transform.forward, ref val2, 50f, num, (QueryTriggerInteraction)1)) { return true; } Ship componentInParent = ((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<Ship>(); if (!Object.op_Implicit((Object)(object)componentInParent) || !Rules.SupportedShip(((Object)((Component)componentInParent).gameObject).name) || Vector3.Dot(((RaycastHit)(ref val2)).normal, ((Component)componentInParent).transform.up) < 0.5f) { return true; } if (string.IsNullOrEmpty(ShipIdentity.Ensure(componentInParent))) { __0 = (__1 = Vector3.zero); __2 = null; __3 = null; __4 = null; __result = false; return false; } float num2 = (float)PlaceDistance.GetValue(__instance); if (Vector3.Distance(((Character)__instance).GetEyePoint(), ((RaycastHit)(ref val2)).point) >= num2) { return true; } __0 = ((RaycastHit)(ref val2)).point; __1 = ((RaycastHit)(ref val2)).normal; __2 = null; __3 = null; __4 = null; __result = true; return false; } } return true; } } [HarmonyPatch(typeof(Player), "PlacePiece")] private static class PlacementContext { private static void Prefix(Piece piece, Vector3 pos) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) PlacingOn = ((Object.op_Implicit((Object)(object)piece) && Object.op_Implicit((Object)(object)((Component)piece).GetComponent<Turret>()) && Rules.Ballista(((Object)((Component)piece).gameObject).name)) ? ResolveShip(pos) : null); } private static Exception Finalizer(Exception __exception) { PlacingOn = null; return __exception; } } [HarmonyPatch(typeof(WearNTear), "OnPlaced")] private static class EarlyMountBinding { private static void Prefix(WearNTear __instance) { if (Object.op_Implicit((Object)(object)PlacingOn)) { MountedBallista component = ((Component)__instance).GetComponent<MountedBallista>(); if (Object.op_Implicit((Object)(object)component)) { component.OnPlaced(); } } } } [HarmonyPatch(typeof(WearNTear), "UpdateSupport")] private static class ShipSupport { private static bool Prefix(WearNTear __instance) { MountedBallista component = ((Component)__instance).GetComponent<MountedBallista>(); if (!Object.op_Implicit((Object)(object)component) || !component.Mounted) { return true; } ProvideShipSupport(__instance, component); return false; } } [HarmonyPatch(typeof(Turret), "UpdateTurretRotation")] private static class MountedRotation { private static bool Prefix(Turret __instance) { MountedBallista mountedBallista = Mount(__instance); if (!Object.op_Implicit((Object)(object)mountedBallista) || !mountedBallista.Mounted) { return true; } if (mountedBallista.Ready) { mountedBallista.RotateGun(); } return false; } } [HarmonyPatch(typeof(Turret), "FixedUpdate")] private static class MountedTick { private static bool Prefix(Turret __instance) { MountedBallista mountedBallista = Mount(__instance); if (!Object.op_Implicit((Object)(object)mountedBallista) || !mountedBallista.Mounted) { return true; } mountedBallista.TickOwner(); return mountedBallista.Ready; } } [HarmonyPatch(typeof(Turret), "UpdateTarget")] private static class ManualTarget { private static bool Prefix(Turret __instance) { MountedBallista mountedBallista = Mount(__instance); if (Object.op_Implicit((Object)(object)mountedBallista) && mountedBallista.Mounted) { return !mountedBallista.Manual; } return true; } } [HarmonyPatch(typeof(Turret), "UpdateAttack")] private static class AttackGuard { private static bool Prefix(Turret __instance) { MountedBallista mountedBallista = Mount(__instance); if (!Object.op_Implicit((Object)(object)mountedBallista) || !mountedBallista.Mounted) { return true; } object? value = Target.GetValue(__instance); Character val = (Character)((value is Character) ? value : null); if (mountedBallista.Ready && !mountedBallista.Manual && Object.op_Implicit((Object)(object)val) && !val.IsPlayer()) { return !val.IsTamed(); } return false; } } [HarmonyPatch(typeof(Turret), "ShootProjectile")] private static class ShootGuard { private static bool Prefix(Turret __instance) { MountedBallista mountedBallista = Mount(__instance); if (Object.op_Implicit((Object)(object)mountedBallista) && mountedBallista.Mounted) { if (mountedBallista.Ready && mountedBallista.View.IsOwner()) { return mountedBallista.LineSafe(); } return false; } return true; } private static void Postfix(Turret __instance) { //IL_0080: 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_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) MountedBallista mountedBallista = Mount(__instance); if (!Object.op_Implicit((Object)(object)mountedBallista) || !mountedBallista.Ready || !mountedBallista.View.IsOwner()) { return; } object? value = Projectile.GetValue(__instance); GameObject val = (GameObject)((value is GameObject) ? value : null); if (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)mountedBallista.LastInheritedProjectile) { Projectile component = val.GetComponent<Projectile>(); Rigidbody component2 = ((Component)mountedBallista.Ship).GetComponent<Rigidbody>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2)) { ProjectileVelocity.SetValue(component, (Vector3)ProjectileVelocity.GetValue(component) + component2.GetPointVelocity(val.transform.position)); } mountedBallista.LastInheritedProjectile = val; } } } [HarmonyPatch(typeof(Turret), "Interact")] private static class ManualInteract { private static bool Prefix(Turret __instance, Humanoid __0, bool __1, bool __2, ref bool __result) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown MountedBallista mountedBallista = Mount(__instance); if (!Object.op_Implicit((Object)(object)mountedBallista) || !mountedBallista.Mounted || !__2 || __1 || !(__0 is Player)) { return true; } mountedBallista.Request((Player)__0); __result = true; return false; } } [HarmonyPatch(typeof(Turret), "GetHoverText")] private static class HoverText { private static void Postfix(Turret __instance, ref string __result) { MountedBallista mountedBallista = Mount(__instance); if (Object.op_Implicit((Object)(object)mountedBallista) && mountedBallista.Mounted) { __result = __result + "\n[Shift+E] Manual control\n" + (mountedBallista.Manual ? "Gunner operating" : "Automatic: enemies only"); } } } [HarmonyPatch(typeof(Player), "SetControls")] private static class GunnerControlInput { private static void Prefix(Player __instance, ref bool attack, ref bool attackHold, ref bool secondaryAttack, ref bool secondaryAttackHold) { MountedBallista mountedBallista = __instance.GetDoodadController() as MountedBallista; if (Object.op_Implicit((Object)(object)mountedBallista)) { mountedBallista.CaptureWeaponInput(ref attack, ref attackHold, ref secondaryAttack, ref secondaryAttackHold); } } } [HarmonyPatch(typeof(Player), "PlayerAttackInput")] private static class GunnerAttackInput { private static bool Prefix(Player __instance) { return !(__instance.GetDoodadController() is MountedBallista); } } [HarmonyPatch(typeof(Ship), "CanBeRemoved")] private static class ShipDismantle { private static void Postfix(Ship __instance, ref bool __result) { if (!__result) { return; } foreach (MountedBallista item in MountedBallista.All) { if (Object.op_Implicit((Object)(object)item) && (Object)(object)item.Ship == (Object)(object)__instance && item.Mounted) { __result = false; break; } } } } [HarmonyPatch(typeof(Ship), "OnDestroyed")] private static class ShipDestroyed { private static void Prefix(Ship __instance) { foreach (MountedBallista item in new List<MountedBallista>(MountedBallista.All)) { if (Object.op_Implicit((Object)(object)item) && (Object)(object)item.Ship == (Object)(object)__instance) { item.ParentDestroyed(); } } } } public const string Id = "com.rustyheathens.warships"; internal static Plugin Instance; private Harmony harmony; [ThreadStatic] internal static Ship PlacingOn; internal static readonly FieldInfo Ghost = AccessTools.Field(typeof(Player), "m_placementGhost"); internal static readonly FieldInfo RayMask = AccessTools.Field(typeof(Player), "m_placeRayMask"); internal static readonly FieldInfo PlaceDistance = AccessTools.Field(typeof(Player), "m_maxPlaceDistance"); internal static readonly FieldInfo Target = AccessTools.Field(typeof(Turret), "m_target"); internal static readonly FieldInfo HaveTarget = AccessTools.Field(typeof(Turret), "m_haveTarget"); internal static readonly FieldInfo AimDiff = AccessTools.Field(typeof(Turret), "m_aimDiffToTarget"); internal static readonly FieldInfo TargetTimer = AccessTools.Field(typeof(Turret), "m_updateTargetTimer"); internal static readonly FieldInfo BaseBody = AccessTools.Field(typeof(Turret), "m_baseBodyRotation"); internal static readonly FieldInfo BaseNeck = AccessTools.Field(typeof(Turret), "m_baseNeckRotation"); internal static readonly MethodInfo Shoot = AccessTools.Method(typeof(Turret), "ShootProjectile", (Type[])null, (Type[])null); internal static readonly MethodInfo Ammo = AccessTools.Method(typeof(Turret), "HasAmmo", (Type[])null, (Type[])null); internal static readonly MethodInfo Cooling = AccessTools.Method(typeof(Turret), "IsCoolingDown", (Type[])null, (Type[])null); internal static readonly MethodInfo Reload = AccessTools.Method(typeof(Turret), "UpdateReloadState", (Type[])null, (Type[])null); internal static readonly MethodInfo Bolt = AccessTools.Method(typeof(Turret), "UpdateVisualBolt", (Type[])null, (Type[])null); internal static readonly FieldInfo Projectile = AccessTools.Field(typeof(Turret), "m_lastProjectile"); internal static readonly FieldInfo Support = AccessTools.Field(typeof(WearNTear), "m_support"); internal static readonly MethodInfo MaxSupport = AccessTools.Method(typeof(WearNTear), "GetMaxSupport", (Type[])null, (Type[])null); internal static readonly FieldInfo ProjectileVelocity = AccessTools.Field(typeof(Projectile), "m_vel"); private void Awake() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown Instance = this; if (Target == null || Shoot == null || Ammo == null || Cooling == null || Ghost == null || PlaceDistance == null) { throw new InvalidOperationException("Unsupported Valheim ballista/placement API."); } harmony = new Harmony("com.rustyheathens.warships"); harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"War Ships 0.1.3 test build loaded. Longship/Drakkar: place a ballista with the hammer; Shift+E to aim manually."); } private void OnDestroy() { foreach (MountedBallista item in new List<MountedBallista>(MountedBallista.All)) { if (Object.op_Implicit((Object)(object)item)) { item.StopLocal(); } } Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } Instance = null; } internal static void LogMount(string message) { if (Object.op_Implicit((Object)(object)Instance)) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("[War Ships] " + message)); } } internal static void Tell(string message) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)2, message, 0, (Sprite)null, false); } } internal static bool HasAmmo(Turret t) { return (bool)Ammo.Invoke(t, null); } internal static bool IsCooling(Turret t) { return (bool)Cooling.Invoke(t, null); } internal static void ClearTarget(Turret t) { Target.SetValue(t, null); HaveTarget.SetValue(t, false); TargetTimer.SetValue(t, 0f); } internal static MountedBallista Mount(Turret t) { if (!Object.op_Implicit((Object)(object)t)) { return null; } return ((Component)t).GetComponent<MountedBallista>(); } internal static Ship ResolveShip(Vector3 pos) { //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_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_0015: 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_0081: 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) RaycastHit[] array = Physics.RaycastAll(pos + Vector3.up * 0.4f, Vector3.down, 1.8f, -1, (QueryTriggerInteraction)1); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val = array2[num]; Ship componentInParent = ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent<Ship>(); if (Object.op_Implicit((Object)(object)componentInParent) && Rules.SupportedShip(((Object)((Component)componentInParent).gameObject).name) && Vector3.Dot(((RaycastHit)(ref val)).normal, ((Component)componentInParent).transform.up) > 0.5f) { return componentInParent; } } return null; } internal static void ProvideShipSupport(WearNTear wear, MountedBallista mount) { if (!Object.op_Implicit((Object)(object)wear) || !Object.op_Implicit((Object)(object)mount) || !mount.Mounted) { return; } wear.m_noSupportWear = false; if (mount.Ready) { float num = (float)MaxSupport.Invoke(wear, null); Support.SetValue(wear, num); if (mount.View.IsOwner()) { mount.View.GetZDO().Set(ZDOVars.s_support, num); } } } internal static void EnsureMount(Turret turret) { if (Object.op_Implicit((Object)(object)turret) && Rules.Ballista(((Object)((Component)turret).gameObject).name)) { ZNetView component = ((Component)turret).GetComponent<ZNetView>(); if (Object.op_Implicit((Object)(object)component) && component.IsValid() && !Object.op_Implicit((Object)(object)Mount(turret))) { ((Component)turret).gameObject.AddComponent<MountedBallista>(); } } } } internal static class Rules { internal const float ManualYawLimit = 180f; internal const float ManualPitchMin = -75f; internal const float ManualPitchMax = 60f; internal static bool SupportedShip(string name) { if (name == null) { return false; } if (name.EndsWith("(Clone)", StringComparison.Ordinal)) { name = name.Substring(0, name.Length - 7); } if (!(name == "VikingShip")) { return name == "VikingShip_Ashlands"; } return true; } internal static bool Ballista(string name) { if (name == null) { return false; } if (name.EndsWith("(Clone)", StringComparison.Ordinal)) { name = name.Substring(0, name.Length - 7); } return name == "piece_turret"; } internal static bool Finite(float n) { if (!float.IsNaN(n)) { return !float.IsInfinity(n); } return false; } internal static bool InArc(float yaw, float pitch, float limit, float minPitch = -30f, float maxPitch = 45f) { if (Finite(yaw) && Finite(pitch) && Math.Abs(yaw) <= limit && pitch >= minPitch) { return pitch <= maxPitch; } return false; } internal static float Clamp(float n, float lo, float hi) { return Math.Max(lo, Math.Min(hi, n)); } } internal sealed class StableShipIndex<T> where T : class { private readonly Dictionary<string, HashSet<T>> entries = new Dictionary<string, HashSet<T>>(StringComparer.Ordinal); internal void Add(string id, T item) { if (!string.IsNullOrEmpty(id) && item != null) { if (!entries.TryGetValue(id, out var value)) { value = new HashSet<T>(); entries.Add(id, value); } value.Add(item); } } internal void Remove(string id, T item) { if (!string.IsNullOrEmpty(id) && entries.TryGetValue(id, out var value)) { value.Remove(item); if (value.Count == 0) { entries.Remove(id); } } } internal bool TryUnique(string id, Predicate<T> valid, out T result) { result = null; if (string.IsNullOrEmpty(id) || !entries.TryGetValue(id, out var value)) { return false; } foreach (T item in value) { if (valid(item)) { if (result != null) { result = null; return false; } result = item; } } return result != null; } } internal static class GunnerInput { internal static bool Consume(ref bool attack, ref bool attackHold, ref bool secondary, ref bool secondaryHold) { bool result = attack | attackHold; attack = (attackHold = (secondary = (secondaryHold = false))); return result; } } internal sealed class ExitKeyLatch { private bool released; internal void Reset() { released = false; } internal bool Poll(bool held, bool down) { if (!released) { if (!held) { released = true; } return false; } return down; } } internal sealed class ControlLease { internal long Player; internal long Peer; internal int Token; internal double Expires; private int sequence; internal ControlLease(int seed) { sequence = seed; } internal bool Active(double now) { if (Player != 0L) { return now < Expires; } return false; } internal bool Acquire(long player, long peer, double now, bool allowed) { if (!allowed || player == 0L || peer == 0L || Active(now)) { return false; } Player = player; Peer = peer; Token = ++sequence; if (Token == 0) { Token = ++sequence; } Expires = now + 2.5; return true; } internal bool Matches(long player, long peer, int token, double now) { if (Active(now) && Player == player && Peer == peer) { return Token == token; } return false; } internal bool Input(long player, long peer, int token, double now, bool allowed, float yaw, float pitch) { if (!allowed || !Matches(player, peer, token, now) || !Rules.Finite(yaw) || !Rules.Finite(pitch)) { return false; } Expires = now + 2.5; return true; } internal void Clear() { Player = (Peer = 0L); Expires = 0.0; Token = 0; } } public sealed class ShipIdentity : MonoBehaviour { internal const string Key = "RHSB.ShipGuid.v1"; private static readonly StableShipIndex<ShipIdentity> Index = new StableShipIndex<ShipIdentity>(); private Ship ship; private ZNetView view; private string registered = ""; private float next; internal static string Ensure(Ship ship) { if (!Object.op_Implicit((Object)(object)ship) || !Rules.SupportedShip(((Object)((Component)ship).gameObject).name)) { return ""; } ShipIdentity shipIdentity = ((Component)ship).GetComponent<ShipIdentity>(); if (!Object.op_Implicit((Object)(object)shipIdentity)) { shipIdentity = ((Component)ship).gameObject.AddComponent<ShipIdentity>(); } return shipIdentity.Refresh(); } internal static Ship Find(string guid) { if (!Index.TryUnique(guid, (ShipIdentity x) => Object.op_Implicit((Object)(object)x) && Object.op_Implicit((Object)(object)x.view) && x.view.IsValid() && x.view.GetZDO().GetString("RHSB.ShipGuid.v1", "") == guid, out var result)) { return null; } return result.ship; } private void Awake() { ship = ((Component)this).GetComponent<Ship>(); view = ((Component)this).GetComponent<ZNetView>(); Refresh(); } private string Refresh() { if (!Object.op_Implicit((Object)(object)view) || !view.IsValid()) { return ""; } ZDO zDO = view.GetZDO(); string text = zDO.GetString("RHSB.ShipGuid.v1", ""); if (string.IsNullOrEmpty(text) && view.IsOwner()) { text = Guid.NewGuid().ToString("N"); zDO.Set("RHSB.ShipGuid.v1", text); Plugin.LogMount("Saved ship identity initialized for " + ((Object)((Component)this).gameObject).name); } if (text != registered) { Index.Remove(registered, this); registered = text; Index.Add(registered, this); } return text; } private void Update() { if (Time.unscaledTime >= next) { next = Time.unscaledTime + 0.5f; Refresh(); } } private void OnDestroy() { Index.Remove(registered, this); } } }