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 PocketCartTurret v0.1.1
BepInEx/plugins/PocketCartTurret/PocketCartTurret.dll
Decompiled 12 hours agousing System; using System.Collections; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("artrointel")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Turn pocket carts with mounted cannons or lasers into automatic turrets. Only the host needs the mod; vanilla clients are supported.")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+584d0c089206d8094eaa3b938425123171a8df27")] [assembly: AssemblyProduct("PocketCartTurret")] [assembly: AssemblyTitle("PocketCartTurret")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 PocketCartTurret { internal sealed class DetectionWarning { internal const float Delay = 2f; internal const float LossGrace = 0.5f; private bool _active; private bool _visible; private float _fireAt; private float _lostAt; internal bool FirstShotPending { get; private set; } internal bool KeepItem { get { if (_active) { return FirstShotPending; } return false; } } internal bool Observe(bool eligible, bool visible, float now) { if (!eligible) { Reset(); return false; } if (!visible) { if (_visible) { _lostAt = now; } _visible = false; _fireAt = float.PositiveInfinity; if (_active && now - _lostAt >= 0.5f) { Reset(); } return false; } if (_active && !_visible && now - _lostAt >= 0.5f) { Reset(); } if (_active && !_visible) { _visible = true; _fireAt = now + 2f; bool result = !FirstShotPending; FirstShotPending = true; return result; } _visible = true; if (_active) { return false; } _active = true; FirstShotPending = true; _fireAt = now + 2f; return true; } internal bool CanFire(float now) { if (_active && _visible) { return now >= _fireAt; } return false; } internal bool CanFire(float now, float cycleReadyAt, bool aligned) { return CanFire(now) && now >= cycleReadyAt && aligned; } internal void MarkFired() { FirstShotPending = false; } internal void Reset() { _active = false; _visible = false; FirstShotPending = false; _fireAt = float.PositiveInfinity; _lostAt = 0f; } } internal sealed class MineWarningCarrier : MonoBehaviour { private static Item? _mineItem; private Transform _mount; private PhysGrabObject _physical; private Rigidbody _body; private float _leaseExpiresAt; private bool _disposing; private Collider[] _colliders = Array.Empty<Collider>(); private ItemMine _mine; private bool _armingStarted; internal static bool IsWarning(Component component) { return (Object)(object)component.GetComponent<MineWarningCarrier>() != (Object)null; } internal void RenewLease() { _leaseExpiresAt = Time.time + 5f; } internal static MineWarningCarrier Create(Transform mount) { //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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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) Item val = FindMine(); Vector3 position = mount.position; GameObject val2 = (SemiFunc.IsMultiplayer() ? PhotonNetwork.InstantiateRoomObject(((PrefabRef<GameObject>)(object)val.prefab).ResourcePath, position, mount.rotation, (byte)0, (object[])null) : Object.Instantiate<GameObject>(((PrefabRef<GameObject>)(object)val.prefab).Prefab, position, mount.rotation)); MineWarningCarrier mineWarningCarrier = null; try { mineWarningCarrier = val2.AddComponent<MineWarningCarrier>(); mineWarningCarrier._mount = mount; mineWarningCarrier._physical = val2.GetComponent<PhysGrabObject>(); mineWarningCarrier._body = val2.GetComponent<Rigidbody>(); mineWarningCarrier._mine = val2.GetComponent<ItemMine>(); mineWarningCarrier.RenewLease(); mineWarningCarrier._colliders = val2.GetComponentsInChildren<Collider>(true); mineWarningCarrier.PinToMount(); mineWarningCarrier._mine.triggeredByEnemies = false; mineWarningCarrier._mine.triggeredByPlayers = false; mineWarningCarrier._mine.triggeredByRigidBodies = false; mineWarningCarrier._mine.triggeredByForces = false; val2.GetComponent<PhysGrabObjectImpactDetector>().destroyDisable = true; ItemMineTrigger[] componentsInChildren = val2.GetComponentsInChildren<ItemMineTrigger>(true); foreach (ItemMineTrigger val3 in componentsInChildren) { ((Behaviour)val3).enabled = false; } PhotonView component = val2.GetComponent<PhotonView>(); if (SemiFunc.IsMultiplayer()) { component.RPC("ToggleDisableRPC", (RpcTarget)3, new object[1] { true }); component.RPC("StateSetRPC", (RpcTarget)3, new object[1] { 1 }); } else { mineWarningCarrier._mine.StateSetRPC(1, default(PhotonMessageInfo)); } val2.SetActive(true); return mineWarningCarrier; } catch { if ((Object)(object)mineWarningCarrier != (Object)null) { mineWarningCarrier.Dispose(); } else if (SemiFunc.IsMultiplayer()) { PhotonNetwork.Destroy(val2); } else { Object.Destroy((Object)(object)val2); } throw; } } private IEnumerator Start() { yield return null; if (!_disposing && !((Object)(object)_mount == (Object)null)) { PinToMount(); _physical.Teleport(((Component)this).transform.position, ((Component)this).transform.rotation); StartArming(); } } private void StartArming() { if (!_armingStarted && SemiFunc.IsMasterClientOrSingleplayer()) { _armingStarted = true; VanillaMineArming.Tick(_mine); } } private void Update() { if (_armingStarted && !_disposing && SemiFunc.IsMasterClientOrSingleplayer()) { VanillaMineArming.Tick(_mine); } } private static Item FindMine() { if ((Object)(object)_mineItem != (Object)null) { return _mineItem; } foreach (Item value in StatsManager.instance.itemDictionary.Values) { if ((Object)(object)value != (Object)null && value.prefab != null && ((PrefabRef<GameObject>)(object)value.prefab).IsValid() && (Object)(object)((PrefabRef<GameObject>)(object)value.prefab).Prefab != (Object)null && (Object)(object)((PrefabRef<GameObject>)(object)value.prefab).Prefab.GetComponent<ItemMineExplosive>() != (Object)null) { Sound soundArmingBeep = ((PrefabRef<GameObject>)(object)value.prefab).Prefab.GetComponent<ItemMine>().soundArmingBeep; if (soundArmingBeep == null || soundArmingBeep.Sounds == null || soundArmingBeep.Sounds.Length == 0) { throw new InvalidOperationException("The vanilla Explosive Mine has no arming sound."); } _mineItem = value; return value; } } throw new InvalidOperationException("The vanilla Explosive Mine prefab (ItemMine) was not found."); } private void LateUpdate() { if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } if ((Object)(object)_mount == (Object)null || Time.time >= _leaseExpiresAt) { Dispose(); return; } Collider[] colliders = _colliders; foreach (Collider val in colliders) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } PinToMount(); } private void PinToMount() { //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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) _physical.OverrideKinematic(0.2f); _physical.OverrideGrabDisable(0.2f); _physical.OverrideIndestructible(0.2f); _body.detectCollisions = false; _body.interpolation = (RigidbodyInterpolation)0; Vector3 position = _mount.position; ((Component)this).transform.SetPositionAndRotation(position, _mount.rotation); _body.position = position; _body.rotation = _mount.rotation; } internal void Dispose() { if (_disposing) { return; } bool flag = (Object)(object)GameManager.instance != (Object)null && SemiFunc.IsMultiplayer(); if (!flag || !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient) { _disposing = true; if (flag && PhotonNetwork.InRoom) { PhotonNetwork.Destroy(((Component)this).gameObject); } else { Object.Destroy((Object)(object)((Component)this).gameObject); } } } } [HarmonyPatch(typeof(StatsManager), "ItemFetchName")] internal static class WarningItemStatsPatch { [HarmonyPrefix] private static bool Prefix(ItemAttributes itemAttributes) { if (!((Object)(object)itemAttributes == (Object)null)) { return !MineWarningCarrier.IsWarning((Component)(object)itemAttributes); } return true; } } [HarmonyPatch(typeof(ItemManager), "AddSpawnedItem")] internal static class WarningItemListPatch { [HarmonyPrefix] private static bool Prefix(ItemAttributes item) { if (!((Object)(object)item == (Object)null)) { return !MineWarningCarrier.IsWarning((Component)(object)item); } return true; } } [HarmonyPatch(typeof(PhysGrabObject), "GrabStartedRPC")] internal static class WarningItemGrabPatch { [HarmonyPrefix] private static bool Prefix(PhysGrabObject __instance) { return !MineWarningCarrier.IsWarning((Component)(object)__instance); } } [HarmonyPatch(typeof(ItemEquippable), "RPC_RequestEquip")] internal static class WarningItemEquipPatch { [HarmonyPrefix] private static bool Prefix(ItemEquippable __instance) { return !MineWarningCarrier.IsWarning((Component)(object)__instance); } } [BepInPlugin("artrointel.PocketCartTurret", "PocketCartTurret", "0.1.1")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "artrointel.PocketCartTurret"; public const string PluginName = "PocketCartTurret"; public const string PluginVersion = "0.1.1"; private Harmony? _harmony; internal static ManualLogSource ModLogger { get; private set; } private void Awake() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown ModLogger = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("artrointel.PocketCartTurret"); _harmony.PatchAll(); ModLogger.LogInfo((object)"PocketCartTurret v0.1.1 loaded."); } private void OnDestroy() { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } internal sealed class TurretController : MonoBehaviour { private ItemCartCannonMain _weapon; private ItemBattery _battery; private PhysGrabObject _physical; private PhysGrabObjectImpactDetector _impact; private Transform _muzzle; private float _range; private EnemyParent? _target; private bool _automaticCycle; private bool _failed; private readonly DetectionWarning _warningState = new DetectionWarning(); private MineWarningCarrier? _warningItem; private float _cycleReadyAt; internal bool OwnsAim { get { if (_failed || (Object)(object)GameManager.instance == (Object)null || (Object)(object)RunManager.instance == (Object)null) { return false; } PhysGrabCart val = VanillaWeapon.Cart.Invoke(_impact); return TurretRules.CanAutomate(SemiFunc.IsMasterClientOrSingleplayer(), (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && SemiFunc.RunIsLevel(), (Object)(object)val != (Object)null && val.isSmallCart, _impact.inCart && (Object)(object)val != (Object)null, VanillaWeapon.BatteryBars.Invoke(_battery) > 0 && VanillaWeapon.BatteryLife.Invoke(_battery) > 0f, _physical.playerGrabbing.Count > 0); } } internal void Initialize(ItemCartCannonMain weapon) { _weapon = weapon; _battery = ((Component)this).GetComponent<ItemBattery>(); _physical = ((Component)this).GetComponent<PhysGrabObject>(); _impact = ((Component)this).GetComponent<PhysGrabObjectImpactDetector>(); Rigidbody component = ((Component)this).GetComponent<Rigidbody>(); ItemCartLaser component2 = ((Component)this).GetComponent<ItemCartLaser>(); _muzzle = (((Object)(object)component2 != (Object)null) ? component2.muzzleTransform : weapon.muzzle); _range = (((Object)(object)component2 != (Object)null) ? 15f : 25f); _failed = (Object)(object)_battery == (Object)null || (Object)(object)_physical == (Object)null || (Object)(object)_impact == (Object)null || (Object)(object)component == (Object)null || (Object)(object)_muzzle == (Object)null; if (_failed) { Plugin.ModLogger.LogError((object)("Cannot initialize turret on " + ((Object)this).name + ": a required vanilla component is missing.")); } } internal void BeforeWeaponUpdate() { //IL_005a: 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_00c9: Invalid comparison between Unknown and I4 //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Invalid comparison between Unknown and I4 //IL_00cb: 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_0100: Expected I4, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Invalid comparison between Unknown and I4 //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Invalid comparison between Unknown and I4 if (_failed || !SemiFunc.IsMasterClientOrSingleplayer()) { RemoveWarningItem(); _target = null; _automaticCycle = false; _warningState.Reset(); return; } try { bool ownsAim = OwnsAim; _target = (ownsAim ? FindNearestTarget() : null); state val = VanillaWeapon.State.Invoke(_weapon); if (_warningState.Observe(ownsAim, (Object)(object)_target != (Object)null, Time.time)) { RemoveWarningItem(); _warningItem = MineWarningCarrier.Create(((Component)_weapon).transform); } if (!ownsAim || !_warningState.KeepItem) { RemoveWarningItem(); } else { _warningItem?.RenewLease(); } if (_automaticCycle) { if ((int)val == 1 || (int)val == 0) { _automaticCycle = false; } else { if (!ownsAim || (Object)(object)_target == (Object)null || ((int)val == 3 && !CurrentRayHits(_target))) { int? num = TurretRules.StopState((int)val); if (num.HasValue) { VanillaWeaponState.Set(_weapon, num.Value); } return; } if ((int)val == 2) { if (PrepareAutomaticShot()) { VanillaWeaponState.Set(_weapon, 3); } return; } } } if (ownsAim && (int)val == 1 && (Object)(object)_target != (Object)null) { _automaticCycle = true; _cycleReadyAt = (_warningState.FirstShotPending ? Time.time : (Time.time + _weapon.shootBuildUpTime)); VanillaWeaponState.Set(_weapon, 2); } } catch (Exception exception) { DisableAutomation(exception); } } internal bool PrepareAutomaticShot() { if (!_automaticCycle) { return true; } if (!OwnsAim || (Object)(object)_target == (Object)null || !_warningState.CanFire(Time.time, _cycleReadyAt, CurrentRayHits(_target))) { return false; } RemoveWarningItem(); _warningState.MarkFired(); return true; } private void RemoveWarningItem() { if ((Object)(object)_warningItem != (Object)null) { _warningItem.Dispose(); _warningItem = null; } } internal void DisableAutomation(Exception exception) { _failed = true; Plugin.ModLogger.LogError((object)$"Turret disabled on {((Object)this).name}; vanilla behavior retained: {exception}"); try { StopAutomaticCycle(); } catch (Exception arg) { _automaticCycle = false; _target = null; Plugin.ModLogger.LogError((object)$"Could not cancel the automatic firing cycle: {arg}"); } } internal void BeforeVanillaGrab() { //IL_0066: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0084: 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_00a9: 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_00e5: Unknown result type (might be due to invalid IL or missing references) if (!OwnsAim || (Object)(object)_target == (Object)null || (Object)(object)_weapon.currentCorrector == (Object)null) { return; } Enemy val = VanillaWeapon.Enemy.Invoke(_target); if (!((Object)(object)val == (Object)null) && IsLive(_target, val)) { Transform transform = _weapon.currentCorrector.transform; Quaternion rotation = transform.rotation; if (TryAimYaw(AimPoint(val), _muzzle.position, _muzzle.forward, out var yaw)) { float num = ((Component)this).transform.eulerAngles.y + yaw; float num2 = Mathf.Clamp(Mathf.DeltaAngle(((Quaternion)(ref rotation)).eulerAngles.y, num), -180f * Time.fixedDeltaTime, 180f * Time.fixedDeltaTime); transform.rotation = Quaternion.AngleAxis(num2, Vector3.up) * rotation; } } } private EnemyParent? FindNearestTarget() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)EnemyDirector.instance == (Object)null) { return null; } EnemyParent result = null; float bestDistanceSquared = float.PositiveInfinity; int bestId = int.MaxValue; foreach (EnemyParent item in EnemyDirector.instance.enemiesSpawned) { if ((Object)(object)item == (Object)null) { continue; } Enemy enemy = VanillaWeapon.Enemy.Invoke(item); if (IsLive(item, enemy)) { Vector3 val = AimPoint(enemy); Vector3 val2 = val - _muzzle.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; int instanceID = ((Object)item).GetInstanceID(); if (TurretRules.InRange(sqrMagnitude, _range) && TurretRules.PreferCandidate(sqrMagnitude, instanceID, bestDistanceSquared, bestId) && SweptRayHits(item, val)) { result = item; bestDistanceSquared = sqrMagnitude; bestId = instanceID; } } } return result; } private static bool IsLive(EnemyParent parent, Enemy enemy) { if ((Object)(object)enemy == (Object)null || !VanillaWeapon.Spawned.Invoke(parent) || !((Behaviour)enemy).isActiveAndEnabled) { return false; } EnemyHealth component = ((Component)enemy).GetComponent<EnemyHealth>(); if (!((Object)(object)component == (Object)null)) { return !VanillaWeapon.Dead.Invoke(component); } return true; } private static Vector3 AimPoint(Enemy enemy) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)enemy.CenterTransform != (Object)null)) { return ((Component)enemy).transform.position; } return enemy.CenterTransform.position; } private bool SweptRayHits(EnemyParent target, Vector3 point) { //IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) Vector3 position = _muzzle.position; Vector3 forward = _muzzle.forward; if (!TryAimYaw(point, position, forward, out var yaw)) { return false; } Quaternion val = Quaternion.AngleAxis(yaw, Vector3.up); Vector3 origin = ((Component)this).transform.position + val * (position - ((Component)this).transform.position); return RayHits(target, origin, val * forward); } private bool TryAimYaw(Vector3 point, Vector3 origin, Vector3 forward, out float yaw) { //IL_0000: 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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0042: Unknown result type (might be due to invalid IL or missing references) Vector3 val = point - ((Component)this).transform.position; Vector3 val2 = origin - ((Component)this).transform.position; return TurretRules.TryAimYaw(forward.x, forward.z, val2.x, val2.z, val.x, val.z, out yaw); } private bool CurrentRayHits(EnemyParent target) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) if (IsLive(target, VanillaWeapon.Enemy.Invoke(target))) { Vector3 val = AimPoint(VanillaWeapon.Enemy.Invoke(target)) - _muzzle.position; if (TurretRules.InRange(((Vector3)(ref val)).sqrMagnitude, _range)) { return RayHits(target, _muzzle.position, _muzzle.forward); } } return false; } private bool RayHits(EnemyParent target, Vector3 origin, Vector3 direction) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) int num = LayerMask.op_Implicit(SemiFunc.LayerMaskGetVisionObstruct()) | LayerMask.GetMask(new string[1] { "Enemy" }); RaycastHit[] array = Physics.RaycastAll(origin, direction, _range * 0.7f, num, (QueryTriggerInteraction)2); float num2 = float.PositiveInfinity; Collider val = null; RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val2 = array2[i]; if (!((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<PhysGrabObject>() == (Object)(object)_physical) && !(((RaycastHit)(ref val2)).distance >= num2) && !((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponentInParent<MineWarningCarrier>() != (Object)null) && (!((RaycastHit)(ref val2)).collider.isTrigger || ((Component)((RaycastHit)(ref val2)).collider).gameObject.layer == LayerMask.NameToLayer("Enemy"))) { num2 = ((RaycastHit)(ref val2)).distance; val = ((RaycastHit)(ref val2)).collider; } } if ((Object)(object)val != (Object)null) { return (Object)(object)((Component)val).GetComponentInParent<EnemyParent>() == (Object)(object)target; } return false; } private void StopAutomaticCycle() { RemoveWarningItem(); _warningState.Reset(); if (_automaticCycle && (Object)(object)_weapon != (Object)null && (Object)(object)GameManager.instance != (Object)null && SemiFunc.IsMasterClientOrSingleplayer()) { int? num = TurretRules.StopState((int)VanillaWeapon.State.Invoke(_weapon)); if (num.HasValue) { VanillaWeaponState.Set(_weapon, num.Value); } } _automaticCycle = false; _target = null; } private void OnDisable() { StopAutomaticCycle(); } } internal static class TurretRules { internal const float CannonRange = 25f; internal const float LaserRange = 15f; internal const float DetectionRatio = 0.7f; internal const float TurnSpeedDegrees = 180f; internal static bool CanAutomate(bool host, bool missionReady, bool smallCart, bool mounted, bool powered, bool weaponHeld) { if (host && missionReady && smallCart && mounted && powered) { return !weaponHeld; } return false; } internal static bool InRange(float distanceSquared, float weaponRange) { if (distanceSquared >= 0f) { return distanceSquared <= weaponRange * weaponRange * 0.7f * 0.7f; } return false; } internal static bool PreferCandidate(float distanceSquared, int id, float bestDistanceSquared, int bestId) { if (!(distanceSquared < bestDistanceSquared)) { if (distanceSquared == bestDistanceSquared) { return id < bestId; } return false; } return true; } internal static float YawDelta(float forwardX, float forwardZ, float offsetX, float offsetZ) { double y = forwardZ * offsetX - forwardX * offsetZ; double x = forwardX * offsetX + forwardZ * offsetZ; return (float)(Math.Atan2(y, x) * (180.0 / Math.PI)); } internal static bool TryAimYaw(float forwardX, float forwardZ, float muzzleX, float muzzleZ, float targetX, float targetZ, out float yaw) { yaw = 0f; double num = Math.Sqrt(forwardX * forwardX + forwardZ * forwardZ); double num2 = Math.Sqrt(targetX * targetX + targetZ * targetZ); if (num < 0.0001 || num2 < 0.0001) { return false; } double num3 = (double)(forwardZ * muzzleX - forwardX * muzzleZ) / num; if (Math.Abs(num3) >= num2) { return false; } yaw = YawDelta(forwardX, forwardZ, targetX, targetZ) - (float)(Math.Asin(num3 / num2) * (180.0 / Math.PI)); double num4 = (double)(forwardX * muzzleX + forwardZ * muzzleZ) / num; return Math.Sqrt(num2 * num2 - num3 * num3) > num4; } internal static int? StopState(int state) { return state switch { 3 => 4, 2 => 1, _ => null, }; } } internal static class VanillaWeapon { internal static readonly FieldRef<ItemCartCannonMain, state> State = AccessTools.FieldRefAccess<ItemCartCannonMain, state>("stateCurrent"); internal static readonly FieldRef<PhysGrabObjectImpactDetector, PhysGrabCart> Cart = AccessTools.FieldRefAccess<PhysGrabObjectImpactDetector, PhysGrabCart>("currentCart"); internal static readonly FieldRef<ItemBattery, int> BatteryBars = AccessTools.FieldRefAccess<ItemBattery, int>("batteryLifeInt"); internal static readonly FieldRef<ItemBattery, float> BatteryLife = AccessTools.FieldRefAccess<ItemBattery, float>("batteryLife"); internal static readonly FieldRef<EnemyParent, Enemy> Enemy = AccessTools.FieldRefAccess<EnemyParent, Enemy>("Enemy"); internal static readonly FieldRef<EnemyParent, bool> Spawned = AccessTools.FieldRefAccess<EnemyParent, bool>("Spawned"); internal static readonly FieldRef<EnemyHealth, bool> Dead = AccessTools.FieldRefAccess<EnemyHealth, bool>("dead"); } [HarmonyPatch(typeof(ItemCartCannonMain), "StateSet")] internal static class VanillaWeaponState { [MethodImpl(MethodImplOptions.NoInlining)] [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] internal static void Set(ItemCartCannonMain instance, int state) { throw new NotSupportedException("Harmony reverse patch was not installed."); } } [HarmonyPatch(typeof(ItemMine), "Start")] internal static class WarningMineStartPatch { [HarmonyPostfix] private static void Postfix(ItemMine __instance) { if ((Object)(object)((Component)__instance).GetComponent<MineWarningCarrier>() != (Object)null) { ((Behaviour)__instance).enabled = false; } } } [HarmonyPatch(typeof(ItemMine), "StateSetRPC")] internal static class WarningMineStatePatch { [HarmonyPrefix] private static bool Prefix(ItemMine __instance, int newState) { if (MineWarningCarrier.IsWarning((Component)(object)__instance)) { return newState == 1; } return true; } } [HarmonyPatch(typeof(ItemMine), "StateSet")] internal static class WarningMineTransitionPatch { [HarmonyPrefix] private static bool Prefix(ItemMine __instance) { return !MineWarningCarrier.IsWarning((Component)(object)__instance); } } [HarmonyPatch(typeof(ItemMine), "DestroyMine")] internal static class WarningMineDestroyPatch { [HarmonyPrefix] private static bool Prefix(ItemMine __instance) { return !MineWarningCarrier.IsWarning((Component)(object)__instance); } } [HarmonyPatch(typeof(ItemMine), "TriggeredRPC")] internal static class WarningMineTriggerPatch { [HarmonyPrefix] private static bool Prefix(ItemMine __instance) { return !MineWarningCarrier.IsWarning((Component)(object)__instance); } } [HarmonyPatch(typeof(ItemMineExplosive), "OnTriggered")] internal static class WarningMineExplosionPatch { [HarmonyPrefix] private static bool Prefix(ItemMineExplosive __instance) { return !MineWarningCarrier.IsWarning((Component)(object)__instance); } } [HarmonyPatch(typeof(ItemMine), "StateArming")] internal static class VanillaMineArming { [MethodImpl(MethodImplOptions.NoInlining)] [HarmonyReversePatch(/*Could not decode attribute arguments.*/)] internal static void Tick(ItemMine instance) { throw new NotSupportedException("Harmony reverse patch was not installed."); } } [HarmonyPatch(typeof(ItemCartCannonMain), "Start")] internal static class WeaponStartPatch { [HarmonyPostfix] private static void Postfix(ItemCartCannonMain __instance) { if (SemiFunc.IsMasterClientOrSingleplayer() && ((Object)(object)((Component)__instance).GetComponent<ItemCartCannon>() != (Object)null || (Object)(object)((Component)__instance).GetComponent<ItemCartLaser>() != (Object)null) && (Object)(object)((Component)__instance).GetComponent<TurretController>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<TurretController>().Initialize(__instance); } } } [HarmonyPatch(typeof(ItemCartCannonMain), "Update")] internal static class WeaponUpdatePatch { [HarmonyPrefix] private static void Prefix(ItemCartCannonMain __instance) { ((Component)__instance).GetComponent<TurretController>()?.BeforeWeaponUpdate(); } } [HarmonyPatch(typeof(ItemCartCannonMain), "GrabLogic")] internal static class WeaponGrabPatch { [HarmonyPrefix] private static void Prefix(ItemCartCannonMain __instance) { TurretController component = ((Component)__instance).GetComponent<TurretController>(); try { component?.BeforeVanillaGrab(); } catch (Exception exception) { component?.DisableAutomation(exception); } } } [HarmonyPatch(typeof(ItemCartCannonMain), "StateSet")] internal static class WeaponShotGatePatch { [HarmonyPrefix] private static bool Prefix(ItemCartCannonMain __instance, int state) { if (state != 3 || !SemiFunc.IsMasterClientOrSingleplayer()) { return true; } TurretController component = ((Component)__instance).GetComponent<TurretController>(); if (!((Object)(object)component == (Object)null)) { return component.PrepareAutomaticShot(); } return true; } } }